Merge pull request #39 from Dark-Alex-17/alternative-keymappings
Alternative keymappings
This commit is contained in:
@@ -98,7 +98,7 @@ mod tests {
|
|||||||
assert!(!app.is_loading);
|
assert!(!app.is_loading);
|
||||||
assert!(!app.is_routing);
|
assert!(!app.is_routing);
|
||||||
assert!(!app.should_refresh);
|
assert!(!app.should_refresh);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app.cli_mode);
|
assert!(!app.cli_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,7 +118,7 @@ mod tests {
|
|||||||
assert!(!app.is_loading);
|
assert!(!app.is_loading);
|
||||||
assert!(!app.is_routing);
|
assert!(!app.is_routing);
|
||||||
assert!(!app.should_refresh);
|
assert!(!app.should_refresh);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app.cli_mode);
|
assert!(!app.cli_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+61
-1
@@ -44,128 +44,188 @@ generate_keybindings! {
|
|||||||
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
|
||||||
pub struct KeyBinding {
|
pub struct KeyBinding {
|
||||||
pub key: Key,
|
pub key: Key,
|
||||||
|
pub alt: Option<Key>,
|
||||||
pub desc: &'static str,
|
pub desc: &'static str,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DEFAULT_KEYBINDINGS: KeyBindings = KeyBindings {
|
pub const DEFAULT_KEYBINDINGS: KeyBindings = KeyBindings {
|
||||||
add: KeyBinding {
|
add: KeyBinding {
|
||||||
key: Key::Char('a'),
|
key: Key::Char('a'),
|
||||||
|
alt: None,
|
||||||
desc: "add",
|
desc: "add",
|
||||||
},
|
},
|
||||||
up: KeyBinding {
|
up: KeyBinding {
|
||||||
key: Key::Up,
|
key: Key::Up,
|
||||||
|
alt: Some(Key::Char('k')),
|
||||||
desc: "up",
|
desc: "up",
|
||||||
},
|
},
|
||||||
down: KeyBinding {
|
down: KeyBinding {
|
||||||
key: Key::Down,
|
key: Key::Down,
|
||||||
|
alt: Some(Key::Char('j')),
|
||||||
desc: "down",
|
desc: "down",
|
||||||
},
|
},
|
||||||
left: KeyBinding {
|
left: KeyBinding {
|
||||||
key: Key::Left,
|
key: Key::Left,
|
||||||
|
alt: Some(Key::Char('h')),
|
||||||
desc: "left",
|
desc: "left",
|
||||||
},
|
},
|
||||||
right: KeyBinding {
|
right: KeyBinding {
|
||||||
key: Key::Right,
|
key: Key::Right,
|
||||||
|
alt: Some(Key::Char('l')),
|
||||||
desc: "right",
|
desc: "right",
|
||||||
},
|
},
|
||||||
backspace: KeyBinding {
|
backspace: KeyBinding {
|
||||||
key: Key::Backspace,
|
key: Key::Backspace,
|
||||||
|
alt: Some(Key::Ctrl('h')),
|
||||||
desc: "backspace",
|
desc: "backspace",
|
||||||
},
|
},
|
||||||
next_servarr: KeyBinding {
|
next_servarr: KeyBinding {
|
||||||
key: Key::Tab,
|
key: Key::Tab,
|
||||||
|
alt: None,
|
||||||
desc: "next servarr",
|
desc: "next servarr",
|
||||||
},
|
},
|
||||||
previous_servarr: KeyBinding {
|
previous_servarr: KeyBinding {
|
||||||
key: Key::BackTab,
|
key: Key::BackTab,
|
||||||
|
alt: None,
|
||||||
desc: "previous servarr",
|
desc: "previous servarr",
|
||||||
},
|
},
|
||||||
clear: KeyBinding {
|
clear: KeyBinding {
|
||||||
key: Key::Char('c'),
|
key: Key::Char('c'),
|
||||||
|
alt: None,
|
||||||
desc: "clear",
|
desc: "clear",
|
||||||
},
|
},
|
||||||
auto_search: KeyBinding {
|
auto_search: KeyBinding {
|
||||||
key: Key::Char('S'),
|
key: Key::Char('S'),
|
||||||
|
alt: None,
|
||||||
desc: "auto search",
|
desc: "auto search",
|
||||||
},
|
},
|
||||||
search: KeyBinding {
|
search: KeyBinding {
|
||||||
key: Key::Char('s'),
|
key: Key::Char('s'),
|
||||||
|
alt: None,
|
||||||
desc: "search",
|
desc: "search",
|
||||||
},
|
},
|
||||||
settings: KeyBinding {
|
settings: KeyBinding {
|
||||||
key: Key::Char('S'),
|
key: Key::Char('S'),
|
||||||
|
alt: None,
|
||||||
desc: "settings",
|
desc: "settings",
|
||||||
},
|
},
|
||||||
filter: KeyBinding {
|
filter: KeyBinding {
|
||||||
key: Key::Char('f'),
|
key: Key::Char('f'),
|
||||||
|
alt: None,
|
||||||
desc: "filter",
|
desc: "filter",
|
||||||
},
|
},
|
||||||
sort: KeyBinding {
|
sort: KeyBinding {
|
||||||
key: Key::Char('o'),
|
key: Key::Char('o'),
|
||||||
|
alt: None,
|
||||||
desc: "sort",
|
desc: "sort",
|
||||||
},
|
},
|
||||||
edit: KeyBinding {
|
edit: KeyBinding {
|
||||||
key: Key::Char('e'),
|
key: Key::Char('e'),
|
||||||
|
alt: None,
|
||||||
desc: "edit",
|
desc: "edit",
|
||||||
},
|
},
|
||||||
events: KeyBinding {
|
events: KeyBinding {
|
||||||
key: Key::Char('e'),
|
key: Key::Char('e'),
|
||||||
|
alt: None,
|
||||||
desc: "events",
|
desc: "events",
|
||||||
},
|
},
|
||||||
logs: KeyBinding {
|
logs: KeyBinding {
|
||||||
key: Key::Char('l'),
|
key: Key::Char('L'),
|
||||||
|
alt: None,
|
||||||
desc: "logs",
|
desc: "logs",
|
||||||
},
|
},
|
||||||
tasks: KeyBinding {
|
tasks: KeyBinding {
|
||||||
key: Key::Char('t'),
|
key: Key::Char('t'),
|
||||||
|
alt: None,
|
||||||
desc: "tasks",
|
desc: "tasks",
|
||||||
},
|
},
|
||||||
test: KeyBinding {
|
test: KeyBinding {
|
||||||
key: Key::Char('t'),
|
key: Key::Char('t'),
|
||||||
|
alt: None,
|
||||||
desc: "test",
|
desc: "test",
|
||||||
},
|
},
|
||||||
test_all: KeyBinding {
|
test_all: KeyBinding {
|
||||||
key: Key::Char('T'),
|
key: Key::Char('T'),
|
||||||
|
alt: None,
|
||||||
desc: "test all",
|
desc: "test all",
|
||||||
},
|
},
|
||||||
toggle_monitoring: KeyBinding {
|
toggle_monitoring: KeyBinding {
|
||||||
key: Key::Char('m'),
|
key: Key::Char('m'),
|
||||||
|
alt: None,
|
||||||
desc: "toggle monitoring",
|
desc: "toggle monitoring",
|
||||||
},
|
},
|
||||||
refresh: KeyBinding {
|
refresh: KeyBinding {
|
||||||
key: Key::Ctrl('r'),
|
key: Key::Ctrl('r'),
|
||||||
|
alt: None,
|
||||||
desc: "refresh",
|
desc: "refresh",
|
||||||
},
|
},
|
||||||
update: KeyBinding {
|
update: KeyBinding {
|
||||||
key: Key::Char('u'),
|
key: Key::Char('u'),
|
||||||
|
alt: None,
|
||||||
desc: "update",
|
desc: "update",
|
||||||
},
|
},
|
||||||
home: KeyBinding {
|
home: KeyBinding {
|
||||||
key: Key::Home,
|
key: Key::Home,
|
||||||
|
alt: None,
|
||||||
desc: "home",
|
desc: "home",
|
||||||
},
|
},
|
||||||
end: KeyBinding {
|
end: KeyBinding {
|
||||||
key: Key::End,
|
key: Key::End,
|
||||||
|
alt: None,
|
||||||
desc: "end",
|
desc: "end",
|
||||||
},
|
},
|
||||||
delete: KeyBinding {
|
delete: KeyBinding {
|
||||||
key: Key::Delete,
|
key: Key::Delete,
|
||||||
|
alt: None,
|
||||||
desc: "delete",
|
desc: "delete",
|
||||||
},
|
},
|
||||||
submit: KeyBinding {
|
submit: KeyBinding {
|
||||||
key: Key::Enter,
|
key: Key::Enter,
|
||||||
|
alt: None,
|
||||||
desc: "submit",
|
desc: "submit",
|
||||||
},
|
},
|
||||||
confirm: KeyBinding {
|
confirm: KeyBinding {
|
||||||
key: Key::Ctrl('s'),
|
key: Key::Ctrl('s'),
|
||||||
|
alt: None,
|
||||||
desc: "submit",
|
desc: "submit",
|
||||||
},
|
},
|
||||||
quit: KeyBinding {
|
quit: KeyBinding {
|
||||||
key: Key::Char('q'),
|
key: Key::Char('q'),
|
||||||
|
alt: None,
|
||||||
desc: "quit",
|
desc: "quit",
|
||||||
},
|
},
|
||||||
esc: KeyBinding {
|
esc: KeyBinding {
|
||||||
key: Key::Esc,
|
key: Key::Esc,
|
||||||
|
alt: None,
|
||||||
desc: "close",
|
desc: "close",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! matches_key {
|
||||||
|
($binding:ident, $key:expr) => {
|
||||||
|
$crate::app::key_binding::DEFAULT_KEYBINDINGS.$binding.key == $key
|
||||||
|
|| ($crate::app::key_binding::DEFAULT_KEYBINDINGS
|
||||||
|
.$binding
|
||||||
|
.alt
|
||||||
|
.is_some()
|
||||||
|
&& $crate::app::key_binding::DEFAULT_KEYBINDINGS
|
||||||
|
.$binding
|
||||||
|
.alt
|
||||||
|
.unwrap()
|
||||||
|
== $key)
|
||||||
|
};
|
||||||
|
($binding:ident, $key:expr, $ignore_special_keys:expr) => {
|
||||||
|
$crate::app::key_binding::DEFAULT_KEYBINDINGS.$binding.key == $key
|
||||||
|
|| !$ignore_special_keys
|
||||||
|
&& ($crate::app::key_binding::DEFAULT_KEYBINDINGS
|
||||||
|
.$binding
|
||||||
|
.alt
|
||||||
|
.is_some()
|
||||||
|
&& $crate::app::key_binding::DEFAULT_KEYBINDINGS
|
||||||
|
.$binding
|
||||||
|
.alt
|
||||||
|
.unwrap()
|
||||||
|
== $key)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,44 +5,85 @@ mod test {
|
|||||||
|
|
||||||
use crate::app::key_binding::{KeyBinding, DEFAULT_KEYBINDINGS};
|
use crate::app::key_binding::{KeyBinding, DEFAULT_KEYBINDINGS};
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
|
use crate::matches_key;
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
#[case(DEFAULT_KEYBINDINGS.add, Key::Char('a'), "add")]
|
#[case(DEFAULT_KEYBINDINGS.add, Key::Char('a'), None, "add")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.up, Key::Up, "up")]
|
#[case(DEFAULT_KEYBINDINGS.up, Key::Up, Some(Key::Char('k')), "up")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.down, Key::Down, "down")]
|
#[case(DEFAULT_KEYBINDINGS.down, Key::Down, Some(Key::Char('j')), "down")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.left, Key::Left, "left")]
|
#[case(DEFAULT_KEYBINDINGS.left, Key::Left, Some(Key::Char('h')), "left")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.right, Key::Right, "right")]
|
#[case(DEFAULT_KEYBINDINGS.right, Key::Right, Some(Key::Char('l')), "right")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.backspace, Key::Backspace, "backspace")]
|
#[case(DEFAULT_KEYBINDINGS.backspace, Key::Backspace, Some(Key::Ctrl('h')), "backspace")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.next_servarr, Key::Tab, "next servarr")]
|
#[case(DEFAULT_KEYBINDINGS.next_servarr, Key::Tab, None, "next servarr")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.previous_servarr, Key::BackTab, "previous servarr")]
|
#[case(DEFAULT_KEYBINDINGS.previous_servarr, Key::BackTab, None, "previous servarr")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.clear, Key::Char('c'), "clear")]
|
#[case(DEFAULT_KEYBINDINGS.clear, Key::Char('c'), None, "clear")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.auto_search, Key::Char('S'), "auto search")]
|
#[case(DEFAULT_KEYBINDINGS.auto_search, Key::Char('S'), None, "auto search")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.search, Key::Char('s'), "search")]
|
#[case(DEFAULT_KEYBINDINGS.search, Key::Char('s'), None, "search")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.settings, Key::Char('S'), "settings")]
|
#[case(DEFAULT_KEYBINDINGS.settings, Key::Char('S'), None, "settings")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.filter, Key::Char('f'), "filter")]
|
#[case(DEFAULT_KEYBINDINGS.filter, Key::Char('f'), None, "filter")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.sort, Key::Char('o'), "sort")]
|
#[case(DEFAULT_KEYBINDINGS.sort, Key::Char('o'), None, "sort")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.edit, Key::Char('e'), "edit")]
|
#[case(DEFAULT_KEYBINDINGS.edit, Key::Char('e'), None, "edit")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.events, Key::Char('e'), "events")]
|
#[case(DEFAULT_KEYBINDINGS.events, Key::Char('e'), None, "events")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.logs, Key::Char('l'), "logs")]
|
#[case(DEFAULT_KEYBINDINGS.logs, Key::Char('L'), None, "logs")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.tasks, Key::Char('t'), "tasks")]
|
#[case(DEFAULT_KEYBINDINGS.tasks, Key::Char('t'), None, "tasks")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.test, Key::Char('t'), "test")]
|
#[case(DEFAULT_KEYBINDINGS.test, Key::Char('t'), None, "test")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.test_all, Key::Char('T'), "test all")]
|
#[case(DEFAULT_KEYBINDINGS.test_all, Key::Char('T'), None, "test all")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.toggle_monitoring, Key::Char('m'), "toggle monitoring")]
|
#[case(DEFAULT_KEYBINDINGS.toggle_monitoring, Key::Char('m'), None, "toggle monitoring")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.refresh, Key::Ctrl('r'), "refresh")]
|
#[case(DEFAULT_KEYBINDINGS.refresh, Key::Ctrl('r'), None, "refresh")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.update, Key::Char('u'), "update")]
|
#[case(DEFAULT_KEYBINDINGS.update, Key::Char('u'), None, "update")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.home, Key::Home, "home")]
|
#[case(DEFAULT_KEYBINDINGS.home, Key::Home, None, "home")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.end, Key::End, "end")]
|
#[case(DEFAULT_KEYBINDINGS.end, Key::End, None, "end")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.delete, Key::Delete, "delete")]
|
#[case(DEFAULT_KEYBINDINGS.delete, Key::Delete, None, "delete")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.submit, Key::Enter, "submit")]
|
#[case(DEFAULT_KEYBINDINGS.submit, Key::Enter, None, "submit")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.confirm, Key::Ctrl('s'), "submit")]
|
#[case(DEFAULT_KEYBINDINGS.confirm, Key::Ctrl('s'), None, "submit")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.quit, Key::Char('q'), "quit")]
|
#[case(DEFAULT_KEYBINDINGS.quit, Key::Char('q'), None, "quit")]
|
||||||
#[case(DEFAULT_KEYBINDINGS.esc, Key::Esc, "close")]
|
#[case(DEFAULT_KEYBINDINGS.esc, Key::Esc, None, "close")]
|
||||||
fn test_default_key_bindings_and_descriptions(
|
fn test_default_key_bindings_and_descriptions(
|
||||||
#[case] key_binding: KeyBinding,
|
#[case] key_binding: KeyBinding,
|
||||||
#[case] expected_key: Key,
|
#[case] expected_key: Key,
|
||||||
|
#[case] expected_alt_key: Option<Key>,
|
||||||
#[case] expected_desc: &str,
|
#[case] expected_desc: &str,
|
||||||
) {
|
) {
|
||||||
assert_eq!(key_binding.key, expected_key);
|
assert_eq!(key_binding.key, expected_key);
|
||||||
|
assert_eq!(key_binding.alt, expected_alt_key);
|
||||||
assert_str_eq!(key_binding.desc, expected_desc);
|
assert_str_eq!(key_binding.desc, expected_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_matches_key_macro() {
|
||||||
|
let key = Key::Char('t');
|
||||||
|
|
||||||
|
assert!(matches_key!(test, key));
|
||||||
|
assert!(!matches_key!(test, Key::Char('T')));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_matches_key_macro_with_alt_keybinding() {
|
||||||
|
let alt_key = Key::Char('k');
|
||||||
|
let key = Key::Up;
|
||||||
|
|
||||||
|
assert!(matches_key!(up, key));
|
||||||
|
assert!(matches_key!(up, alt_key));
|
||||||
|
assert!(!matches_key!(up, Key::Char('t')));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_matches_key_macro_with_alt_keybinding_uses_alt_key_when_ignore_special_keys_is_false() {
|
||||||
|
let alt_key = Key::Char('k');
|
||||||
|
let key = Key::Up;
|
||||||
|
|
||||||
|
assert!(matches_key!(up, key, false));
|
||||||
|
assert!(matches_key!(up, alt_key, false));
|
||||||
|
assert!(!matches_key!(up, Key::Char('t'), false));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_matches_key_macro_with_alt_keybinding_ignores_alt_key_when_ignore_special_keys_is_true() {
|
||||||
|
let alt_key = Key::Char('k');
|
||||||
|
let key = Key::Up;
|
||||||
|
|
||||||
|
assert!(matches_key!(up, key, true));
|
||||||
|
assert!(!matches_key!(up, alt_key, true));
|
||||||
|
assert!(!matches_key!(up, Key::Char('t'), true));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -39,7 +39,7 @@ pub struct App<'a> {
|
|||||||
pub is_routing: bool,
|
pub is_routing: bool,
|
||||||
pub is_loading: bool,
|
pub is_loading: bool,
|
||||||
pub should_refresh: bool,
|
pub should_refresh: bool,
|
||||||
pub should_ignore_quit_key: bool,
|
pub ignore_special_keys_for_textbox_input: bool,
|
||||||
pub cli_mode: bool,
|
pub cli_mode: bool,
|
||||||
pub data: Data<'a>,
|
pub data: Data<'a>,
|
||||||
}
|
}
|
||||||
@@ -224,7 +224,7 @@ impl Default for App<'_> {
|
|||||||
is_loading: false,
|
is_loading: false,
|
||||||
is_routing: false,
|
is_routing: false,
|
||||||
should_refresh: false,
|
should_refresh: false,
|
||||||
should_ignore_quit_key: false,
|
ignore_special_keys_for_textbox_input: false,
|
||||||
cli_mode: false,
|
cli_mode: false,
|
||||||
data: Data::default(),
|
data: Data::default(),
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-23
@@ -1,9 +1,9 @@
|
|||||||
use radarr_handlers::RadarrHandler;
|
use radarr_handlers::RadarrHandler;
|
||||||
use sonarr_handlers::SonarrHandler;
|
use sonarr_handlers::SonarrHandler;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
|
use crate::matches_key;
|
||||||
use crate::models::{HorizontallyScrollableText, Route};
|
use crate::models::{HorizontallyScrollableText, Route};
|
||||||
|
|
||||||
mod radarr_handlers;
|
mod radarr_handlers;
|
||||||
@@ -22,40 +22,42 @@ pub trait KeyEventHandler<'a, 'b, T: Into<Route> + Copy> {
|
|||||||
fn handle_key_event(&mut self) {
|
fn handle_key_event(&mut self) {
|
||||||
let key = self.get_key();
|
let key = self.get_key();
|
||||||
match key {
|
match key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.up.key => {
|
_ if matches_key!(up, key, self.ignore_special_keys()) => {
|
||||||
if self.is_ready() {
|
if self.is_ready() {
|
||||||
self.handle_scroll_up();
|
self.handle_scroll_up();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.down.key => {
|
_ if matches_key!(down, key, self.ignore_special_keys()) => {
|
||||||
if self.is_ready() {
|
if self.is_ready() {
|
||||||
self.handle_scroll_down();
|
self.handle_scroll_down();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.home.key => {
|
_ if matches_key!(home, key) => {
|
||||||
if self.is_ready() {
|
if self.is_ready() {
|
||||||
self.handle_home();
|
self.handle_home();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.end.key => {
|
_ if matches_key!(end, key) => {
|
||||||
if self.is_ready() {
|
if self.is_ready() {
|
||||||
self.handle_end();
|
self.handle_end();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.delete.key => {
|
_ if matches_key!(delete, key) => {
|
||||||
if self.is_ready() {
|
if self.is_ready() {
|
||||||
self.handle_delete();
|
self.handle_delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.left.key || key == DEFAULT_KEYBINDINGS.right.key => {
|
_ if matches_key!(left, key, self.ignore_special_keys())
|
||||||
|
|| matches_key!(right, key, self.ignore_special_keys()) =>
|
||||||
|
{
|
||||||
self.handle_left_right_action()
|
self.handle_left_right_action()
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.submit.key => {
|
_ if matches_key!(submit, key) => {
|
||||||
if self.is_ready() {
|
if self.is_ready() {
|
||||||
self.handle_submit();
|
self.handle_submit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.esc.key => self.handle_esc(),
|
_ if matches_key!(esc, key) => self.handle_esc(),
|
||||||
_ => {
|
_ => {
|
||||||
if self.is_ready() {
|
if self.is_ready() {
|
||||||
self.handle_char_key_event();
|
self.handle_char_key_event();
|
||||||
@@ -71,6 +73,7 @@ pub trait KeyEventHandler<'a, 'b, T: Into<Route> + Copy> {
|
|||||||
fn accepts(active_block: T) -> bool;
|
fn accepts(active_block: T) -> bool;
|
||||||
fn new(key: Key, app: &'a mut App<'b>, active_block: T, context: Option<T>) -> Self;
|
fn new(key: Key, app: &'a mut App<'b>, active_block: T, context: Option<T>) -> Self;
|
||||||
fn get_key(&self) -> Key;
|
fn get_key(&self) -> Key;
|
||||||
|
fn ignore_special_keys(&self) -> bool;
|
||||||
fn is_ready(&self) -> bool;
|
fn is_ready(&self) -> bool;
|
||||||
fn handle_scroll_up(&mut self);
|
fn handle_scroll_up(&mut self);
|
||||||
fn handle_scroll_down(&mut self);
|
fn handle_scroll_down(&mut self);
|
||||||
@@ -84,12 +87,12 @@ pub trait KeyEventHandler<'a, 'b, T: Into<Route> + Copy> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_events(key: Key, app: &mut App<'_>) {
|
pub fn handle_events(key: Key, app: &mut App<'_>) {
|
||||||
if key == DEFAULT_KEYBINDINGS.next_servarr.key {
|
if matches_key!(next_servarr, key) {
|
||||||
app.reset();
|
app.reset();
|
||||||
app.server_tabs.next();
|
app.server_tabs.next();
|
||||||
app.pop_and_push_navigation_stack(app.server_tabs.get_active_route());
|
app.pop_and_push_navigation_stack(app.server_tabs.get_active_route());
|
||||||
app.cancellation_token.cancel();
|
app.cancellation_token.cancel();
|
||||||
} else if key == DEFAULT_KEYBINDINGS.previous_servarr.key {
|
} else if matches_key!(previous_servarr, key) {
|
||||||
app.reset();
|
app.reset();
|
||||||
app.server_tabs.previous();
|
app.server_tabs.previous();
|
||||||
app.pop_and_push_navigation_stack(app.server_tabs.get_active_route());
|
app.pop_and_push_navigation_stack(app.server_tabs.get_active_route());
|
||||||
@@ -115,17 +118,15 @@ fn handle_clear_errors(app: &mut App<'_>) {
|
|||||||
|
|
||||||
fn handle_prompt_toggle(app: &mut App<'_>, key: Key) {
|
fn handle_prompt_toggle(app: &mut App<'_>, key: Key) {
|
||||||
match key {
|
match key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.left.key || key == DEFAULT_KEYBINDINGS.right.key => {
|
_ if matches_key!(left, key) || matches_key!(right, key) => match app.get_current_route() {
|
||||||
match app.get_current_route() {
|
Route::Radarr(_, _) => {
|
||||||
Route::Radarr(_, _) => {
|
app.data.radarr_data.prompt_confirm = !app.data.radarr_data.prompt_confirm
|
||||||
app.data.radarr_data.prompt_confirm = !app.data.radarr_data.prompt_confirm
|
|
||||||
}
|
|
||||||
Route::Sonarr(_, _) => {
|
|
||||||
app.data.sonarr_data.prompt_confirm = !app.data.sonarr_data.prompt_confirm
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
Route::Sonarr(_, _) => {
|
||||||
|
app.data.sonarr_data.prompt_confirm = !app.data.sonarr_data.prompt_confirm
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
},
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,7 +150,7 @@ macro_rules! handle_text_box_left_right_keys {
|
|||||||
macro_rules! handle_text_box_keys {
|
macro_rules! handle_text_box_keys {
|
||||||
($self:expr, $key:expr, $input:expr) => {
|
($self:expr, $key:expr, $input:expr) => {
|
||||||
match $self.key {
|
match $self.key {
|
||||||
_ if $key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.backspace.key => {
|
_ if $crate::matches_key!(backspace, $key) => {
|
||||||
$input.pop();
|
$input.pop();
|
||||||
}
|
}
|
||||||
Key::Char(character) => {
|
Key::Char(character) => {
|
||||||
@@ -165,7 +166,7 @@ macro_rules! handle_prompt_left_right_keys {
|
|||||||
($self:expr, $confirm_prompt:expr, $data:ident) => {
|
($self:expr, $confirm_prompt:expr, $data:ident) => {
|
||||||
if $self.app.data.$data.selected_block.get_active_block() == $confirm_prompt {
|
if $self.app.data.$data.selected_block.get_active_block() == $confirm_prompt {
|
||||||
handle_prompt_toggle($self.app, $self.key);
|
handle_prompt_toggle($self.app, $self.key);
|
||||||
} else if $self.key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.left.key {
|
} else if $crate::matches_key!(left, $self.key) {
|
||||||
$self.app.data.$data.selected_block.left();
|
$self.app.data.$data.selected_block.left();
|
||||||
} else {
|
} else {
|
||||||
$self.app.data.$data.selected_block.right();
|
$self.app.data.$data.selected_block.right();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ mod tests {
|
|||||||
|
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -541,6 +542,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_blocklist_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = BlocklistHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_blocklist_item_id() {
|
fn test_extract_blocklist_item_id() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -9,6 +7,7 @@ use crate::models::radarr_models::BlocklistItem;
|
|||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, BLOCKLIST_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, BLOCKLIST_BLOCKS};
|
||||||
use crate::models::stateful_table::SortOption;
|
use crate::models::stateful_table::SortOption;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "blocklist_handler_tests.rs"]
|
#[path = "blocklist_handler_tests.rs"]
|
||||||
@@ -51,6 +50,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for BlocklistHandler<'a,
|
|||||||
BLOCKLIST_BLOCKS.contains(&active_block)
|
BLOCKLIST_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -143,10 +146,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for BlocklistHandler<'a,
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::Blocklist => match self.key {
|
ActiveRadarrBlock::Blocklist => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.clear.key => {
|
_ if matches_key!(clear, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::BlocklistClearAllItemsPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::BlocklistClearAllItemsPrompt.into());
|
||||||
@@ -154,7 +157,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for BlocklistHandler<'a,
|
|||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveRadarrBlock::DeleteBlocklistItemPrompt => {
|
ActiveRadarrBlock::DeleteBlocklistItemPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteBlocklistItem(
|
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DeleteBlocklistItem(
|
||||||
self.extract_blocklist_item_id(),
|
self.extract_blocklist_item_id(),
|
||||||
@@ -164,7 +167,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for BlocklistHandler<'a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::BlocklistClearAllItemsPrompt => {
|
ActiveRadarrBlock::BlocklistClearAllItemsPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::ClearBlocklist);
|
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::ClearBlocklist);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::KeyEventHandler;
|
use crate::handlers::KeyEventHandler;
|
||||||
use crate::models::radarr_models::CollectionMovie;
|
use crate::models::radarr_models::CollectionMovie;
|
||||||
@@ -11,6 +9,7 @@ use crate::models::servarr_data::radarr::radarr_data::{
|
|||||||
};
|
};
|
||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
use crate::models::BlockSelectionState;
|
use crate::models::BlockSelectionState;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "collection_details_handler_tests.rs"]
|
#[path = "collection_details_handler_tests.rs"]
|
||||||
@@ -46,6 +45,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionDetailsHan
|
|||||||
COLLECTION_DETAILS_BLOCKS.contains(&active_block)
|
COLLECTION_DETAILS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -130,7 +133,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionDetailsHan
|
|||||||
|
|
||||||
fn handle_char_key_event(&mut self) {
|
fn handle_char_key_event(&mut self) {
|
||||||
if self.active_radarr_block == ActiveRadarrBlock::CollectionDetails
|
if self.active_radarr_block == ActiveRadarrBlock::CollectionDetails
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.edit.key
|
&& matches_key!(edit, self.key)
|
||||||
{
|
{
|
||||||
self.app.push_navigation_stack(
|
self.app.push_navigation_stack(
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_str_eq;
|
use pretty_assertions::assert_str_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -278,6 +279,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_collection_details_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = CollectionDetailsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collection_details_handler_not_ready_when_loading() {
|
fn test_collection_details_handler_not_ready_when_loading() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -589,6 +589,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_collections_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = CollectionsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_collections_handler_not_ready_when_loading() {
|
fn test_collections_handler_not_ready_when_loading() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -7,7 +6,7 @@ use crate::models::servarr_data::radarr::modals::EditCollectionModal;
|
|||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_COLLECTION_BLOCKS};
|
||||||
use crate::models::Scrollable;
|
use crate::models::Scrollable;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::{handle_text_box_keys, handle_text_box_left_right_keys};
|
use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "edit_collection_handler_tests.rs"]
|
#[path = "edit_collection_handler_tests.rs"]
|
||||||
@@ -69,6 +68,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle
|
|||||||
EDIT_COLLECTION_BLOCKS.contains(&active_block)
|
EDIT_COLLECTION_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -262,7 +265,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle
|
|||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::EditCollectionToggleMonitored => {
|
ActiveRadarrBlock::EditCollectionToggleMonitored => {
|
||||||
self
|
self
|
||||||
@@ -311,7 +314,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle
|
|||||||
| ActiveRadarrBlock::EditCollectionSelectQualityProfile => self.app.pop_navigation_stack(),
|
| ActiveRadarrBlock::EditCollectionSelectQualityProfile => self.app.pop_navigation_stack(),
|
||||||
ActiveRadarrBlock::EditCollectionRootFolderPathInput => {
|
ActiveRadarrBlock::EditCollectionRootFolderPathInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@@ -321,7 +324,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle
|
|||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::EditCollectionRootFolderPathInput => {
|
ActiveRadarrBlock::EditCollectionRootFolderPathInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::EditCollectionPrompt => {
|
ActiveRadarrBlock::EditCollectionPrompt => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
@@ -354,7 +357,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle
|
|||||||
ActiveRadarrBlock::EditCollectionPrompt => {
|
ActiveRadarrBlock::EditCollectionPrompt => {
|
||||||
if self.app.data.radarr_data.selected_block.get_active_block()
|
if self.app.data.radarr_data.selected_block.get_active_block()
|
||||||
== ActiveRadarrBlock::EditCollectionConfirmPrompt
|
== ActiveRadarrBlock::EditCollectionConfirmPrompt
|
||||||
&& key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, key)
|
||||||
{
|
{
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditCollection(
|
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditCollection(
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
mod tests {
|
mod tests {
|
||||||
use bimap::BiMap;
|
use bimap::BiMap;
|
||||||
use pretty_assertions::assert_str_eq;
|
use pretty_assertions::assert_str_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -457,7 +458,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_edit_collection_root_folder_path_input_submit() {
|
fn test_edit_collection_root_folder_path_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal {
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal {
|
||||||
path: "Test Path".into(),
|
path: "Test Path".into(),
|
||||||
..EditCollectionModal::default()
|
..EditCollectionModal::default()
|
||||||
@@ -473,7 +474,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -759,7 +760,7 @@ mod tests {
|
|||||||
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
||||||
|
|
||||||
if selected_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput {
|
if selected_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput {
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -791,7 +792,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if active_radarr_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput {
|
if active_radarr_block == ActiveRadarrBlock::EditCollectionRootFolderPathInput {
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -811,7 +812,7 @@ mod tests {
|
|||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionRootFolderPathInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditCollectionRootFolderPathInput.into());
|
||||||
|
|
||||||
@@ -823,7 +824,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::EditCollectionPrompt.into()
|
ActiveRadarrBlock::EditCollectionPrompt.into()
|
||||||
@@ -926,7 +927,7 @@ mod tests {
|
|||||||
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
app.data.radarr_data.edit_collection_modal = Some(EditCollectionModal::default());
|
||||||
|
|
||||||
EditCollectionHandler::new(
|
EditCollectionHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
ActiveRadarrBlock::EditCollectionRootFolderPathInput,
|
||||||
None,
|
None,
|
||||||
@@ -942,7 +943,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.path
|
.path
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1019,6 +1020,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_edit_collection_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = EditCollectionHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_edit_collection_params() {
|
fn test_build_edit_collection_params() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::radarr_handlers::collections::collection_details_handler::CollectionDetailsHandler;
|
use crate::handlers::radarr_handlers::collections::collection_details_handler::CollectionDetailsHandler;
|
||||||
use crate::handlers::radarr_handlers::collections::edit_collection_handler::EditCollectionHandler;
|
use crate::handlers::radarr_handlers::collections::edit_collection_handler::EditCollectionHandler;
|
||||||
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
||||||
@@ -14,6 +12,7 @@ use crate::models::servarr_data::radarr::radarr_data::{
|
|||||||
use crate::models::stateful_table::SortOption;
|
use crate::models::stateful_table::SortOption;
|
||||||
use crate::models::BlockSelectionState;
|
use crate::models::BlockSelectionState;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
mod collection_details_handler;
|
mod collection_details_handler;
|
||||||
mod edit_collection_handler;
|
mod edit_collection_handler;
|
||||||
@@ -73,6 +72,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionsHandler<'
|
|||||||
|| COLLECTIONS_BLOCKS.contains(&active_block)
|
|| COLLECTIONS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -145,7 +148,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionsHandler<'
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::Collections => match self.key {
|
ActiveRadarrBlock::Collections => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.edit.key => {
|
_ if matches_key!(edit, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::EditCollectionPrompt.into());
|
||||||
@@ -154,18 +157,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionsHandler<'
|
|||||||
self.app.data.radarr_data.selected_block =
|
self.app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS);
|
BlockSelectionState::new(EDIT_COLLECTION_SELECTION_BLOCKS);
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.update.key => {
|
_ if matches_key!(update, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::UpdateAllCollectionsPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::UpdateAllCollectionsPrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt => {
|
ActiveRadarrBlock::UpdateAllCollectionsPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateCollections);
|
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateCollections);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -387,6 +388,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_downloads_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = DownloadsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_download_id() {
|
fn test_extract_download_id() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
||||||
use crate::models::radarr_models::DownloadRecord;
|
use crate::models::radarr_models::DownloadRecord;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DOWNLOADS_BLOCKS};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "downloads_handler_tests.rs"]
|
#[path = "downloads_handler_tests.rs"]
|
||||||
@@ -47,6 +46,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DownloadsHandler<'a,
|
|||||||
DOWNLOADS_BLOCKS.contains(&active_block)
|
DOWNLOADS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -130,18 +133,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DownloadsHandler<'a,
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::Downloads => match self.key {
|
ActiveRadarrBlock::Downloads => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.update.key => {
|
_ if matches_key!(update, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::UpdateDownloadsPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::UpdateDownloadsPrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveRadarrBlock::DeleteDownloadPrompt => {
|
ActiveRadarrBlock::DeleteDownloadPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
Some(RadarrEvent::DeleteDownload(self.extract_download_id()));
|
Some(RadarrEvent::DeleteDownload(self.extract_download_id()));
|
||||||
@@ -150,7 +153,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DownloadsHandler<'a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::UpdateDownloadsPrompt => {
|
ActiveRadarrBlock::UpdateDownloadsPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateDownloads);
|
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateDownloads);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -6,7 +5,9 @@ use crate::models::servarr_data::modals::EditIndexerModal;
|
|||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS};
|
||||||
use crate::models::servarr_models::EditIndexerParams;
|
use crate::models::servarr_models::EditIndexerParams;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::{handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys};
|
use crate::{
|
||||||
|
handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys, matches_key,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "edit_indexer_handler_tests.rs"]
|
#[path = "edit_indexer_handler_tests.rs"]
|
||||||
@@ -65,6 +66,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<'
|
|||||||
EDIT_INDEXER_BLOCKS.contains(&active_block)
|
EDIT_INDEXER_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -356,7 +361,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<'
|
|||||||
| ActiveRadarrBlock::EditIndexerSeedRatioInput
|
| ActiveRadarrBlock::EditIndexerSeedRatioInput
|
||||||
| ActiveRadarrBlock::EditIndexerTagsInput => {
|
| ActiveRadarrBlock::EditIndexerTagsInput => {
|
||||||
self.app.push_navigation_stack(selected_block.into());
|
self.app.push_navigation_stack(selected_block.into());
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::EditIndexerPriorityInput => self
|
ActiveRadarrBlock::EditIndexerPriorityInput => self
|
||||||
.app
|
.app
|
||||||
@@ -402,7 +407,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<'
|
|||||||
| ActiveRadarrBlock::EditIndexerSeedRatioInput
|
| ActiveRadarrBlock::EditIndexerSeedRatioInput
|
||||||
| ActiveRadarrBlock::EditIndexerTagsInput => {
|
| ActiveRadarrBlock::EditIndexerTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::EditIndexerPriorityInput => self.app.pop_navigation_stack(),
|
ActiveRadarrBlock::EditIndexerPriorityInput => self.app.pop_navigation_stack(),
|
||||||
_ => (),
|
_ => (),
|
||||||
@@ -423,7 +428,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<'
|
|||||||
| ActiveRadarrBlock::EditIndexerPriorityInput
|
| ActiveRadarrBlock::EditIndexerPriorityInput
|
||||||
| ActiveRadarrBlock::EditIndexerTagsInput => {
|
| ActiveRadarrBlock::EditIndexerTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => self.app.pop_navigation_stack(),
|
_ => self.app.pop_navigation_stack(),
|
||||||
}
|
}
|
||||||
@@ -504,7 +509,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<'
|
|||||||
ActiveRadarrBlock::EditIndexerPrompt => {
|
ActiveRadarrBlock::EditIndexerPrompt => {
|
||||||
if self.app.data.radarr_data.selected_block.get_active_block()
|
if self.app.data.radarr_data.selected_block.get_active_block()
|
||||||
== ActiveRadarrBlock::EditIndexerConfirmPrompt
|
== ActiveRadarrBlock::EditIndexerConfirmPrompt
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, self.key)
|
||||||
{
|
{
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ mod tests {
|
|||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_INDEXER_BLOCKS};
|
||||||
use crate::models::servarr_models::EditIndexerParams;
|
use crate::models::servarr_models::EditIndexerParams;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
mod test_handle_scroll_up_and_down {
|
mod test_handle_scroll_up_and_down {
|
||||||
@@ -1002,7 +1003,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), block.into());
|
assert_eq!(app.get_current_route(), block.into());
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1027,7 +1028,7 @@ mod tests {
|
|||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::EditIndexerPriorityInput.into()
|
ActiveRadarrBlock::EditIndexerPriorityInput.into()
|
||||||
);
|
);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1193,7 +1194,7 @@ mod tests {
|
|||||||
fn test_edit_indexer_name_input_submit() {
|
fn test_edit_indexer_name_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
||||||
name: "Test".into(),
|
name: "Test".into(),
|
||||||
..EditIndexerModal::default()
|
..EditIndexerModal::default()
|
||||||
@@ -1209,7 +1210,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -1229,7 +1230,7 @@ mod tests {
|
|||||||
fn test_edit_indexer_url_input_submit() {
|
fn test_edit_indexer_url_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
||||||
url: "Test".into(),
|
url: "Test".into(),
|
||||||
..EditIndexerModal::default()
|
..EditIndexerModal::default()
|
||||||
@@ -1245,7 +1246,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -1265,7 +1266,7 @@ mod tests {
|
|||||||
fn test_edit_indexer_api_key_input_submit() {
|
fn test_edit_indexer_api_key_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
||||||
api_key: "Test".into(),
|
api_key: "Test".into(),
|
||||||
..EditIndexerModal::default()
|
..EditIndexerModal::default()
|
||||||
@@ -1281,7 +1282,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -1301,7 +1302,7 @@ mod tests {
|
|||||||
fn test_edit_indexer_seed_ratio_input_submit() {
|
fn test_edit_indexer_seed_ratio_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
||||||
seed_ratio: "Test".into(),
|
seed_ratio: "Test".into(),
|
||||||
..EditIndexerModal::default()
|
..EditIndexerModal::default()
|
||||||
@@ -1317,7 +1318,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -1337,7 +1338,7 @@ mod tests {
|
|||||||
fn test_edit_indexer_tags_input_submit() {
|
fn test_edit_indexer_tags_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
||||||
tags: "Test".into(),
|
tags: "Test".into(),
|
||||||
..EditIndexerModal::default()
|
..EditIndexerModal::default()
|
||||||
@@ -1353,7 +1354,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -1417,12 +1418,12 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
|
||||||
EditIndexerHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
EditIndexerHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.data.radarr_data.edit_indexer_modal,
|
app.data.radarr_data.edit_indexer_modal,
|
||||||
Some(EditIndexerModal::default())
|
Some(EditIndexerModal::default())
|
||||||
@@ -1597,7 +1598,7 @@ mod tests {
|
|||||||
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||||
|
|
||||||
EditIndexerHandler::new(
|
EditIndexerHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditIndexerNameInput,
|
ActiveRadarrBlock::EditIndexerNameInput,
|
||||||
None,
|
None,
|
||||||
@@ -1613,7 +1614,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.name
|
.name
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1624,7 +1625,7 @@ mod tests {
|
|||||||
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||||
|
|
||||||
EditIndexerHandler::new(
|
EditIndexerHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditIndexerUrlInput,
|
ActiveRadarrBlock::EditIndexerUrlInput,
|
||||||
None,
|
None,
|
||||||
@@ -1640,7 +1641,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.url
|
.url
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1651,7 +1652,7 @@ mod tests {
|
|||||||
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||||
|
|
||||||
EditIndexerHandler::new(
|
EditIndexerHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditIndexerApiKeyInput,
|
ActiveRadarrBlock::EditIndexerApiKeyInput,
|
||||||
None,
|
None,
|
||||||
@@ -1667,7 +1668,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.api_key
|
.api_key
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1678,7 +1679,7 @@ mod tests {
|
|||||||
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||||
|
|
||||||
EditIndexerHandler::new(
|
EditIndexerHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditIndexerSeedRatioInput,
|
ActiveRadarrBlock::EditIndexerSeedRatioInput,
|
||||||
None,
|
None,
|
||||||
@@ -1694,7 +1695,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.seed_ratio
|
.seed_ratio
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1705,7 +1706,7 @@ mod tests {
|
|||||||
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
app.data.radarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||||
|
|
||||||
EditIndexerHandler::new(
|
EditIndexerHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditIndexerTagsInput,
|
ActiveRadarrBlock::EditIndexerTagsInput,
|
||||||
None,
|
None,
|
||||||
@@ -1721,7 +1722,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.tags
|
.tags
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1793,6 +1794,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_edit_indexer_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = EditIndexerHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_edit_indexer_params() {
|
fn test_build_edit_indexer_params() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -7,7 +6,9 @@ use crate::models::servarr_data::radarr::radarr_data::{
|
|||||||
ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS,
|
ActiveRadarrBlock, INDEXER_SETTINGS_BLOCKS,
|
||||||
};
|
};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::{handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys};
|
use crate::{
|
||||||
|
handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys, matches_key,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "edit_indexer_settings_handler_tests.rs"]
|
#[path = "edit_indexer_settings_handler_tests.rs"]
|
||||||
@@ -37,6 +38,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl
|
|||||||
INDEXER_SETTINGS_BLOCKS.contains(&active_block)
|
INDEXER_SETTINGS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -207,7 +212,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl
|
|||||||
self.app.push_navigation_stack(
|
self.app.push_navigation_stack(
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into(),
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into(),
|
||||||
);
|
);
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags => {
|
ActiveRadarrBlock::IndexerSettingsTogglePreferIndexerFlags => {
|
||||||
let indexer_settings = self.app.data.radarr_data.indexer_settings.as_mut().unwrap();
|
let indexer_settings = self.app.data.radarr_data.indexer_settings.as_mut().unwrap();
|
||||||
@@ -224,7 +229,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl
|
|||||||
}
|
}
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput => {
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::IndexerSettingsMinimumAgeInput
|
ActiveRadarrBlock::IndexerSettingsMinimumAgeInput
|
||||||
| ActiveRadarrBlock::IndexerSettingsRetentionInput
|
| ActiveRadarrBlock::IndexerSettingsRetentionInput
|
||||||
@@ -244,7 +249,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl
|
|||||||
}
|
}
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput => {
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => self.app.pop_navigation_stack(),
|
_ => self.app.pop_navigation_stack(),
|
||||||
}
|
}
|
||||||
@@ -269,7 +274,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl
|
|||||||
ActiveRadarrBlock::AllIndexerSettingsPrompt => {
|
ActiveRadarrBlock::AllIndexerSettingsPrompt => {
|
||||||
if self.app.data.radarr_data.selected_block.get_active_block()
|
if self.app.data.radarr_data.selected_block.get_active_block()
|
||||||
== ActiveRadarrBlock::IndexerSettingsConfirmPrompt
|
== ActiveRadarrBlock::IndexerSettingsConfirmPrompt
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, self.key)
|
||||||
{
|
{
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(
|
self.app.data.radarr_data.prompt_confirm_action = Some(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -602,7 +603,7 @@ mod tests {
|
|||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into()
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into()
|
||||||
);
|
);
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -716,7 +717,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_submit() {
|
fn test_edit_indexer_settings_whitelisted_subtitle_tags_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings {
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings {
|
||||||
whitelisted_hardcoded_subs: "Test tags".into(),
|
whitelisted_hardcoded_subs: "Test tags".into(),
|
||||||
..IndexerSettings::default()
|
..IndexerSettings::default()
|
||||||
@@ -734,7 +735,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -814,7 +815,7 @@ mod tests {
|
|||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into(),
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput.into(),
|
||||||
);
|
);
|
||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
|
||||||
IndexerSettingsHandler::new(
|
IndexerSettingsHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
@@ -825,7 +826,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Indexers.into());
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.data.radarr_data.indexer_settings,
|
app.data.radarr_data.indexer_settings,
|
||||||
Some(IndexerSettings::default())
|
Some(IndexerSettings::default())
|
||||||
@@ -907,7 +908,7 @@ mod tests {
|
|||||||
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
app.data.radarr_data.indexer_settings = Some(IndexerSettings::default());
|
||||||
|
|
||||||
IndexerSettingsHandler::new(
|
IndexerSettingsHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
ActiveRadarrBlock::IndexerSettingsWhitelistedSubtitleTagsInput,
|
||||||
None,
|
None,
|
||||||
@@ -923,7 +924,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.whitelisted_hardcoded_subs
|
.whitelisted_hardcoded_subs
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -970,6 +971,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_indexer_settings_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = IndexerSettingsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_edit_indexer_settings_body() {
|
fn test_build_edit_indexer_settings_body() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -633,6 +633,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_indexers_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = IndexersHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_indexer_id() {
|
fn test_extract_indexer_id() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
||||||
use crate::handlers::radarr_handlers::indexers::edit_indexer_handler::EditIndexerHandler;
|
use crate::handlers::radarr_handlers::indexers::edit_indexer_handler::EditIndexerHandler;
|
||||||
use crate::handlers::radarr_handlers::indexers::edit_indexer_settings_handler::IndexerSettingsHandler;
|
use crate::handlers::radarr_handlers::indexers::edit_indexer_settings_handler::IndexerSettingsHandler;
|
||||||
@@ -15,6 +13,7 @@ use crate::models::servarr_data::radarr::radarr_data::{
|
|||||||
use crate::models::servarr_models::Indexer;
|
use crate::models::servarr_models::Indexer;
|
||||||
use crate::models::BlockSelectionState;
|
use crate::models::BlockSelectionState;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
mod edit_indexer_handler;
|
mod edit_indexer_handler;
|
||||||
mod edit_indexer_settings_handler;
|
mod edit_indexer_settings_handler;
|
||||||
@@ -70,6 +69,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexersHandler<'a,
|
|||||||
|| INDEXERS_BLOCKS.contains(&active_block)
|
|| INDEXERS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -169,20 +172,20 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexersHandler<'a,
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::Indexers => match self.key {
|
ActiveRadarrBlock::Indexers => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.test.key => {
|
_ if matches_key!(test, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::TestIndexer.into());
|
.push_navigation_stack(ActiveRadarrBlock::TestIndexer.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.test_all.key => {
|
_ if matches_key!(test_all, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::TestAllIndexers.into());
|
.push_navigation_stack(ActiveRadarrBlock::TestAllIndexers.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.settings.key => {
|
_ if matches_key!(settings, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::AllIndexerSettingsPrompt.into());
|
||||||
@@ -192,7 +195,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexersHandler<'a,
|
|||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveRadarrBlock::DeleteIndexerPrompt => {
|
ActiveRadarrBlock::DeleteIndexerPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
Some(RadarrEvent::DeleteIndexer(self.extract_indexer_id()));
|
Some(RadarrEvent::DeleteIndexer(self.extract_indexer_id()));
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for TestAllIndexersHandl
|
|||||||
active_block == ActiveRadarrBlock::TestAllIndexers
|
active_block == ActiveRadarrBlock::TestAllIndexers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ mod tests {
|
|||||||
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
mod test_handle_esc {
|
mod test_handle_esc {
|
||||||
@@ -48,6 +49,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_test_all_indexers_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = TestAllIndexersHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_test_all_indexers_handler_is_not_ready_when_loading() {
|
fn test_test_all_indexers_handler_is_not_ready_when_loading() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
use crate::models::radarr_models::{
|
use crate::models::radarr_models::{
|
||||||
@@ -11,7 +10,9 @@ use crate::models::servarr_data::radarr::radarr_data::{
|
|||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
use crate::models::{BlockSelectionState, Scrollable};
|
use crate::models::{BlockSelectionState, Scrollable};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::{handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys, App, Key};
|
use crate::{
|
||||||
|
handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys, matches_key, App, Key,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "add_movie_handler_tests.rs"]
|
#[path = "add_movie_handler_tests.rs"]
|
||||||
@@ -132,6 +133,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
|||||||
ADD_MOVIE_BLOCKS.contains(&active_block)
|
ADD_MOVIE_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -404,7 +409,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
|||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
|
.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ if self.active_radarr_block == ActiveRadarrBlock::AddMovieSearchResults
|
_ if self.active_radarr_block == ActiveRadarrBlock::AddMovieSearchResults
|
||||||
&& self.app.data.radarr_data.add_searched_movies.is_some() =>
|
&& self.app.data.radarr_data.add_searched_movies.is_some() =>
|
||||||
@@ -468,7 +473,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
|||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@@ -479,7 +484,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
|||||||
| ActiveRadarrBlock::AddMovieSelectRootFolder => self.app.pop_navigation_stack(),
|
| ActiveRadarrBlock::AddMovieSelectRootFolder => self.app.pop_navigation_stack(),
|
||||||
ActiveRadarrBlock::AddMovieTagsInput => {
|
ActiveRadarrBlock::AddMovieTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@@ -490,12 +495,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
|||||||
ActiveRadarrBlock::AddMovieSearchInput => {
|
ActiveRadarrBlock::AddMovieSearchInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.data.radarr_data.add_movie_search = None;
|
self.app.data.radarr_data.add_movie_search = None;
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::AddMovieSearchResults | ActiveRadarrBlock::AddMovieEmptySearchResults => {
|
ActiveRadarrBlock::AddMovieSearchResults | ActiveRadarrBlock::AddMovieEmptySearchResults => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.data.radarr_data.add_searched_movies = None;
|
self.app.data.radarr_data.add_searched_movies = None;
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::AddMoviePrompt => {
|
ActiveRadarrBlock::AddMoviePrompt => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
@@ -509,7 +514,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
|||||||
| ActiveRadarrBlock::AddMovieSelectRootFolder => self.app.pop_navigation_stack(),
|
| ActiveRadarrBlock::AddMovieSelectRootFolder => self.app.pop_navigation_stack(),
|
||||||
ActiveRadarrBlock::AddMovieTagsInput => {
|
ActiveRadarrBlock::AddMovieTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@@ -542,7 +547,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a,
|
|||||||
ActiveRadarrBlock::AddMoviePrompt => {
|
ActiveRadarrBlock::AddMoviePrompt => {
|
||||||
if self.app.data.radarr_data.selected_block.get_active_block()
|
if self.app.data.radarr_data.selected_block.get_active_block()
|
||||||
== ActiveRadarrBlock::AddMovieConfirmPrompt
|
== ActiveRadarrBlock::AddMovieConfirmPrompt
|
||||||
&& key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, key)
|
||||||
{
|
{
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
|
|||||||
@@ -782,7 +782,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_search_input_submit() {
|
fn test_add_movie_search_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.add_movie_search = Some("test".into());
|
app.data.radarr_data.add_movie_search = Some("test".into());
|
||||||
|
|
||||||
AddMovieHandler::new(
|
AddMovieHandler::new(
|
||||||
@@ -793,7 +793,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::AddMovieSearchResults.into()
|
ActiveRadarrBlock::AddMovieSearchResults.into()
|
||||||
@@ -805,7 +805,7 @@ mod tests {
|
|||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.add_movie_search = Some(HorizontallyScrollableText::default());
|
app.data.radarr_data.add_movie_search = Some(HorizontallyScrollableText::default());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
|
||||||
AddMovieHandler::new(
|
AddMovieHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
@@ -815,7 +815,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::AddMovieSearchInput.into()
|
ActiveRadarrBlock::AddMovieSearchInput.into()
|
||||||
@@ -1093,7 +1093,7 @@ mod tests {
|
|||||||
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
||||||
|
|
||||||
if selected_block == ActiveRadarrBlock::AddMovieTagsInput {
|
if selected_block == ActiveRadarrBlock::AddMovieTagsInput {
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1126,7 +1126,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if active_radarr_block == ActiveRadarrBlock::AddMovieTagsInput {
|
if active_radarr_block == ActiveRadarrBlock::AddMovieTagsInput {
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1149,7 +1149,7 @@ mod tests {
|
|||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
||||||
|
|
||||||
AddMovieHandler::new(
|
AddMovieHandler::new(
|
||||||
@@ -1160,7 +1160,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
assert_eq!(app.data.radarr_data.add_movie_search, None);
|
assert_eq!(app.data.radarr_data.add_movie_search, None);
|
||||||
}
|
}
|
||||||
@@ -1169,7 +1169,7 @@ mod tests {
|
|||||||
fn test_add_movie_input_esc() {
|
fn test_add_movie_input_esc() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieTagsInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieTagsInput.into());
|
||||||
|
|
||||||
@@ -1181,7 +1181,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::AddMoviePrompt.into()
|
ActiveRadarrBlock::AddMoviePrompt.into()
|
||||||
@@ -1213,7 +1213,7 @@ mod tests {
|
|||||||
ActiveRadarrBlock::AddMovieSearchInput.into()
|
ActiveRadarrBlock::AddMovieSearchInput.into()
|
||||||
);
|
);
|
||||||
assert!(app.data.radarr_data.add_searched_movies.is_none());
|
assert!(app.data.radarr_data.add_searched_movies.is_none());
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1259,7 +1259,7 @@ mod tests {
|
|||||||
fn test_add_movie_tags_input_esc() {
|
fn test_add_movie_tags_input_esc() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMoviePrompt.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieTagsInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieTagsInput.into());
|
||||||
|
|
||||||
@@ -1271,7 +1271,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::AddMoviePrompt.into()
|
ActiveRadarrBlock::AddMoviePrompt.into()
|
||||||
@@ -1395,7 +1395,7 @@ mod tests {
|
|||||||
app.data.radarr_data.add_movie_search = Some(HorizontallyScrollableText::default());
|
app.data.radarr_data.add_movie_search = Some(HorizontallyScrollableText::default());
|
||||||
|
|
||||||
AddMovieHandler::new(
|
AddMovieHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieSearchInput,
|
ActiveRadarrBlock::AddMovieSearchInput,
|
||||||
None,
|
None,
|
||||||
@@ -1404,7 +1404,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_str_eq!(
|
assert_str_eq!(
|
||||||
app.data.radarr_data.add_movie_search.as_ref().unwrap().text,
|
app.data.radarr_data.add_movie_search.as_ref().unwrap().text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1414,7 +1414,7 @@ mod tests {
|
|||||||
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
app.data.radarr_data.add_movie_modal = Some(AddMovieModal::default());
|
||||||
|
|
||||||
AddMovieHandler::new(
|
AddMovieHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddMovieTagsInput,
|
ActiveRadarrBlock::AddMovieTagsInput,
|
||||||
None,
|
None,
|
||||||
@@ -1430,7 +1430,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.tags
|
.tags
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1523,6 +1523,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_add_movie_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = AddMovieHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_movie_search_no_panic_on_none_search_result() {
|
fn test_add_movie_search_no_panic_on_none_search_result() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
|
use crate::matches_key;
|
||||||
use crate::models::radarr_models::DeleteMovieParams;
|
use crate::models::radarr_models::DeleteMovieParams;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, DELETE_MOVIE_BLOCKS};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
@@ -37,6 +37,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DeleteMovieHandler<'
|
|||||||
DELETE_MOVIE_BLOCKS.contains(&active_block)
|
DELETE_MOVIE_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -122,7 +126,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for DeleteMovieHandler<'
|
|||||||
if self.active_radarr_block == ActiveRadarrBlock::DeleteMoviePrompt
|
if self.active_radarr_block == ActiveRadarrBlock::DeleteMoviePrompt
|
||||||
&& self.app.data.radarr_data.selected_block.get_active_block()
|
&& self.app.data.radarr_data.selected_block.get_active_block()
|
||||||
== ActiveRadarrBlock::DeleteMovieConfirmPrompt
|
== ActiveRadarrBlock::DeleteMovieConfirmPrompt
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, self.key)
|
||||||
{
|
{
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -313,6 +314,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_delete_movie_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = DeleteMovieHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_delete_movie_params() {
|
fn test_build_delete_movie_params() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -7,7 +6,7 @@ use crate::models::servarr_data::radarr::modals::EditMovieModal;
|
|||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, EDIT_MOVIE_BLOCKS};
|
||||||
use crate::models::Scrollable;
|
use crate::models::Scrollable;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::{handle_text_box_keys, handle_text_box_left_right_keys};
|
use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "edit_movie_handler_tests.rs"]
|
#[path = "edit_movie_handler_tests.rs"]
|
||||||
@@ -68,6 +67,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a,
|
|||||||
EDIT_MOVIE_BLOCKS.contains(&active_block)
|
EDIT_MOVIE_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -290,7 +293,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a,
|
|||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::EditMovieToggleMonitored => {
|
ActiveRadarrBlock::EditMovieToggleMonitored => {
|
||||||
self
|
self
|
||||||
@@ -319,7 +322,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a,
|
|||||||
| ActiveRadarrBlock::EditMovieSelectQualityProfile => self.app.pop_navigation_stack(),
|
| ActiveRadarrBlock::EditMovieSelectQualityProfile => self.app.pop_navigation_stack(),
|
||||||
ActiveRadarrBlock::EditMoviePathInput | ActiveRadarrBlock::EditMovieTagsInput => {
|
ActiveRadarrBlock::EditMoviePathInput | ActiveRadarrBlock::EditMovieTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@@ -329,7 +332,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a,
|
|||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::EditMovieTagsInput | ActiveRadarrBlock::EditMoviePathInput => {
|
ActiveRadarrBlock::EditMovieTagsInput | ActiveRadarrBlock::EditMoviePathInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::EditMoviePrompt => {
|
ActiveRadarrBlock::EditMoviePrompt => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
@@ -376,7 +379,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a,
|
|||||||
ActiveRadarrBlock::EditMoviePrompt => {
|
ActiveRadarrBlock::EditMoviePrompt => {
|
||||||
if self.app.data.radarr_data.selected_block.get_active_block()
|
if self.app.data.radarr_data.selected_block.get_active_block()
|
||||||
== ActiveRadarrBlock::EditMovieConfirmPrompt
|
== ActiveRadarrBlock::EditMovieConfirmPrompt
|
||||||
&& key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, key)
|
||||||
{
|
{
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
mod tests {
|
mod tests {
|
||||||
use bimap::BiMap;
|
use bimap::BiMap;
|
||||||
use pretty_assertions::assert_str_eq;
|
use pretty_assertions::assert_str_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -548,7 +549,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_path_input_submit() {
|
fn test_edit_movie_path_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
||||||
path: "Test Path".into(),
|
path: "Test Path".into(),
|
||||||
..EditMovieModal::default()
|
..EditMovieModal::default()
|
||||||
@@ -564,7 +565,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -583,7 +584,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_edit_movie_tags_input_submit() {
|
fn test_edit_movie_tags_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal {
|
||||||
tags: "Test Tags".into(),
|
tags: "Test Tags".into(),
|
||||||
..EditMovieModal::default()
|
..EditMovieModal::default()
|
||||||
@@ -599,7 +600,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -813,7 +814,7 @@ mod tests {
|
|||||||
if selected_block == ActiveRadarrBlock::EditMoviePathInput
|
if selected_block == ActiveRadarrBlock::EditMoviePathInput
|
||||||
|| selected_block == ActiveRadarrBlock::EditMovieTagsInput
|
|| selected_block == ActiveRadarrBlock::EditMovieTagsInput
|
||||||
{
|
{
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -851,7 +852,7 @@ mod tests {
|
|||||||
.into()
|
.into()
|
||||||
);
|
);
|
||||||
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
@@ -885,7 +886,7 @@ mod tests {
|
|||||||
if active_radarr_block == ActiveRadarrBlock::EditMoviePathInput
|
if active_radarr_block == ActiveRadarrBlock::EditMoviePathInput
|
||||||
|| active_radarr_block == ActiveRadarrBlock::EditMovieTagsInput
|
|| active_radarr_block == ActiveRadarrBlock::EditMovieTagsInput
|
||||||
{
|
{
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -911,13 +912,13 @@ mod tests {
|
|||||||
) {
|
) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::EditMoviePrompt.into());
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
|
|
||||||
EditMovieHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
EditMovieHandler::new(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::EditMoviePrompt.into()
|
ActiveRadarrBlock::EditMoviePrompt.into()
|
||||||
@@ -1033,7 +1034,7 @@ mod tests {
|
|||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
|
|
||||||
EditMovieHandler::new(
|
EditMovieHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMoviePathInput,
|
ActiveRadarrBlock::EditMoviePathInput,
|
||||||
None,
|
None,
|
||||||
@@ -1049,7 +1050,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.path
|
.path
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1059,7 +1060,7 @@ mod tests {
|
|||||||
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
app.data.radarr_data.edit_movie_modal = Some(EditMovieModal::default());
|
||||||
|
|
||||||
EditMovieHandler::new(
|
EditMovieHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::EditMovieTagsInput,
|
ActiveRadarrBlock::EditMovieTagsInput,
|
||||||
None,
|
None,
|
||||||
@@ -1075,7 +1076,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.tags
|
.tags
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1148,6 +1149,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_edit_movie_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = EditMovieHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_edit_movie_params() {
|
fn test_build_edit_movie_params() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ mod tests {
|
|||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::AddMovieSearchInput.into()
|
ActiveRadarrBlock::AddMovieSearchInput.into()
|
||||||
);
|
);
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.radarr_data.add_movie_search.is_some());
|
assert!(app.data.radarr_data.add_movie_search.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +355,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.radarr_data.add_movie_search.is_none());
|
assert!(app.data.radarr_data.add_movie_search.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,6 +777,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_library_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = LibraryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_library_handler_not_ready_when_loading() {
|
fn test_library_handler_not_ready_when_loading() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
||||||
@@ -8,7 +7,6 @@ use crate::handlers::radarr_handlers::library::edit_movie_handler::EditMovieHand
|
|||||||
use crate::handlers::radarr_handlers::library::movie_details_handler::MovieDetailsHandler;
|
use crate::handlers::radarr_handlers::library::movie_details_handler::MovieDetailsHandler;
|
||||||
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
||||||
|
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::models::radarr_models::Movie;
|
use crate::models::radarr_models::Movie;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::{
|
use crate::models::servarr_data::radarr::radarr_data::{
|
||||||
@@ -17,6 +15,7 @@ use crate::models::servarr_data::radarr::radarr_data::{
|
|||||||
use crate::models::stateful_table::SortOption;
|
use crate::models::stateful_table::SortOption;
|
||||||
use crate::models::{BlockSelectionState, HorizontallyScrollableText};
|
use crate::models::{BlockSelectionState, HorizontallyScrollableText};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
mod add_movie_handler;
|
mod add_movie_handler;
|
||||||
mod delete_movie_handler;
|
mod delete_movie_handler;
|
||||||
@@ -81,6 +80,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, '
|
|||||||
|| LIBRARY_BLOCKS.contains(&active_block)
|
|| LIBRARY_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -161,7 +164,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, '
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::Movies => match self.key {
|
ActiveRadarrBlock::Movies => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.edit.key => {
|
_ if matches_key!(edit, key) => {
|
||||||
self.app.push_navigation_stack(
|
self.app.push_navigation_stack(
|
||||||
(
|
(
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -173,25 +176,25 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, '
|
|||||||
self.app.data.radarr_data.selected_block =
|
self.app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.add.key => {
|
_ if matches_key!(add, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
||||||
self.app.data.radarr_data.add_movie_search = Some(HorizontallyScrollableText::default());
|
self.app.data.radarr_data.add_movie_search = Some(HorizontallyScrollableText::default());
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.update.key => {
|
_ if matches_key!(update, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::UpdateAllMoviesPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::UpdateAllMoviesPrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveRadarrBlock::UpdateAllMoviesPrompt => {
|
ActiveRadarrBlock::UpdateAllMoviesPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateAllMovies);
|
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateAllMovies);
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
use serde_json::Number;
|
use serde_json::Number;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
use crate::models::radarr_models::{
|
use crate::models::radarr_models::{
|
||||||
@@ -16,6 +14,7 @@ use crate::models::servarr_models::Language;
|
|||||||
use crate::models::stateful_table::SortOption;
|
use crate::models::stateful_table::SortOption;
|
||||||
use crate::models::{BlockSelectionState, Scrollable};
|
use crate::models::{BlockSelectionState, Scrollable};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "movie_details_handler_tests.rs"]
|
#[path = "movie_details_handler_tests.rs"]
|
||||||
@@ -136,6 +135,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler<
|
|||||||
MOVIE_DETAILS_BLOCKS.contains(&active_block)
|
MOVIE_DETAILS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -245,13 +248,13 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler<
|
|||||||
| ActiveRadarrBlock::Cast
|
| ActiveRadarrBlock::Cast
|
||||||
| ActiveRadarrBlock::Crew
|
| ActiveRadarrBlock::Crew
|
||||||
| ActiveRadarrBlock::ManualSearch => match self.key {
|
| ActiveRadarrBlock::ManualSearch => match self.key {
|
||||||
_ if self.key == DEFAULT_KEYBINDINGS.left.key => {
|
_ if matches_key!(left, self.key) => {
|
||||||
self.app.data.radarr_data.movie_info_tabs.previous();
|
self.app.data.radarr_data.movie_info_tabs.previous();
|
||||||
self.app.pop_and_push_navigation_stack(
|
self.app.pop_and_push_navigation_stack(
|
||||||
self.app.data.radarr_data.movie_info_tabs.get_active_route(),
|
self.app.data.radarr_data.movie_info_tabs.get_active_route(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ if self.key == DEFAULT_KEYBINDINGS.right.key => {
|
_ if matches_key!(right, self.key) => {
|
||||||
self.app.data.radarr_data.movie_info_tabs.next();
|
self.app.data.radarr_data.movie_info_tabs.next();
|
||||||
self.app.pop_and_push_navigation_stack(
|
self.app.pop_and_push_navigation_stack(
|
||||||
self.app.data.radarr_data.movie_info_tabs.get_active_route(),
|
self.app.data.radarr_data.movie_info_tabs.get_active_route(),
|
||||||
@@ -332,12 +335,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler<
|
|||||||
| ActiveRadarrBlock::Cast
|
| ActiveRadarrBlock::Cast
|
||||||
| ActiveRadarrBlock::Crew
|
| ActiveRadarrBlock::Crew
|
||||||
| ActiveRadarrBlock::ManualSearch => match self.key {
|
| ActiveRadarrBlock::ManualSearch => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.auto_search.key => {
|
_ if matches_key!(auto_search, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::AutomaticallySearchMoviePrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::AutomaticallySearchMoviePrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.edit.key => {
|
_ if matches_key!(edit, key) => {
|
||||||
self.app.push_navigation_stack(
|
self.app.push_navigation_stack(
|
||||||
(
|
(
|
||||||
ActiveRadarrBlock::EditMoviePrompt,
|
ActiveRadarrBlock::EditMoviePrompt,
|
||||||
@@ -349,35 +352,33 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for MovieDetailsHandler<
|
|||||||
self.app.data.radarr_data.selected_block =
|
self.app.data.radarr_data.selected_block =
|
||||||
BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
BlockSelectionState::new(EDIT_MOVIE_SELECTION_BLOCKS);
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.update.key => {
|
_ if matches_key!(update, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::UpdateAndScanPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::UpdateAndScanPrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.pop_and_push_navigation_stack(self.active_radarr_block.into());
|
.pop_and_push_navigation_stack(self.active_radarr_block.into());
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt
|
ActiveRadarrBlock::AutomaticallySearchMoviePrompt if matches_key!(confirm, key) => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key =>
|
|
||||||
{
|
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
Some(RadarrEvent::TriggerAutomaticSearch(self.extract_movie_id()));
|
Some(RadarrEvent::TriggerAutomaticSearch(self.extract_movie_id()));
|
||||||
|
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::UpdateAndScanPrompt if key == DEFAULT_KEYBINDINGS.confirm.key => {
|
ActiveRadarrBlock::UpdateAndScanPrompt if matches_key!(confirm, key) => {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
Some(RadarrEvent::UpdateAndScan(self.extract_movie_id()));
|
Some(RadarrEvent::UpdateAndScan(self.extract_movie_id()));
|
||||||
|
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::ManualSearchConfirmPrompt if key == DEFAULT_KEYBINDINGS.confirm.key => {
|
ActiveRadarrBlock::ManualSearchConfirmPrompt if matches_key!(confirm, key) => {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DownloadRelease(
|
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::DownloadRelease(
|
||||||
self.build_radarr_release_download_body(),
|
self.build_radarr_release_download_body(),
|
||||||
|
|||||||
@@ -1042,6 +1042,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_movie_details_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = MovieDetailsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_movie_details_handler_is_not_ready_when_loading(
|
fn test_movie_details_handler_is_not_ready_when_loading(
|
||||||
#[values(
|
#[values(
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::handlers::radarr_handlers::blocklist::BlocklistHandler;
|
use crate::handlers::radarr_handlers::blocklist::BlocklistHandler;
|
||||||
use crate::handlers::radarr_handlers::collections::CollectionsHandler;
|
use crate::handlers::radarr_handlers::collections::CollectionsHandler;
|
||||||
use crate::handlers::radarr_handlers::downloads::DownloadsHandler;
|
use crate::handlers::radarr_handlers::downloads::DownloadsHandler;
|
||||||
@@ -8,7 +7,7 @@ use crate::handlers::radarr_handlers::root_folders::RootFoldersHandler;
|
|||||||
use crate::handlers::radarr_handlers::system::SystemHandler;
|
use crate::handlers::radarr_handlers::system::SystemHandler;
|
||||||
use crate::handlers::KeyEventHandler;
|
use crate::handlers::KeyEventHandler;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||||
use crate::{App, Key};
|
use crate::{matches_key, App, Key};
|
||||||
|
|
||||||
mod blocklist;
|
mod blocklist;
|
||||||
mod collections;
|
mod collections;
|
||||||
@@ -65,6 +64,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RadarrHandler<'a, 'b
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -109,11 +112,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RadarrHandler<'a, 'b
|
|||||||
pub fn handle_change_tab_left_right_keys(app: &mut App<'_>, key: Key) {
|
pub fn handle_change_tab_left_right_keys(app: &mut App<'_>, key: Key) {
|
||||||
let key_ref = key;
|
let key_ref = key;
|
||||||
match key_ref {
|
match key_ref {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.left.key => {
|
_ if matches_key!(left, key, app.ignore_special_keys_for_textbox_input) => {
|
||||||
app.data.radarr_data.main_tabs.previous();
|
app.data.radarr_data.main_tabs.previous();
|
||||||
app.pop_and_push_navigation_stack(app.data.radarr_data.main_tabs.get_active_route());
|
app.pop_and_push_navigation_stack(app.data.radarr_data.main_tabs.get_active_route());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.right.key => {
|
_ if matches_key!(right, key, app.ignore_special_keys_for_textbox_input) => {
|
||||||
app.data.radarr_data.main_tabs.next();
|
app.data.radarr_data.main_tabs.next();
|
||||||
app.pop_and_push_navigation_stack(app.data.radarr_data.main_tabs.get_active_route());
|
app.pop_and_push_navigation_stack(app.data.radarr_data.main_tabs.get_active_route());
|
||||||
}
|
}
|
||||||
@@ -139,7 +142,7 @@ macro_rules! search_table {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$app.data.radarr_data.is_searching = false;
|
$app.data.radarr_data.is_searching = false;
|
||||||
$app.should_ignore_quit_key = false;
|
$app.ignore_special_keys_for_textbox_input = false;
|
||||||
|
|
||||||
if search_index.is_some() {
|
if search_index.is_some() {
|
||||||
$app.pop_navigation_stack();
|
$app.pop_navigation_stack();
|
||||||
@@ -166,7 +169,7 @@ macro_rules! search_table {
|
|||||||
};
|
};
|
||||||
|
|
||||||
$app.data.radarr_data.is_searching = false;
|
$app.data.radarr_data.is_searching = false;
|
||||||
$app.should_ignore_quit_key = false;
|
$app.ignore_special_keys_for_textbox_input = false;
|
||||||
|
|
||||||
if search_index.is_some() {
|
if search_index.is_some() {
|
||||||
$app.pop_navigation_stack();
|
$app.pop_navigation_stack();
|
||||||
|
|||||||
@@ -46,6 +46,76 @@ mod tests {
|
|||||||
assert_eq!(app.get_current_route(), right_block.into());
|
assert_eq!(app.get_current_route(), right_block.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(0, ActiveRadarrBlock::System, ActiveRadarrBlock::Collections)]
|
||||||
|
#[case(1, ActiveRadarrBlock::Movies, ActiveRadarrBlock::Downloads)]
|
||||||
|
#[case(2, ActiveRadarrBlock::Collections, ActiveRadarrBlock::Blocklist)]
|
||||||
|
#[case(3, ActiveRadarrBlock::Downloads, ActiveRadarrBlock::RootFolders)]
|
||||||
|
#[case(4, ActiveRadarrBlock::Blocklist, ActiveRadarrBlock::Indexers)]
|
||||||
|
#[case(5, ActiveRadarrBlock::RootFolders, ActiveRadarrBlock::System)]
|
||||||
|
#[case(6, ActiveRadarrBlock::Indexers, ActiveRadarrBlock::Movies)]
|
||||||
|
fn test_radarr_handler_change_tab_left_right_keys_alt_navigation(
|
||||||
|
#[case] index: usize,
|
||||||
|
#[case] left_block: ActiveRadarrBlock,
|
||||||
|
#[case] right_block: ActiveRadarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = false;
|
||||||
|
app.data.radarr_data.main_tabs.set_index(index);
|
||||||
|
|
||||||
|
handle_change_tab_left_right_keys(&mut app, DEFAULT_KEYBINDINGS.left.alt.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.radarr_data.main_tabs.get_active_route(),
|
||||||
|
left_block.into()
|
||||||
|
);
|
||||||
|
assert_eq!(app.get_current_route(), left_block.into());
|
||||||
|
|
||||||
|
app.data.radarr_data.main_tabs.set_index(index);
|
||||||
|
|
||||||
|
handle_change_tab_left_right_keys(&mut app, DEFAULT_KEYBINDINGS.right.alt.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.radarr_data.main_tabs.get_active_route(),
|
||||||
|
right_block.into()
|
||||||
|
);
|
||||||
|
assert_eq!(app.get_current_route(), right_block.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(0, ActiveRadarrBlock::Movies)]
|
||||||
|
#[case(1, ActiveRadarrBlock::Collections)]
|
||||||
|
#[case(2, ActiveRadarrBlock::Downloads)]
|
||||||
|
#[case(3, ActiveRadarrBlock::Blocklist)]
|
||||||
|
#[case(4, ActiveRadarrBlock::RootFolders)]
|
||||||
|
#[case(5, ActiveRadarrBlock::Indexers)]
|
||||||
|
#[case(6, ActiveRadarrBlock::System)]
|
||||||
|
fn test_radarr_handler_change_tab_left_right_keys_alt_navigation_no_op_when_ignoring_quit_key(
|
||||||
|
#[case] index: usize,
|
||||||
|
#[case] block: ActiveRadarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
app.push_navigation_stack(block.into());
|
||||||
|
app.data.radarr_data.main_tabs.set_index(index);
|
||||||
|
|
||||||
|
handle_change_tab_left_right_keys(&mut app, DEFAULT_KEYBINDINGS.left.alt.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.radarr_data.main_tabs.get_active_route(),
|
||||||
|
block.into()
|
||||||
|
);
|
||||||
|
assert_eq!(app.get_current_route(), block.into());
|
||||||
|
|
||||||
|
handle_change_tab_left_right_keys(&mut app, DEFAULT_KEYBINDINGS.right.alt.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.radarr_data.main_tabs.get_active_route(),
|
||||||
|
block.into()
|
||||||
|
);
|
||||||
|
assert_eq!(app.get_current_route(), block.into());
|
||||||
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_delegates_system_blocks_to_system_handler(
|
fn test_delegates_system_blocks_to_system_handler(
|
||||||
#[values(
|
#[values(
|
||||||
@@ -217,6 +287,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_radarr_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = RadarrHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::Movies,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_radarr_handler_is_ready() {
|
fn test_radarr_handler_is_ready() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
||||||
@@ -8,7 +7,9 @@ use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, ROOT_F
|
|||||||
use crate::models::servarr_models::{AddRootFolderBody, RootFolder};
|
use crate::models::servarr_models::{AddRootFolderBody, RootFolder};
|
||||||
use crate::models::HorizontallyScrollableText;
|
use crate::models::HorizontallyScrollableText;
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::{handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys};
|
use crate::{
|
||||||
|
handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys, matches_key,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "root_folders_handler_tests.rs"]
|
#[path = "root_folders_handler_tests.rs"]
|
||||||
@@ -68,6 +69,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RootFoldersHandler<'
|
|||||||
ROOT_FOLDERS_BLOCKS.contains(&active_block)
|
ROOT_FOLDERS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -168,7 +173,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RootFoldersHandler<'
|
|||||||
self.build_add_root_folder_body(),
|
self.build_add_root_folder_body(),
|
||||||
));
|
));
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
@@ -181,7 +186,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RootFoldersHandler<'
|
|||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.data.radarr_data.edit_root_folder = None;
|
self.app.data.radarr_data.edit_root_folder = None;
|
||||||
self.app.data.radarr_data.prompt_confirm = false;
|
self.app.data.radarr_data.prompt_confirm = false;
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::DeleteRootFolderPrompt => {
|
ActiveRadarrBlock::DeleteRootFolderPrompt => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
@@ -195,15 +200,15 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RootFoldersHandler<'
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::RootFolders => match self.key {
|
ActiveRadarrBlock::RootFolders => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.add.key => {
|
_ if matches_key!(add, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::AddRootFolderPrompt.into());
|
.push_navigation_stack(ActiveRadarrBlock::AddRootFolderPrompt.into());
|
||||||
self.app.data.radarr_data.edit_root_folder = Some(HorizontallyScrollableText::default());
|
self.app.data.radarr_data.edit_root_folder = Some(HorizontallyScrollableText::default());
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
@@ -215,7 +220,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for RootFoldersHandler<'
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::DeleteRootFolderPrompt => {
|
ActiveRadarrBlock::DeleteRootFolderPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
Some(RadarrEvent::DeleteRootFolder(self.extract_root_folder_id()));
|
Some(RadarrEvent::DeleteRootFolder(self.extract_root_folder_id()));
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -262,7 +263,7 @@ mod tests {
|
|||||||
.set_items(vec![RootFolder::default()]);
|
.set_items(vec![RootFolder::default()]);
|
||||||
app.data.radarr_data.edit_root_folder = Some("Test".into());
|
app.data.radarr_data.edit_root_folder = Some("Test".into());
|
||||||
app.data.radarr_data.prompt_confirm = true;
|
app.data.radarr_data.prompt_confirm = true;
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::RootFolders.into());
|
app.push_navigation_stack(ActiveRadarrBlock::RootFolders.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddRootFolderPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddRootFolderPrompt.into());
|
||||||
|
|
||||||
@@ -275,7 +276,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(app.data.radarr_data.prompt_confirm);
|
assert!(app.data.radarr_data.prompt_confirm);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.data.radarr_data.prompt_confirm_action,
|
app.data.radarr_data.prompt_confirm_action,
|
||||||
Some(RadarrEvent::AddRootFolder(expected_add_root_folder_body))
|
Some(RadarrEvent::AddRootFolder(expected_add_root_folder_body))
|
||||||
@@ -291,7 +292,7 @@ mod tests {
|
|||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.data.radarr_data.edit_root_folder = Some(HorizontallyScrollableText::default());
|
app.data.radarr_data.edit_root_folder = Some(HorizontallyScrollableText::default());
|
||||||
app.data.radarr_data.prompt_confirm = false;
|
app.data.radarr_data.prompt_confirm = false;
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::RootFolders.into());
|
app.push_navigation_stack(ActiveRadarrBlock::RootFolders.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddRootFolderPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddRootFolderPrompt.into());
|
||||||
|
|
||||||
@@ -304,7 +305,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.radarr_data.prompt_confirm_action.is_none());
|
assert!(app.data.radarr_data.prompt_confirm_action.is_none());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -406,7 +407,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveRadarrBlock::RootFolders.into());
|
app.push_navigation_stack(ActiveRadarrBlock::RootFolders.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddRootFolderPrompt.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddRootFolderPrompt.into());
|
||||||
app.data.radarr_data.edit_root_folder = Some("/nfs/test".into());
|
app.data.radarr_data.edit_root_folder = Some("/nfs/test".into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
|
||||||
RootFoldersHandler::new(
|
RootFoldersHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
@@ -423,7 +424,7 @@ mod tests {
|
|||||||
|
|
||||||
assert!(app.data.radarr_data.edit_root_folder.is_none());
|
assert!(app.data.radarr_data.edit_root_folder.is_none());
|
||||||
assert!(!app.data.radarr_data.prompt_confirm);
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
@@ -472,7 +473,7 @@ mod tests {
|
|||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::AddRootFolderPrompt.into()
|
ActiveRadarrBlock::AddRootFolderPrompt.into()
|
||||||
);
|
);
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.radarr_data.edit_root_folder.is_some());
|
assert!(app.data.radarr_data.edit_root_folder.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -499,7 +500,7 @@ mod tests {
|
|||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::RootFolders.into()
|
ActiveRadarrBlock::RootFolders.into()
|
||||||
);
|
);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.radarr_data.edit_root_folder.is_none());
|
assert!(app.data.radarr_data.edit_root_folder.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,7 +590,7 @@ mod tests {
|
|||||||
app.data.radarr_data.edit_root_folder = Some(HorizontallyScrollableText::default());
|
app.data.radarr_data.edit_root_folder = Some(HorizontallyScrollableText::default());
|
||||||
|
|
||||||
RootFoldersHandler::new(
|
RootFoldersHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::AddRootFolderPrompt,
|
ActiveRadarrBlock::AddRootFolderPrompt,
|
||||||
None,
|
None,
|
||||||
@@ -598,7 +599,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_str_eq!(
|
assert_str_eq!(
|
||||||
app.data.radarr_data.edit_root_folder.as_ref().unwrap().text,
|
app.data.radarr_data.edit_root_folder.as_ref().unwrap().text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -644,6 +645,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_root_folders_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = RootFoldersHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_add_root_folder_body() {
|
fn test_build_add_root_folder_body() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::radarr_handlers::handle_change_tab_left_right_keys;
|
||||||
use crate::handlers::radarr_handlers::system::system_details_handler::SystemDetailsHandler;
|
use crate::handlers::radarr_handlers::system::system_details_handler::SystemDetailsHandler;
|
||||||
use crate::handlers::{handle_clear_errors, KeyEventHandler};
|
use crate::handlers::{handle_clear_errors, KeyEventHandler};
|
||||||
|
use crate::matches_key;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
use crate::models::servarr_data::radarr::radarr_data::ActiveRadarrBlock;
|
||||||
use crate::models::Scrollable;
|
use crate::models::Scrollable;
|
||||||
|
|
||||||
@@ -35,6 +35,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for SystemHandler<'a, 'b
|
|||||||
SystemDetailsHandler::accepts(active_block) || active_block == ActiveRadarrBlock::System
|
SystemDetailsHandler::accepts(active_block) || active_block == ActiveRadarrBlock::System
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -86,15 +90,15 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for SystemHandler<'a, 'b
|
|||||||
if self.active_radarr_block == ActiveRadarrBlock::System {
|
if self.active_radarr_block == ActiveRadarrBlock::System {
|
||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.key {
|
match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.events.key => {
|
_ if matches_key!(events, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::SystemQueuedEvents.into());
|
.push_navigation_stack(ActiveRadarrBlock::SystemQueuedEvents.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.logs.key => {
|
_ if matches_key!(logs, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::SystemLogs.into());
|
.push_navigation_stack(ActiveRadarrBlock::SystemLogs.into());
|
||||||
@@ -106,12 +110,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for SystemHandler<'a, 'b
|
|||||||
.set_items(self.app.data.radarr_data.logs.items.to_vec());
|
.set_items(self.app.data.radarr_data.logs.items.to_vec());
|
||||||
self.app.data.radarr_data.log_details.scroll_to_bottom();
|
self.app.data.radarr_data.log_details.scroll_to_bottom();
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.tasks.key => {
|
_ if matches_key!(tasks, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::SystemTasks.into());
|
.push_navigation_stack(ActiveRadarrBlock::SystemTasks.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.update.key => {
|
_ if matches_key!(update, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveRadarrBlock::SystemUpdates.into());
|
.push_navigation_stack(ActiveRadarrBlock::SystemUpdates.into());
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
|
use crate::matches_key;
|
||||||
use crate::models::radarr_models::RadarrTaskName;
|
use crate::models::radarr_models::RadarrTaskName;
|
||||||
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS};
|
use crate::models::servarr_data::radarr::radarr_data::{ActiveRadarrBlock, SYSTEM_DETAILS_BLOCKS};
|
||||||
use crate::models::stateful_list::StatefulList;
|
use crate::models::stateful_list::StatefulList;
|
||||||
@@ -36,6 +36,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for SystemDetailsHandler
|
|||||||
SYSTEM_DETAILS_BLOCKS.contains(&active_block)
|
SYSTEM_DETAILS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -114,7 +118,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for SystemDetailsHandler
|
|||||||
|
|
||||||
match self.active_radarr_block {
|
match self.active_radarr_block {
|
||||||
ActiveRadarrBlock::SystemLogs => match self.key {
|
ActiveRadarrBlock::SystemLogs => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.left.key => {
|
_ if matches_key!(left, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.data
|
.data
|
||||||
@@ -124,7 +128,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for SystemDetailsHandler
|
|||||||
.iter()
|
.iter()
|
||||||
.for_each(|log| log.scroll_right());
|
.for_each(|log| log.scroll_right());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.right.key => {
|
_ if matches_key!(right, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.data
|
.data
|
||||||
@@ -178,14 +182,13 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for SystemDetailsHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_char_key_event(&mut self) {
|
fn handle_char_key_event(&mut self) {
|
||||||
if SYSTEM_DETAILS_BLOCKS.contains(&self.active_radarr_block)
|
if SYSTEM_DETAILS_BLOCKS.contains(&self.active_radarr_block) && matches_key!(refresh, self.key)
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.refresh.key
|
|
||||||
{
|
{
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.active_radarr_block == ActiveRadarrBlock::SystemTaskStartConfirmPrompt
|
if self.active_radarr_block == ActiveRadarrBlock::SystemTaskStartConfirmPrompt
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, self.key)
|
||||||
{
|
{
|
||||||
self.app.data.radarr_data.prompt_confirm = true;
|
self.app.data.radarr_data.prompt_confirm = true;
|
||||||
self.app.data.radarr_data.prompt_confirm_action =
|
self.app.data.radarr_data.prompt_confirm_action =
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -938,6 +939,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_system_details_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = SystemDetailsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_task_name() {
|
fn test_extract_task_name() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -450,6 +450,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_system_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = SystemHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveRadarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_system_handler_is_not_ready_when_loading() {
|
fn test_system_handler_is_not_ready_when_loading() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ mod tests {
|
|||||||
|
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -513,6 +514,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_blocklist_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = BlocklistHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_blocklist_item_id() {
|
fn test_extract_blocklist_item_id() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys;
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -9,6 +7,7 @@ use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, BLOCKL
|
|||||||
use crate::models::sonarr_models::BlocklistItem;
|
use crate::models::sonarr_models::BlocklistItem;
|
||||||
use crate::models::stateful_table::SortOption;
|
use crate::models::stateful_table::SortOption;
|
||||||
use crate::network::sonarr_network::SonarrEvent;
|
use crate::network::sonarr_network::SonarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "blocklist_handler_tests.rs"]
|
#[path = "blocklist_handler_tests.rs"]
|
||||||
@@ -51,6 +50,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for BlocklistHandler<'a,
|
|||||||
BLOCKLIST_BLOCKS.contains(&active_block)
|
BLOCKLIST_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -143,10 +146,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for BlocklistHandler<'a,
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_sonarr_block {
|
match self.active_sonarr_block {
|
||||||
ActiveSonarrBlock::Blocklist => match self.key {
|
ActiveSonarrBlock::Blocklist => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.clear.key => {
|
_ if matches_key!(clear, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::BlocklistClearAllItemsPrompt.into());
|
.push_navigation_stack(ActiveSonarrBlock::BlocklistClearAllItemsPrompt.into());
|
||||||
@@ -154,7 +157,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for BlocklistHandler<'a,
|
|||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveSonarrBlock::DeleteBlocklistItemPrompt => {
|
ActiveSonarrBlock::DeleteBlocklistItemPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::DeleteBlocklistItem(
|
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::DeleteBlocklistItem(
|
||||||
self.extract_blocklist_item_id(),
|
self.extract_blocklist_item_id(),
|
||||||
@@ -164,7 +167,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for BlocklistHandler<'a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::BlocklistClearAllItemsPrompt => {
|
ActiveSonarrBlock::BlocklistClearAllItemsPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::ClearBlocklist);
|
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::ClearBlocklist);
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -389,6 +390,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_downloads_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = DownloadsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_download_id() {
|
fn test_extract_download_id() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys;
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler};
|
||||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DOWNLOADS_BLOCKS};
|
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DOWNLOADS_BLOCKS};
|
||||||
use crate::models::sonarr_models::DownloadRecord;
|
use crate::models::sonarr_models::DownloadRecord;
|
||||||
use crate::network::sonarr_network::SonarrEvent;
|
use crate::network::sonarr_network::SonarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "downloads_handler_tests.rs"]
|
#[path = "downloads_handler_tests.rs"]
|
||||||
@@ -47,6 +46,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for DownloadsHandler<'a,
|
|||||||
DOWNLOADS_BLOCKS.contains(&active_block)
|
DOWNLOADS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -130,18 +133,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for DownloadsHandler<'a,
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_sonarr_block {
|
match self.active_sonarr_block {
|
||||||
ActiveSonarrBlock::Downloads => match self.key {
|
ActiveSonarrBlock::Downloads => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.update.key => {
|
_ if matches_key!(update, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::UpdateDownloadsPrompt.into());
|
.push_navigation_stack(ActiveSonarrBlock::UpdateDownloadsPrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveSonarrBlock::DeleteDownloadPrompt => {
|
ActiveSonarrBlock::DeleteDownloadPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action =
|
self.app.data.sonarr_data.prompt_confirm_action =
|
||||||
Some(SonarrEvent::DeleteDownload(self.extract_download_id()));
|
Some(SonarrEvent::DeleteDownload(self.extract_download_id()));
|
||||||
@@ -150,7 +153,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for DownloadsHandler<'a,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::UpdateDownloadsPrompt => {
|
ActiveSonarrBlock::UpdateDownloadsPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::UpdateDownloads);
|
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::UpdateDownloads);
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ mod tests {
|
|||||||
|
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -306,6 +307,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_history_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = HistoryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_history_handler_not_ready_when_loading() {
|
fn test_history_handler_not_ready_when_loading() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys;
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_clear_errors, KeyEventHandler};
|
use crate::handlers::{handle_clear_errors, KeyEventHandler};
|
||||||
@@ -9,6 +7,7 @@ use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, HISTOR
|
|||||||
use crate::models::servarr_models::Language;
|
use crate::models::servarr_models::Language;
|
||||||
use crate::models::sonarr_models::SonarrHistoryItem;
|
use crate::models::sonarr_models::SonarrHistoryItem;
|
||||||
use crate::models::stateful_table::SortOption;
|
use crate::models::stateful_table::SortOption;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "history_handler_tests.rs"]
|
#[path = "history_handler_tests.rs"]
|
||||||
@@ -52,6 +51,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for HistoryHandler<'a, '
|
|||||||
HISTORY_BLOCKS.contains(&active_block)
|
HISTORY_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -110,7 +113,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for HistoryHandler<'a, '
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
if self.active_sonarr_block == ActiveSonarrBlock::History {
|
if self.active_sonarr_block == ActiveSonarrBlock::History {
|
||||||
match self.key {
|
match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -6,7 +5,9 @@ use crate::models::servarr_data::modals::EditIndexerModal;
|
|||||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_INDEXER_BLOCKS};
|
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_INDEXER_BLOCKS};
|
||||||
use crate::models::servarr_models::EditIndexerParams;
|
use crate::models::servarr_models::EditIndexerParams;
|
||||||
use crate::network::sonarr_network::SonarrEvent;
|
use crate::network::sonarr_network::SonarrEvent;
|
||||||
use crate::{handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys};
|
use crate::{
|
||||||
|
handle_prompt_left_right_keys, handle_text_box_keys, handle_text_box_left_right_keys, matches_key,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "edit_indexer_handler_tests.rs"]
|
#[path = "edit_indexer_handler_tests.rs"]
|
||||||
@@ -64,6 +65,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditIndexerHandler<'
|
|||||||
EDIT_INDEXER_BLOCKS.contains(&active_block)
|
EDIT_INDEXER_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -355,7 +360,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditIndexerHandler<'
|
|||||||
| ActiveSonarrBlock::EditIndexerSeedRatioInput
|
| ActiveSonarrBlock::EditIndexerSeedRatioInput
|
||||||
| ActiveSonarrBlock::EditIndexerTagsInput => {
|
| ActiveSonarrBlock::EditIndexerTagsInput => {
|
||||||
self.app.push_navigation_stack(selected_block.into());
|
self.app.push_navigation_stack(selected_block.into());
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::EditIndexerPriorityInput => self
|
ActiveSonarrBlock::EditIndexerPriorityInput => self
|
||||||
.app
|
.app
|
||||||
@@ -401,7 +406,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditIndexerHandler<'
|
|||||||
| ActiveSonarrBlock::EditIndexerSeedRatioInput
|
| ActiveSonarrBlock::EditIndexerSeedRatioInput
|
||||||
| ActiveSonarrBlock::EditIndexerTagsInput => {
|
| ActiveSonarrBlock::EditIndexerTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::EditIndexerPriorityInput => self.app.pop_navigation_stack(),
|
ActiveSonarrBlock::EditIndexerPriorityInput => self.app.pop_navigation_stack(),
|
||||||
_ => (),
|
_ => (),
|
||||||
@@ -422,7 +427,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditIndexerHandler<'
|
|||||||
| ActiveSonarrBlock::EditIndexerPriorityInput
|
| ActiveSonarrBlock::EditIndexerPriorityInput
|
||||||
| ActiveSonarrBlock::EditIndexerTagsInput => {
|
| ActiveSonarrBlock::EditIndexerTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => self.app.pop_navigation_stack(),
|
_ => self.app.pop_navigation_stack(),
|
||||||
}
|
}
|
||||||
@@ -503,7 +508,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditIndexerHandler<'
|
|||||||
ActiveSonarrBlock::EditIndexerPrompt => {
|
ActiveSonarrBlock::EditIndexerPrompt => {
|
||||||
if self.app.data.sonarr_data.selected_block.get_active_block()
|
if self.app.data.sonarr_data.selected_block.get_active_block()
|
||||||
== ActiveSonarrBlock::EditIndexerConfirmPrompt
|
== ActiveSonarrBlock::EditIndexerConfirmPrompt
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, self.key)
|
||||||
{
|
{
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action =
|
self.app.data.sonarr_data.prompt_confirm_action =
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ mod tests {
|
|||||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_INDEXER_BLOCKS};
|
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_INDEXER_BLOCKS};
|
||||||
use crate::models::servarr_models::EditIndexerParams;
|
use crate::models::servarr_models::EditIndexerParams;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
mod test_handle_scroll_up_and_down {
|
mod test_handle_scroll_up_and_down {
|
||||||
@@ -1002,7 +1003,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), block.into());
|
assert_eq!(app.get_current_route(), block.into());
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1027,7 +1028,7 @@ mod tests {
|
|||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveSonarrBlock::EditIndexerPriorityInput.into()
|
ActiveSonarrBlock::EditIndexerPriorityInput.into()
|
||||||
);
|
);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1193,7 +1194,7 @@ mod tests {
|
|||||||
fn test_edit_indexer_name_input_submit() {
|
fn test_edit_indexer_name_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Indexers.into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
||||||
name: "Test".into(),
|
name: "Test".into(),
|
||||||
..EditIndexerModal::default()
|
..EditIndexerModal::default()
|
||||||
@@ -1209,7 +1210,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.sonarr_data
|
.sonarr_data
|
||||||
@@ -1229,7 +1230,7 @@ mod tests {
|
|||||||
fn test_edit_indexer_url_input_submit() {
|
fn test_edit_indexer_url_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Indexers.into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
||||||
url: "Test".into(),
|
url: "Test".into(),
|
||||||
..EditIndexerModal::default()
|
..EditIndexerModal::default()
|
||||||
@@ -1245,7 +1246,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.sonarr_data
|
.sonarr_data
|
||||||
@@ -1265,7 +1266,7 @@ mod tests {
|
|||||||
fn test_edit_indexer_api_key_input_submit() {
|
fn test_edit_indexer_api_key_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Indexers.into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
||||||
api_key: "Test".into(),
|
api_key: "Test".into(),
|
||||||
..EditIndexerModal::default()
|
..EditIndexerModal::default()
|
||||||
@@ -1281,7 +1282,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.sonarr_data
|
.sonarr_data
|
||||||
@@ -1301,7 +1302,7 @@ mod tests {
|
|||||||
fn test_edit_indexer_seed_ratio_input_submit() {
|
fn test_edit_indexer_seed_ratio_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Indexers.into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
||||||
seed_ratio: "Test".into(),
|
seed_ratio: "Test".into(),
|
||||||
..EditIndexerModal::default()
|
..EditIndexerModal::default()
|
||||||
@@ -1317,7 +1318,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.sonarr_data
|
.sonarr_data
|
||||||
@@ -1337,7 +1338,7 @@ mod tests {
|
|||||||
fn test_edit_indexer_tags_input_submit() {
|
fn test_edit_indexer_tags_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Indexers.into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal {
|
||||||
tags: "Test".into(),
|
tags: "Test".into(),
|
||||||
..EditIndexerModal::default()
|
..EditIndexerModal::default()
|
||||||
@@ -1353,7 +1354,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.sonarr_data
|
.sonarr_data
|
||||||
@@ -1417,12 +1418,12 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveSonarrBlock::Indexers.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Indexers.into());
|
||||||
app.push_navigation_stack(active_sonarr_block.into());
|
app.push_navigation_stack(active_sonarr_block.into());
|
||||||
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
|
||||||
EditIndexerHandler::new(ESC_KEY, &mut app, active_sonarr_block, None).handle();
|
EditIndexerHandler::new(ESC_KEY, &mut app, active_sonarr_block, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into());
|
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Indexers.into());
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.data.sonarr_data.edit_indexer_modal,
|
app.data.sonarr_data.edit_indexer_modal,
|
||||||
Some(EditIndexerModal::default())
|
Some(EditIndexerModal::default())
|
||||||
@@ -1597,7 +1598,7 @@ mod tests {
|
|||||||
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||||
|
|
||||||
EditIndexerHandler::new(
|
EditIndexerHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::EditIndexerNameInput,
|
ActiveSonarrBlock::EditIndexerNameInput,
|
||||||
None,
|
None,
|
||||||
@@ -1613,7 +1614,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.name
|
.name
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1624,7 +1625,7 @@ mod tests {
|
|||||||
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||||
|
|
||||||
EditIndexerHandler::new(
|
EditIndexerHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::EditIndexerUrlInput,
|
ActiveSonarrBlock::EditIndexerUrlInput,
|
||||||
None,
|
None,
|
||||||
@@ -1640,7 +1641,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.url
|
.url
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1651,7 +1652,7 @@ mod tests {
|
|||||||
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||||
|
|
||||||
EditIndexerHandler::new(
|
EditIndexerHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::EditIndexerApiKeyInput,
|
ActiveSonarrBlock::EditIndexerApiKeyInput,
|
||||||
None,
|
None,
|
||||||
@@ -1667,7 +1668,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.api_key
|
.api_key
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1678,7 +1679,7 @@ mod tests {
|
|||||||
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||||
|
|
||||||
EditIndexerHandler::new(
|
EditIndexerHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::EditIndexerSeedRatioInput,
|
ActiveSonarrBlock::EditIndexerSeedRatioInput,
|
||||||
None,
|
None,
|
||||||
@@ -1694,7 +1695,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.seed_ratio
|
.seed_ratio
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1705,7 +1706,7 @@ mod tests {
|
|||||||
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
app.data.sonarr_data.edit_indexer_modal = Some(EditIndexerModal::default());
|
||||||
|
|
||||||
EditIndexerHandler::new(
|
EditIndexerHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::EditIndexerTagsInput,
|
ActiveSonarrBlock::EditIndexerTagsInput,
|
||||||
None,
|
None,
|
||||||
@@ -1721,7 +1722,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.tags
|
.tags
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1793,6 +1794,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_edit_indexer_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = EditIndexerHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_edit_indexer_params() {
|
fn test_build_edit_indexer_params() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_prompt_left_right_keys;
|
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
use crate::models::servarr_data::sonarr::sonarr_data::{
|
use crate::models::servarr_data::sonarr::sonarr_data::{
|
||||||
ActiveSonarrBlock, INDEXER_SETTINGS_BLOCKS,
|
ActiveSonarrBlock, INDEXER_SETTINGS_BLOCKS,
|
||||||
};
|
};
|
||||||
use crate::models::sonarr_models::IndexerSettings;
|
use crate::models::sonarr_models::IndexerSettings;
|
||||||
use crate::network::sonarr_network::SonarrEvent;
|
use crate::network::sonarr_network::SonarrEvent;
|
||||||
|
use crate::{handle_prompt_left_right_keys, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "edit_indexer_settings_handler_tests.rs"]
|
#[path = "edit_indexer_settings_handler_tests.rs"]
|
||||||
@@ -37,6 +36,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexerSettingsHandl
|
|||||||
INDEXER_SETTINGS_BLOCKS.contains(&active_block)
|
INDEXER_SETTINGS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -183,7 +186,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexerSettingsHandl
|
|||||||
if self.active_sonarr_block == ActiveSonarrBlock::AllIndexerSettingsPrompt
|
if self.active_sonarr_block == ActiveSonarrBlock::AllIndexerSettingsPrompt
|
||||||
&& self.app.data.sonarr_data.selected_block.get_active_block()
|
&& self.app.data.sonarr_data.selected_block.get_active_block()
|
||||||
== ActiveSonarrBlock::IndexerSettingsConfirmPrompt
|
== ActiveSonarrBlock::IndexerSettingsConfirmPrompt
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, self.key)
|
||||||
{
|
{
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::EditAllIndexerSettings(
|
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::EditAllIndexerSettings(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -521,6 +522,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_indexer_settings_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = IndexerSettingsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_edit_indexer_settings_params() {
|
fn test_build_edit_indexer_settings_params() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -643,6 +643,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_indexers_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = IndexersHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_indexer_id() {
|
fn test_extract_indexer_id() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys;
|
||||||
use crate::handlers::sonarr_handlers::indexers::edit_indexer_handler::EditIndexerHandler;
|
use crate::handlers::sonarr_handlers::indexers::edit_indexer_handler::EditIndexerHandler;
|
||||||
use crate::handlers::sonarr_handlers::indexers::edit_indexer_settings_handler::IndexerSettingsHandler;
|
use crate::handlers::sonarr_handlers::indexers::edit_indexer_settings_handler::IndexerSettingsHandler;
|
||||||
@@ -15,6 +13,7 @@ use crate::models::servarr_data::sonarr::sonarr_data::{
|
|||||||
use crate::models::servarr_models::Indexer;
|
use crate::models::servarr_models::Indexer;
|
||||||
use crate::models::BlockSelectionState;
|
use crate::models::BlockSelectionState;
|
||||||
use crate::network::sonarr_network::SonarrEvent;
|
use crate::network::sonarr_network::SonarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
mod edit_indexer_handler;
|
mod edit_indexer_handler;
|
||||||
mod edit_indexer_settings_handler;
|
mod edit_indexer_settings_handler;
|
||||||
@@ -70,6 +69,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexersHandler<'a,
|
|||||||
|| INDEXERS_BLOCKS.contains(&active_block)
|
|| INDEXERS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -168,20 +171,20 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexersHandler<'a,
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_sonarr_block {
|
match self.active_sonarr_block {
|
||||||
ActiveSonarrBlock::Indexers => match self.key {
|
ActiveSonarrBlock::Indexers => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.test.key => {
|
_ if matches_key!(test, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::TestIndexer.into());
|
.push_navigation_stack(ActiveSonarrBlock::TestIndexer.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.test_all.key => {
|
_ if matches_key!(test_all, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::TestAllIndexers.into());
|
.push_navigation_stack(ActiveSonarrBlock::TestAllIndexers.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.settings.key => {
|
_ if matches_key!(settings, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::AllIndexerSettingsPrompt.into());
|
.push_navigation_stack(ActiveSonarrBlock::AllIndexerSettingsPrompt.into());
|
||||||
@@ -191,7 +194,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexersHandler<'a,
|
|||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveSonarrBlock::DeleteIndexerPrompt => {
|
ActiveSonarrBlock::DeleteIndexerPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action =
|
self.app.data.sonarr_data.prompt_confirm_action =
|
||||||
Some(SonarrEvent::DeleteIndexer(self.extract_indexer_id()));
|
Some(SonarrEvent::DeleteIndexer(self.extract_indexer_id()));
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for TestAllIndexersHandl
|
|||||||
active_block == ActiveSonarrBlock::TestAllIndexers
|
active_block == ActiveSonarrBlock::TestAllIndexers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ mod tests {
|
|||||||
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
use crate::models::servarr_data::modals::IndexerTestResultModalItem;
|
||||||
use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock;
|
use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock;
|
||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
mod test_handle_esc {
|
mod test_handle_esc {
|
||||||
@@ -48,6 +49,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_test_all_indexers_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = TestAllIndexersHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_test_all_indexers_handler_is_not_ready_when_loading() {
|
fn test_test_all_indexers_handler_is_not_ready_when_loading() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
use crate::models::servarr_data::sonarr::modals::AddSeriesModal;
|
use crate::models::servarr_data::sonarr::modals::AddSeriesModal;
|
||||||
@@ -9,7 +8,9 @@ use crate::models::sonarr_models::{AddSeriesBody, AddSeriesOptions, AddSeriesSea
|
|||||||
use crate::models::stateful_table::StatefulTable;
|
use crate::models::stateful_table::StatefulTable;
|
||||||
use crate::models::{BlockSelectionState, Scrollable};
|
use crate::models::{BlockSelectionState, Scrollable};
|
||||||
use crate::network::sonarr_network::SonarrEvent;
|
use crate::network::sonarr_network::SonarrEvent;
|
||||||
use crate::{handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys, App, Key};
|
use crate::{
|
||||||
|
handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys, matches_key, App, Key,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "add_series_handler_tests.rs"]
|
#[path = "add_series_handler_tests.rs"]
|
||||||
@@ -126,6 +127,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for AddSeriesHandler<'a,
|
|||||||
ADD_SERIES_BLOCKS.contains(&active_block)
|
ADD_SERIES_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -440,7 +445,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for AddSeriesHandler<'a,
|
|||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::AddSeriesSearchResults.into());
|
.push_navigation_stack(ActiveSonarrBlock::AddSeriesSearchResults.into());
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ if self.active_sonarr_block == ActiveSonarrBlock::AddSeriesSearchResults
|
_ if self.active_sonarr_block == ActiveSonarrBlock::AddSeriesSearchResults
|
||||||
&& self.app.data.sonarr_data.add_searched_series.is_some() =>
|
&& self.app.data.sonarr_data.add_searched_series.is_some() =>
|
||||||
@@ -509,7 +514,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for AddSeriesHandler<'a,
|
|||||||
.get_active_block()
|
.get_active_block()
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::AddSeriesToggleUseSeasonFolder => {
|
ActiveSonarrBlock::AddSeriesToggleUseSeasonFolder => {
|
||||||
self
|
self
|
||||||
@@ -538,7 +543,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for AddSeriesHandler<'a,
|
|||||||
| ActiveSonarrBlock::AddSeriesSelectRootFolder => self.app.pop_navigation_stack(),
|
| ActiveSonarrBlock::AddSeriesSelectRootFolder => self.app.pop_navigation_stack(),
|
||||||
ActiveSonarrBlock::AddSeriesTagsInput => {
|
ActiveSonarrBlock::AddSeriesTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@@ -549,13 +554,13 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for AddSeriesHandler<'a,
|
|||||||
ActiveSonarrBlock::AddSeriesSearchInput => {
|
ActiveSonarrBlock::AddSeriesSearchInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.data.sonarr_data.add_series_search = None;
|
self.app.data.sonarr_data.add_series_search = None;
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::AddSeriesSearchResults
|
ActiveSonarrBlock::AddSeriesSearchResults
|
||||||
| ActiveSonarrBlock::AddSeriesEmptySearchResults => {
|
| ActiveSonarrBlock::AddSeriesEmptySearchResults => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.data.sonarr_data.add_searched_series = None;
|
self.app.data.sonarr_data.add_searched_series = None;
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::AddSeriesPrompt => {
|
ActiveSonarrBlock::AddSeriesPrompt => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
@@ -570,7 +575,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for AddSeriesHandler<'a,
|
|||||||
| ActiveSonarrBlock::AddSeriesSelectRootFolder => self.app.pop_navigation_stack(),
|
| ActiveSonarrBlock::AddSeriesSelectRootFolder => self.app.pop_navigation_stack(),
|
||||||
ActiveSonarrBlock::AddSeriesTagsInput => {
|
ActiveSonarrBlock::AddSeriesTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@@ -609,7 +614,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for AddSeriesHandler<'a,
|
|||||||
ActiveSonarrBlock::AddSeriesPrompt => {
|
ActiveSonarrBlock::AddSeriesPrompt => {
|
||||||
if self.app.data.sonarr_data.selected_block.get_active_block()
|
if self.app.data.sonarr_data.selected_block.get_active_block()
|
||||||
== ActiveSonarrBlock::AddSeriesConfirmPrompt
|
== ActiveSonarrBlock::AddSeriesConfirmPrompt
|
||||||
&& key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, key)
|
||||||
{
|
{
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action =
|
self.app.data.sonarr_data.prompt_confirm_action =
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
mod tests {
|
mod tests {
|
||||||
use bimap::BiMap;
|
use bimap::BiMap;
|
||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -912,7 +913,7 @@ mod tests {
|
|||||||
fn test_add_series_search_input_submit() {
|
fn test_add_series_search_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.sonarr_data.add_series_search = Some("test".into());
|
app.data.sonarr_data.add_series_search = Some("test".into());
|
||||||
|
|
||||||
AddSeriesHandler::new(
|
AddSeriesHandler::new(
|
||||||
@@ -923,7 +924,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveSonarrBlock::AddSeriesSearchResults.into()
|
ActiveSonarrBlock::AddSeriesSearchResults.into()
|
||||||
@@ -936,7 +937,7 @@ mod tests {
|
|||||||
app.data.sonarr_data.add_series_search = Some(HorizontallyScrollableText::default());
|
app.data.sonarr_data.add_series_search = Some(HorizontallyScrollableText::default());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::AddSeriesSearchInput.into());
|
app.push_navigation_stack(ActiveSonarrBlock::AddSeriesSearchInput.into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
|
||||||
AddSeriesHandler::new(
|
AddSeriesHandler::new(
|
||||||
SUBMIT_KEY,
|
SUBMIT_KEY,
|
||||||
@@ -946,7 +947,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveSonarrBlock::AddSeriesSearchInput.into()
|
ActiveSonarrBlock::AddSeriesSearchInput.into()
|
||||||
@@ -1230,7 +1231,7 @@ mod tests {
|
|||||||
assert_eq!(app.data.sonarr_data.prompt_confirm_action, None);
|
assert_eq!(app.data.sonarr_data.prompt_confirm_action, None);
|
||||||
|
|
||||||
if selected_block == ActiveSonarrBlock::AddSeriesTagsInput {
|
if selected_block == ActiveSonarrBlock::AddSeriesTagsInput {
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1259,7 +1260,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if active_sonarr_block == ActiveSonarrBlock::AddSeriesTagsInput {
|
if active_sonarr_block == ActiveSonarrBlock::AddSeriesTagsInput {
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1336,7 +1337,7 @@ mod tests {
|
|||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.is_loading = is_ready;
|
app.is_loading = is_ready;
|
||||||
app.data.sonarr_data = create_test_sonarr_data();
|
app.data.sonarr_data = create_test_sonarr_data();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::AddSeriesSearchInput.into());
|
app.push_navigation_stack(ActiveSonarrBlock::AddSeriesSearchInput.into());
|
||||||
|
|
||||||
@@ -1348,7 +1349,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into());
|
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into());
|
||||||
assert_eq!(app.data.sonarr_data.add_series_search, None);
|
assert_eq!(app.data.sonarr_data.add_series_search, None);
|
||||||
}
|
}
|
||||||
@@ -1357,7 +1358,7 @@ mod tests {
|
|||||||
fn test_add_series_input_esc() {
|
fn test_add_series_input_esc() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.data.sonarr_data = create_test_sonarr_data();
|
app.data.sonarr_data = create_test_sonarr_data();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::AddSeriesPrompt.into());
|
app.push_navigation_stack(ActiveSonarrBlock::AddSeriesPrompt.into());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::AddSeriesTagsInput.into());
|
app.push_navigation_stack(ActiveSonarrBlock::AddSeriesTagsInput.into());
|
||||||
@@ -1370,7 +1371,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveSonarrBlock::AddSeriesPrompt.into()
|
ActiveSonarrBlock::AddSeriesPrompt.into()
|
||||||
@@ -1403,7 +1404,7 @@ mod tests {
|
|||||||
ActiveSonarrBlock::AddSeriesSearchInput.into()
|
ActiveSonarrBlock::AddSeriesSearchInput.into()
|
||||||
);
|
);
|
||||||
assert!(app.data.sonarr_data.add_searched_series.is_none());
|
assert!(app.data.sonarr_data.add_searched_series.is_none());
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -1451,7 +1452,7 @@ mod tests {
|
|||||||
fn test_add_series_tags_input_esc() {
|
fn test_add_series_tags_input_esc() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.data.sonarr_data = create_test_sonarr_data();
|
app.data.sonarr_data = create_test_sonarr_data();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::AddSeriesPrompt.into());
|
app.push_navigation_stack(ActiveSonarrBlock::AddSeriesPrompt.into());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::AddSeriesTagsInput.into());
|
app.push_navigation_stack(ActiveSonarrBlock::AddSeriesTagsInput.into());
|
||||||
@@ -1464,7 +1465,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveSonarrBlock::AddSeriesPrompt.into()
|
ActiveSonarrBlock::AddSeriesPrompt.into()
|
||||||
@@ -1570,7 +1571,7 @@ mod tests {
|
|||||||
app.data.sonarr_data.add_series_search = Some(HorizontallyScrollableText::default());
|
app.data.sonarr_data.add_series_search = Some(HorizontallyScrollableText::default());
|
||||||
|
|
||||||
AddSeriesHandler::new(
|
AddSeriesHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::AddSeriesSearchInput,
|
ActiveSonarrBlock::AddSeriesSearchInput,
|
||||||
None,
|
None,
|
||||||
@@ -1585,7 +1586,7 @@ mod tests {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1596,7 +1597,7 @@ mod tests {
|
|||||||
app.data.sonarr_data.add_series_modal = Some(AddSeriesModal::default());
|
app.data.sonarr_data.add_series_modal = Some(AddSeriesModal::default());
|
||||||
|
|
||||||
AddSeriesHandler::new(
|
AddSeriesHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::AddSeriesTagsInput,
|
ActiveSonarrBlock::AddSeriesTagsInput,
|
||||||
None,
|
None,
|
||||||
@@ -1612,7 +1613,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.tags
|
.tags
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1714,6 +1715,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_add_series_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = AddSeriesHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_add_series_search_no_panic_on_none_search_result() {
|
fn test_add_series_search_no_panic_on_none_search_result() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
use crate::models::sonarr_models::DeleteSeriesParams;
|
use crate::models::sonarr_models::DeleteSeriesParams;
|
||||||
use crate::network::sonarr_network::SonarrEvent;
|
use crate::network::sonarr_network::SonarrEvent;
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{key_binding::DEFAULT_KEYBINDINGS, App},
|
app::App,
|
||||||
event::Key,
|
event::Key,
|
||||||
handlers::{handle_prompt_toggle, KeyEventHandler},
|
handlers::{handle_prompt_toggle, KeyEventHandler},
|
||||||
|
matches_key,
|
||||||
models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DELETE_SERIES_BLOCKS},
|
models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, DELETE_SERIES_BLOCKS},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -38,6 +39,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for DeleteSeriesHandler<
|
|||||||
DELETE_SERIES_BLOCKS.contains(&active_block)
|
DELETE_SERIES_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -123,7 +128,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for DeleteSeriesHandler<
|
|||||||
if self.active_sonarr_block == ActiveSonarrBlock::DeleteSeriesPrompt
|
if self.active_sonarr_block == ActiveSonarrBlock::DeleteSeriesPrompt
|
||||||
&& self.app.data.sonarr_data.selected_block.get_active_block()
|
&& self.app.data.sonarr_data.selected_block.get_active_block()
|
||||||
== ActiveSonarrBlock::DeleteSeriesConfirmPrompt
|
== ActiveSonarrBlock::DeleteSeriesConfirmPrompt
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, self.key)
|
||||||
{
|
{
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action =
|
self.app.data.sonarr_data.prompt_confirm_action =
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -320,6 +321,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_delete_series_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = DeleteSeriesHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_delete_series_params() {
|
fn test_build_delete_series_params() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -7,7 +6,7 @@ use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EDIT_S
|
|||||||
use crate::models::sonarr_models::EditSeriesParams;
|
use crate::models::sonarr_models::EditSeriesParams;
|
||||||
use crate::models::Scrollable;
|
use crate::models::Scrollable;
|
||||||
use crate::network::sonarr_network::SonarrEvent;
|
use crate::network::sonarr_network::SonarrEvent;
|
||||||
use crate::{handle_text_box_keys, handle_text_box_left_right_keys};
|
use crate::{handle_text_box_keys, handle_text_box_left_right_keys, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "edit_series_handler_tests.rs"]
|
#[path = "edit_series_handler_tests.rs"]
|
||||||
@@ -83,6 +82,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditSeriesHandler<'a
|
|||||||
EDIT_SERIES_BLOCKS.contains(&active_block)
|
EDIT_SERIES_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -342,7 +345,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditSeriesHandler<'a
|
|||||||
)
|
)
|
||||||
.into(),
|
.into(),
|
||||||
);
|
);
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::EditSeriesToggleMonitored => {
|
ActiveSonarrBlock::EditSeriesToggleMonitored => {
|
||||||
self
|
self
|
||||||
@@ -392,7 +395,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditSeriesHandler<'a
|
|||||||
| ActiveSonarrBlock::EditSeriesSelectLanguageProfile => self.app.pop_navigation_stack(),
|
| ActiveSonarrBlock::EditSeriesSelectLanguageProfile => self.app.pop_navigation_stack(),
|
||||||
ActiveSonarrBlock::EditSeriesPathInput | ActiveSonarrBlock::EditSeriesTagsInput => {
|
ActiveSonarrBlock::EditSeriesPathInput | ActiveSonarrBlock::EditSeriesTagsInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@@ -402,7 +405,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditSeriesHandler<'a
|
|||||||
match self.active_sonarr_block {
|
match self.active_sonarr_block {
|
||||||
ActiveSonarrBlock::EditSeriesTagsInput | ActiveSonarrBlock::EditSeriesPathInput => {
|
ActiveSonarrBlock::EditSeriesTagsInput | ActiveSonarrBlock::EditSeriesPathInput => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::EditSeriesPrompt => {
|
ActiveSonarrBlock::EditSeriesPrompt => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
@@ -450,7 +453,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditSeriesHandler<'a
|
|||||||
ActiveSonarrBlock::EditSeriesPrompt => {
|
ActiveSonarrBlock::EditSeriesPrompt => {
|
||||||
if self.app.data.sonarr_data.selected_block.get_active_block()
|
if self.app.data.sonarr_data.selected_block.get_active_block()
|
||||||
== ActiveSonarrBlock::EditSeriesConfirmPrompt
|
== ActiveSonarrBlock::EditSeriesConfirmPrompt
|
||||||
&& key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, key)
|
||||||
{
|
{
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action =
|
self.app.data.sonarr_data.prompt_confirm_action =
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
mod tests {
|
mod tests {
|
||||||
use bimap::BiMap;
|
use bimap::BiMap;
|
||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -677,7 +678,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_edit_series_path_input_submit() {
|
fn test_edit_series_path_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal {
|
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal {
|
||||||
path: "Test Path".into(),
|
path: "Test Path".into(),
|
||||||
..EditSeriesModal::default()
|
..EditSeriesModal::default()
|
||||||
@@ -694,7 +695,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.sonarr_data
|
.sonarr_data
|
||||||
@@ -713,7 +714,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_edit_series_tags_input_submit() {
|
fn test_edit_series_tags_input_submit() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal {
|
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal {
|
||||||
tags: "Test Tags".into(),
|
tags: "Test Tags".into(),
|
||||||
..EditSeriesModal::default()
|
..EditSeriesModal::default()
|
||||||
@@ -730,7 +731,7 @@ mod tests {
|
|||||||
)
|
)
|
||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(!app
|
assert!(!app
|
||||||
.data
|
.data
|
||||||
.sonarr_data
|
.sonarr_data
|
||||||
@@ -1010,7 +1011,7 @@ mod tests {
|
|||||||
if selected_block == ActiveSonarrBlock::EditSeriesPathInput
|
if selected_block == ActiveSonarrBlock::EditSeriesPathInput
|
||||||
|| selected_block == ActiveSonarrBlock::EditSeriesTagsInput
|
|| selected_block == ActiveSonarrBlock::EditSeriesTagsInput
|
||||||
{
|
{
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1049,7 +1050,7 @@ mod tests {
|
|||||||
.into()
|
.into()
|
||||||
);
|
);
|
||||||
assert_eq!(app.data.sonarr_data.prompt_confirm_action, None);
|
assert_eq!(app.data.sonarr_data.prompt_confirm_action, None);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
@@ -1085,7 +1086,7 @@ mod tests {
|
|||||||
if active_sonarr_block == ActiveSonarrBlock::EditSeriesPathInput
|
if active_sonarr_block == ActiveSonarrBlock::EditSeriesPathInput
|
||||||
|| active_sonarr_block == ActiveSonarrBlock::EditSeriesTagsInput
|
|| active_sonarr_block == ActiveSonarrBlock::EditSeriesTagsInput
|
||||||
{
|
{
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1111,14 +1112,14 @@ mod tests {
|
|||||||
) {
|
) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.data.sonarr_data = create_test_sonarr_data();
|
app.data.sonarr_data = create_test_sonarr_data();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
app.push_navigation_stack(ActiveSonarrBlock::Series.into());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::EditSeriesPrompt.into());
|
app.push_navigation_stack(ActiveSonarrBlock::EditSeriesPrompt.into());
|
||||||
app.push_navigation_stack(active_sonarr_block.into());
|
app.push_navigation_stack(active_sonarr_block.into());
|
||||||
|
|
||||||
EditSeriesHandler::new(ESC_KEY, &mut app, active_sonarr_block, None).handle();
|
EditSeriesHandler::new(ESC_KEY, &mut app, active_sonarr_block, None).handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveSonarrBlock::EditSeriesPrompt.into()
|
ActiveSonarrBlock::EditSeriesPrompt.into()
|
||||||
@@ -1243,7 +1244,7 @@ mod tests {
|
|||||||
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal::default());
|
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal::default());
|
||||||
|
|
||||||
EditSeriesHandler::new(
|
EditSeriesHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::EditSeriesPathInput,
|
ActiveSonarrBlock::EditSeriesPathInput,
|
||||||
None,
|
None,
|
||||||
@@ -1259,7 +1260,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.path
|
.path
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1270,7 +1271,7 @@ mod tests {
|
|||||||
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal::default());
|
app.data.sonarr_data.edit_series_modal = Some(EditSeriesModal::default());
|
||||||
|
|
||||||
EditSeriesHandler::new(
|
EditSeriesHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::EditSeriesTagsInput,
|
ActiveSonarrBlock::EditSeriesTagsInput,
|
||||||
None,
|
None,
|
||||||
@@ -1286,7 +1287,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.tags
|
.tags
|
||||||
.text,
|
.text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1368,6 +1369,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_edit_series_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = EditSeriesHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_build_edit_series_params() {
|
fn test_build_edit_series_params() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::sonarr_handlers::library::season_details_handler::releases_sorting_options;
|
use crate::handlers::sonarr_handlers::library::season_details_handler::releases_sorting_options;
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EPISODE_DETAILS_BLOCKS};
|
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, EPISODE_DETAILS_BLOCKS};
|
||||||
use crate::models::sonarr_models::{SonarrHistoryItem, SonarrRelease, SonarrReleaseDownloadBody};
|
use crate::models::sonarr_models::{SonarrHistoryItem, SonarrRelease, SonarrReleaseDownloadBody};
|
||||||
use crate::network::sonarr_network::SonarrEvent;
|
use crate::network::sonarr_network::SonarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "episode_details_handler_tests.rs"]
|
#[path = "episode_details_handler_tests.rs"]
|
||||||
@@ -88,6 +87,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EpisodeDetailsHandle
|
|||||||
EPISODE_DETAILS_BLOCKS.contains(&active_block)
|
EPISODE_DETAILS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -142,7 +145,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EpisodeDetailsHandle
|
|||||||
| ActiveSonarrBlock::EpisodeHistory
|
| ActiveSonarrBlock::EpisodeHistory
|
||||||
| ActiveSonarrBlock::EpisodeFile
|
| ActiveSonarrBlock::EpisodeFile
|
||||||
| ActiveSonarrBlock::ManualEpisodeSearch => match self.key {
|
| ActiveSonarrBlock::ManualEpisodeSearch => match self.key {
|
||||||
_ if self.key == DEFAULT_KEYBINDINGS.left.key => {
|
_ if matches_key!(left, self.key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.data
|
.data
|
||||||
@@ -170,7 +173,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EpisodeDetailsHandle
|
|||||||
.get_active_route(),
|
.get_active_route(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ if self.key == DEFAULT_KEYBINDINGS.right.key => {
|
_ if matches_key!(right, self.key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.data
|
.data
|
||||||
@@ -306,21 +309,19 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EpisodeDetailsHandle
|
|||||||
| ActiveSonarrBlock::EpisodeHistory
|
| ActiveSonarrBlock::EpisodeHistory
|
||||||
| ActiveSonarrBlock::EpisodeFile
|
| ActiveSonarrBlock::EpisodeFile
|
||||||
| ActiveSonarrBlock::ManualEpisodeSearch => match self.key {
|
| ActiveSonarrBlock::ManualEpisodeSearch => match self.key {
|
||||||
_ if self.key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, self.key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.pop_and_push_navigation_stack(self.active_sonarr_block.into());
|
.pop_and_push_navigation_stack(self.active_sonarr_block.into());
|
||||||
}
|
}
|
||||||
_ if self.key == DEFAULT_KEYBINDINGS.auto_search.key => {
|
_ if matches_key!(auto_search, self.key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::AutomaticallySearchEpisodePrompt.into());
|
.push_navigation_stack(ActiveSonarrBlock::AutomaticallySearchEpisodePrompt.into());
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveSonarrBlock::AutomaticallySearchEpisodePrompt
|
ActiveSonarrBlock::AutomaticallySearchEpisodePrompt if matches_key!(confirm, key) => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key =>
|
|
||||||
{
|
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
||||||
SonarrEvent::TriggerAutomaticEpisodeSearch(self.extract_episode_id()),
|
SonarrEvent::TriggerAutomaticEpisodeSearch(self.extract_episode_id()),
|
||||||
@@ -328,9 +329,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EpisodeDetailsHandle
|
|||||||
|
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::ManualEpisodeSearchConfirmPrompt
|
ActiveSonarrBlock::ManualEpisodeSearchConfirmPrompt if matches_key!(confirm, key) => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key =>
|
|
||||||
{
|
|
||||||
if self.app.data.sonarr_data.prompt_confirm {
|
if self.app.data.sonarr_data.prompt_confirm {
|
||||||
let SonarrRelease {
|
let SonarrRelease {
|
||||||
guid, indexer_id, ..
|
guid, indexer_id, ..
|
||||||
|
|||||||
@@ -625,6 +625,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_episode_details_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = EpisodeDetailsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_episode_id() {
|
fn test_extract_episode_id() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -316,7 +316,7 @@ mod tests {
|
|||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveSonarrBlock::AddSeriesSearchInput.into()
|
ActiveSonarrBlock::AddSeriesSearchInput.into()
|
||||||
);
|
);
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.sonarr_data.add_series_search.is_some());
|
assert!(app.data.sonarr_data.add_series_search.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -340,7 +340,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into());
|
assert_eq!(app.get_current_route(), ActiveSonarrBlock::Series.into());
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.sonarr_data.add_series_search.is_none());
|
assert!(app.data.sonarr_data.add_series_search.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -827,6 +827,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_library_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = LibraryHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_library_handler_not_ready_when_loading() {
|
fn test_library_handler_not_ready_when_loading() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ use crate::{
|
|||||||
event::Key,
|
event::Key,
|
||||||
handle_table_events,
|
handle_table_events,
|
||||||
handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler},
|
handlers::{handle_clear_errors, handle_prompt_toggle, KeyEventHandler},
|
||||||
|
matches_key,
|
||||||
models::{
|
models::{
|
||||||
servarr_data::sonarr::sonarr_data::{
|
servarr_data::sonarr::sonarr_data::{
|
||||||
ActiveSonarrBlock, DELETE_SERIES_SELECTION_BLOCKS, EDIT_SERIES_SELECTION_BLOCKS,
|
ActiveSonarrBlock, DELETE_SERIES_SELECTION_BLOCKS, EDIT_SERIES_SELECTION_BLOCKS,
|
||||||
@@ -21,7 +22,6 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use super::handle_change_tab_left_right_keys;
|
use super::handle_change_tab_left_right_keys;
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::handlers::sonarr_handlers::library::episode_details_handler::EpisodeDetailsHandler;
|
use crate::handlers::sonarr_handlers::library::episode_details_handler::EpisodeDetailsHandler;
|
||||||
use crate::handlers::sonarr_handlers::library::season_details_handler::SeasonDetailsHandler;
|
use crate::handlers::sonarr_handlers::library::season_details_handler::SeasonDetailsHandler;
|
||||||
use crate::handlers::sonarr_handlers::library::series_details_handler::SeriesDetailsHandler;
|
use crate::handlers::sonarr_handlers::library::series_details_handler::SeriesDetailsHandler;
|
||||||
@@ -102,6 +102,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for LibraryHandler<'a, '
|
|||||||
|| LIBRARY_BLOCKS.contains(&active_block)
|
|| LIBRARY_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -182,7 +186,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for LibraryHandler<'a, '
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_sonarr_block {
|
match self.active_sonarr_block {
|
||||||
ActiveSonarrBlock::Series => match self.key {
|
ActiveSonarrBlock::Series => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.edit.key => {
|
_ if matches_key!(edit, key) => {
|
||||||
self.app.push_navigation_stack(
|
self.app.push_navigation_stack(
|
||||||
(
|
(
|
||||||
ActiveSonarrBlock::EditSeriesPrompt,
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
@@ -194,25 +198,25 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for LibraryHandler<'a, '
|
|||||||
self.app.data.sonarr_data.selected_block =
|
self.app.data.sonarr_data.selected_block =
|
||||||
BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.add.key => {
|
_ if matches_key!(add, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::AddSeriesSearchInput.into());
|
.push_navigation_stack(ActiveSonarrBlock::AddSeriesSearchInput.into());
|
||||||
self.app.data.sonarr_data.add_series_search = Some(HorizontallyScrollableText::default());
|
self.app.data.sonarr_data.add_series_search = Some(HorizontallyScrollableText::default());
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.update.key => {
|
_ if matches_key!(update, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::UpdateAllSeriesPrompt.into());
|
.push_navigation_stack(ActiveSonarrBlock::UpdateAllSeriesPrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveSonarrBlock::UpdateAllSeriesPrompt => {
|
ActiveSonarrBlock::UpdateAllSeriesPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::UpdateAllSeries);
|
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::UpdateAllSeries);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::sonarr_handlers::history::history_sorting_options;
|
use crate::handlers::sonarr_handlers::history::history_sorting_options;
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -12,6 +10,7 @@ use crate::models::sonarr_models::{
|
|||||||
};
|
};
|
||||||
use crate::models::stateful_table::SortOption;
|
use crate::models::stateful_table::SortOption;
|
||||||
use crate::network::sonarr_network::SonarrEvent;
|
use crate::network::sonarr_network::SonarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
use serde_json::Number;
|
use serde_json::Number;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -140,6 +139,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler
|
|||||||
SEASON_DETAILS_BLOCKS.contains(&active_block)
|
SEASON_DETAILS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -193,7 +196,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler
|
|||||||
ActiveSonarrBlock::SeasonDetails
|
ActiveSonarrBlock::SeasonDetails
|
||||||
| ActiveSonarrBlock::SeasonHistory
|
| ActiveSonarrBlock::SeasonHistory
|
||||||
| ActiveSonarrBlock::ManualSeasonSearch => match self.key {
|
| ActiveSonarrBlock::ManualSeasonSearch => match self.key {
|
||||||
_ if self.key == DEFAULT_KEYBINDINGS.left.key => {
|
_ if matches_key!(left, self.key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.data
|
.data
|
||||||
@@ -215,7 +218,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler
|
|||||||
.get_active_route(),
|
.get_active_route(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ if self.key == DEFAULT_KEYBINDINGS.right.key => {
|
_ if matches_key!(right, self.key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.data
|
.data
|
||||||
@@ -378,7 +381,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler
|
|||||||
fn handle_char_key_event(&mut self) {
|
fn handle_char_key_event(&mut self) {
|
||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_sonarr_block {
|
match self.active_sonarr_block {
|
||||||
ActiveSonarrBlock::SeasonDetails if self.key == DEFAULT_KEYBINDINGS.toggle_monitoring.key => {
|
ActiveSonarrBlock::SeasonDetails if matches_key!(toggle_monitoring, self.key) => {
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
||||||
SonarrEvent::ToggleEpisodeMonitoring(self.extract_episode_id()),
|
SonarrEvent::ToggleEpisodeMonitoring(self.extract_episode_id()),
|
||||||
@@ -391,21 +394,19 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler
|
|||||||
ActiveSonarrBlock::SeasonDetails
|
ActiveSonarrBlock::SeasonDetails
|
||||||
| ActiveSonarrBlock::SeasonHistory
|
| ActiveSonarrBlock::SeasonHistory
|
||||||
| ActiveSonarrBlock::ManualSeasonSearch => match self.key {
|
| ActiveSonarrBlock::ManualSeasonSearch => match self.key {
|
||||||
_ if self.key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, self.key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.pop_and_push_navigation_stack(self.active_sonarr_block.into());
|
.pop_and_push_navigation_stack(self.active_sonarr_block.into());
|
||||||
}
|
}
|
||||||
_ if self.key == DEFAULT_KEYBINDINGS.auto_search.key => {
|
_ if matches_key!(auto_search, self.key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::AutomaticallySearchSeasonPrompt.into());
|
.push_navigation_stack(ActiveSonarrBlock::AutomaticallySearchSeasonPrompt.into());
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveSonarrBlock::AutomaticallySearchSeasonPrompt
|
ActiveSonarrBlock::AutomaticallySearchSeasonPrompt if matches_key!(confirm, key) => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key =>
|
|
||||||
{
|
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
||||||
SonarrEvent::TriggerAutomaticSeasonSearch(self.extract_series_id_season_number_tuple()),
|
SonarrEvent::TriggerAutomaticSeasonSearch(self.extract_series_id_season_number_tuple()),
|
||||||
@@ -413,7 +414,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler
|
|||||||
|
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::DeleteEpisodeFilePrompt if key == DEFAULT_KEYBINDINGS.confirm.key => {
|
ActiveSonarrBlock::DeleteEpisodeFilePrompt if matches_key!(confirm, key) => {
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::DeleteEpisodeFile(
|
self.app.data.sonarr_data.prompt_confirm_action = Some(SonarrEvent::DeleteEpisodeFile(
|
||||||
self.extract_episode_file_id(),
|
self.extract_episode_file_id(),
|
||||||
@@ -421,9 +422,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler
|
|||||||
|
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::ManualSeasonSearchConfirmPrompt
|
ActiveSonarrBlock::ManualSeasonSearchConfirmPrompt if matches_key!(confirm, key) => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key =>
|
|
||||||
{
|
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
let SonarrRelease {
|
let SonarrRelease {
|
||||||
guid, indexer_id, ..
|
guid, indexer_id, ..
|
||||||
|
|||||||
@@ -789,6 +789,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_season_details_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = SeasonDetailsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_episode_file_id() {
|
fn test_extract_episode_file_id() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handle_table_events;
|
|
||||||
use crate::handlers::sonarr_handlers::history::history_sorting_options;
|
use crate::handlers::sonarr_handlers::history::history_sorting_options;
|
||||||
use crate::handlers::table_handler::TableHandlingConfig;
|
use crate::handlers::table_handler::TableHandlingConfig;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
@@ -11,6 +9,7 @@ use crate::models::servarr_data::sonarr::sonarr_data::{
|
|||||||
use crate::models::sonarr_models::{Season, SonarrHistoryItem};
|
use crate::models::sonarr_models::{Season, SonarrHistoryItem};
|
||||||
use crate::models::BlockSelectionState;
|
use crate::models::BlockSelectionState;
|
||||||
use crate::network::sonarr_network::SonarrEvent;
|
use crate::network::sonarr_network::SonarrEvent;
|
||||||
|
use crate::{handle_table_events, matches_key};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "series_details_handler_tests.rs"]
|
#[path = "series_details_handler_tests.rs"]
|
||||||
@@ -91,6 +90,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler
|
|||||||
SERIES_DETAILS_BLOCKS.contains(&active_block)
|
SERIES_DETAILS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -130,7 +133,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler
|
|||||||
fn handle_left_right_action(&mut self) {
|
fn handle_left_right_action(&mut self) {
|
||||||
match self.active_sonarr_block {
|
match self.active_sonarr_block {
|
||||||
ActiveSonarrBlock::SeriesDetails | ActiveSonarrBlock::SeriesHistory => match self.key {
|
ActiveSonarrBlock::SeriesDetails | ActiveSonarrBlock::SeriesHistory => match self.key {
|
||||||
_ if self.key == DEFAULT_KEYBINDINGS.left.key => {
|
_ if matches_key!(left, self.key) => {
|
||||||
self.app.data.sonarr_data.series_info_tabs.previous();
|
self.app.data.sonarr_data.series_info_tabs.previous();
|
||||||
self.app.pop_and_push_navigation_stack(
|
self.app.pop_and_push_navigation_stack(
|
||||||
self
|
self
|
||||||
@@ -141,7 +144,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler
|
|||||||
.get_active_route(),
|
.get_active_route(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ if self.key == DEFAULT_KEYBINDINGS.right.key => {
|
_ if matches_key!(right, self.key) => {
|
||||||
self.app.data.sonarr_data.series_info_tabs.next();
|
self.app.data.sonarr_data.series_info_tabs.next();
|
||||||
self.app.pop_and_push_navigation_stack(
|
self.app.pop_and_push_navigation_stack(
|
||||||
self
|
self
|
||||||
@@ -250,20 +253,20 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_sonarr_block {
|
match self.active_sonarr_block {
|
||||||
ActiveSonarrBlock::SeriesDetails => match self.key {
|
ActiveSonarrBlock::SeriesDetails => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => self
|
_ if matches_key!(refresh, key) => self
|
||||||
.app
|
.app
|
||||||
.pop_and_push_navigation_stack(self.active_sonarr_block.into()),
|
.pop_and_push_navigation_stack(self.active_sonarr_block.into()),
|
||||||
_ if key == DEFAULT_KEYBINDINGS.auto_search.key => {
|
_ if matches_key!(auto_search, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::AutomaticallySearchSeriesPrompt.into());
|
.push_navigation_stack(ActiveSonarrBlock::AutomaticallySearchSeriesPrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.update.key => {
|
_ if matches_key!(update, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::UpdateAndScanSeriesPrompt.into());
|
.push_navigation_stack(ActiveSonarrBlock::UpdateAndScanSeriesPrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.edit.key => {
|
_ if matches_key!(edit, key) => {
|
||||||
self.app.push_navigation_stack(
|
self.app.push_navigation_stack(
|
||||||
(
|
(
|
||||||
ActiveSonarrBlock::EditSeriesPrompt,
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
@@ -275,7 +278,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler
|
|||||||
self.app.data.sonarr_data.selected_block =
|
self.app.data.sonarr_data.selected_block =
|
||||||
BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.toggle_monitoring.key => {
|
_ if matches_key!(toggle_monitoring, key) => {
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
||||||
SonarrEvent::ToggleSeasonMonitoring(self.extract_series_id_season_number_tuple()),
|
SonarrEvent::ToggleSeasonMonitoring(self.extract_series_id_season_number_tuple()),
|
||||||
@@ -288,15 +291,15 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler
|
|||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveSonarrBlock::SeriesHistory => match self.key {
|
ActiveSonarrBlock::SeriesHistory => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => self
|
_ if matches_key!(refresh, key) => self
|
||||||
.app
|
.app
|
||||||
.pop_and_push_navigation_stack(self.active_sonarr_block.into()),
|
.pop_and_push_navigation_stack(self.active_sonarr_block.into()),
|
||||||
_ if key == DEFAULT_KEYBINDINGS.auto_search.key => {
|
_ if matches_key!(auto_search, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::AutomaticallySearchSeriesPrompt.into());
|
.push_navigation_stack(ActiveSonarrBlock::AutomaticallySearchSeriesPrompt.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.edit.key => {
|
_ if matches_key!(edit, key) => {
|
||||||
self.app.push_navigation_stack(
|
self.app.push_navigation_stack(
|
||||||
(
|
(
|
||||||
ActiveSonarrBlock::EditSeriesPrompt,
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
@@ -308,7 +311,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler
|
|||||||
self.app.data.sonarr_data.selected_block =
|
self.app.data.sonarr_data.selected_block =
|
||||||
BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
BlockSelectionState::new(EDIT_SERIES_SELECTION_BLOCKS);
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.update.key => {
|
_ if matches_key!(update, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::UpdateAndScanSeriesPrompt.into());
|
.push_navigation_stack(ActiveSonarrBlock::UpdateAndScanSeriesPrompt.into());
|
||||||
@@ -316,7 +319,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler
|
|||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
ActiveSonarrBlock::AutomaticallySearchSeriesPrompt => {
|
ActiveSonarrBlock::AutomaticallySearchSeriesPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
self.app.data.sonarr_data.prompt_confirm_action = Some(
|
||||||
SonarrEvent::TriggerAutomaticSeriesSearch(self.extract_series_id()),
|
SonarrEvent::TriggerAutomaticSeriesSearch(self.extract_series_id()),
|
||||||
|
|||||||
@@ -611,6 +611,25 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_series_details_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = SeriesDetailsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_series_id_season_number_tuple() {
|
fn test_extract_series_id_season_number_tuple() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -7,9 +7,7 @@ use root_folders::RootFoldersHandler;
|
|||||||
use system::SystemHandler;
|
use system::SystemHandler;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
app::{key_binding::DEFAULT_KEYBINDINGS, App},
|
app::App, event::Key, matches_key, models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock,
|
||||||
event::Key,
|
|
||||||
models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::KeyEventHandler;
|
use super::KeyEventHandler;
|
||||||
@@ -69,6 +67,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SonarrHandler<'a, 'b
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -113,11 +115,11 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SonarrHandler<'a, 'b
|
|||||||
pub fn handle_change_tab_left_right_keys(app: &mut App<'_>, key: Key) {
|
pub fn handle_change_tab_left_right_keys(app: &mut App<'_>, key: Key) {
|
||||||
let key_ref = key;
|
let key_ref = key;
|
||||||
match key_ref {
|
match key_ref {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.left.key => {
|
_ if matches_key!(left, key, app.ignore_special_keys_for_textbox_input) => {
|
||||||
app.data.sonarr_data.main_tabs.previous();
|
app.data.sonarr_data.main_tabs.previous();
|
||||||
app.pop_and_push_navigation_stack(app.data.sonarr_data.main_tabs.get_active_route());
|
app.pop_and_push_navigation_stack(app.data.sonarr_data.main_tabs.get_active_route());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.right.key => {
|
_ if matches_key!(right, key, app.ignore_special_keys_for_textbox_input) => {
|
||||||
app.data.sonarr_data.main_tabs.next();
|
app.data.sonarr_data.main_tabs.next();
|
||||||
app.pop_and_push_navigation_stack(app.data.sonarr_data.main_tabs.get_active_route());
|
app.pop_and_push_navigation_stack(app.data.sonarr_data.main_tabs.get_active_route());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys;
|
||||||
@@ -8,7 +7,9 @@ use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, ROOT_F
|
|||||||
use crate::models::servarr_models::{AddRootFolderBody, RootFolder};
|
use crate::models::servarr_models::{AddRootFolderBody, RootFolder};
|
||||||
use crate::models::HorizontallyScrollableText;
|
use crate::models::HorizontallyScrollableText;
|
||||||
use crate::network::sonarr_network::SonarrEvent;
|
use crate::network::sonarr_network::SonarrEvent;
|
||||||
use crate::{handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys};
|
use crate::{
|
||||||
|
handle_table_events, handle_text_box_keys, handle_text_box_left_right_keys, matches_key,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "root_folders_handler_tests.rs"]
|
#[path = "root_folders_handler_tests.rs"]
|
||||||
@@ -66,6 +67,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for RootFoldersHandler<'
|
|||||||
ROOT_FOLDERS_BLOCKS.contains(&active_block)
|
ROOT_FOLDERS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -166,7 +171,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for RootFoldersHandler<'
|
|||||||
self.build_add_root_folder_body(),
|
self.build_add_root_folder_body(),
|
||||||
));
|
));
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
@@ -179,7 +184,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for RootFoldersHandler<'
|
|||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.data.sonarr_data.edit_root_folder = None;
|
self.app.data.sonarr_data.edit_root_folder = None;
|
||||||
self.app.data.sonarr_data.prompt_confirm = false;
|
self.app.data.sonarr_data.prompt_confirm = false;
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::DeleteRootFolderPrompt => {
|
ActiveSonarrBlock::DeleteRootFolderPrompt => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
@@ -193,15 +198,15 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for RootFoldersHandler<'
|
|||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.active_sonarr_block {
|
match self.active_sonarr_block {
|
||||||
ActiveSonarrBlock::RootFolders => match self.key {
|
ActiveSonarrBlock::RootFolders => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.add.key => {
|
_ if matches_key!(add, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::AddRootFolderPrompt.into());
|
.push_navigation_stack(ActiveSonarrBlock::AddRootFolderPrompt.into());
|
||||||
self.app.data.sonarr_data.edit_root_folder = Some(HorizontallyScrollableText::default());
|
self.app.data.sonarr_data.edit_root_folder = Some(HorizontallyScrollableText::default());
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
},
|
||||||
@@ -213,7 +218,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for RootFoldersHandler<'
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
ActiveSonarrBlock::DeleteRootFolderPrompt => {
|
ActiveSonarrBlock::DeleteRootFolderPrompt => {
|
||||||
if key == DEFAULT_KEYBINDINGS.confirm.key {
|
if matches_key!(confirm, key) {
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action =
|
self.app.data.sonarr_data.prompt_confirm_action =
|
||||||
Some(SonarrEvent::DeleteRootFolder(self.extract_root_folder_id()));
|
Some(SonarrEvent::DeleteRootFolder(self.extract_root_folder_id()));
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -269,7 +270,7 @@ mod tests {
|
|||||||
.set_items(vec![RootFolder::default()]);
|
.set_items(vec![RootFolder::default()]);
|
||||||
app.data.sonarr_data.edit_root_folder = Some("Test".into());
|
app.data.sonarr_data.edit_root_folder = Some("Test".into());
|
||||||
app.data.sonarr_data.prompt_confirm = true;
|
app.data.sonarr_data.prompt_confirm = true;
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::RootFolders.into());
|
app.push_navigation_stack(ActiveSonarrBlock::RootFolders.into());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::AddRootFolderPrompt.into());
|
app.push_navigation_stack(ActiveSonarrBlock::AddRootFolderPrompt.into());
|
||||||
|
|
||||||
@@ -282,7 +283,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(app.data.sonarr_data.prompt_confirm);
|
assert!(app.data.sonarr_data.prompt_confirm);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.data.sonarr_data.prompt_confirm_action,
|
app.data.sonarr_data.prompt_confirm_action,
|
||||||
Some(SonarrEvent::AddRootFolder(expected_add_root_folder_body))
|
Some(SonarrEvent::AddRootFolder(expected_add_root_folder_body))
|
||||||
@@ -299,7 +300,7 @@ mod tests {
|
|||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.data.sonarr_data.edit_root_folder = Some(HorizontallyScrollableText::default());
|
app.data.sonarr_data.edit_root_folder = Some(HorizontallyScrollableText::default());
|
||||||
app.data.sonarr_data.prompt_confirm = false;
|
app.data.sonarr_data.prompt_confirm = false;
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::RootFolders.into());
|
app.push_navigation_stack(ActiveSonarrBlock::RootFolders.into());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::AddRootFolderPrompt.into());
|
app.push_navigation_stack(ActiveSonarrBlock::AddRootFolderPrompt.into());
|
||||||
|
|
||||||
@@ -312,7 +313,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.sonarr_data.prompt_confirm_action.is_none());
|
assert!(app.data.sonarr_data.prompt_confirm_action.is_none());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -414,7 +415,7 @@ mod tests {
|
|||||||
app.push_navigation_stack(ActiveSonarrBlock::RootFolders.into());
|
app.push_navigation_stack(ActiveSonarrBlock::RootFolders.into());
|
||||||
app.push_navigation_stack(ActiveSonarrBlock::AddRootFolderPrompt.into());
|
app.push_navigation_stack(ActiveSonarrBlock::AddRootFolderPrompt.into());
|
||||||
app.data.sonarr_data.edit_root_folder = Some("/nfs/test".into());
|
app.data.sonarr_data.edit_root_folder = Some("/nfs/test".into());
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
|
||||||
RootFoldersHandler::new(
|
RootFoldersHandler::new(
|
||||||
ESC_KEY,
|
ESC_KEY,
|
||||||
@@ -431,7 +432,7 @@ mod tests {
|
|||||||
|
|
||||||
assert!(app.data.sonarr_data.edit_root_folder.is_none());
|
assert!(app.data.sonarr_data.edit_root_folder.is_none());
|
||||||
assert!(!app.data.sonarr_data.prompt_confirm);
|
assert!(!app.data.sonarr_data.prompt_confirm);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
@@ -481,7 +482,7 @@ mod tests {
|
|||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveSonarrBlock::AddRootFolderPrompt.into()
|
ActiveSonarrBlock::AddRootFolderPrompt.into()
|
||||||
);
|
);
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.sonarr_data.edit_root_folder.is_some());
|
assert!(app.data.sonarr_data.edit_root_folder.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,7 +509,7 @@ mod tests {
|
|||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveSonarrBlock::RootFolders.into()
|
ActiveSonarrBlock::RootFolders.into()
|
||||||
);
|
);
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.sonarr_data.edit_root_folder.is_none());
|
assert!(app.data.sonarr_data.edit_root_folder.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -600,7 +601,7 @@ mod tests {
|
|||||||
app.data.sonarr_data.edit_root_folder = Some(HorizontallyScrollableText::default());
|
app.data.sonarr_data.edit_root_folder = Some(HorizontallyScrollableText::default());
|
||||||
|
|
||||||
RootFoldersHandler::new(
|
RootFoldersHandler::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveSonarrBlock::AddRootFolderPrompt,
|
ActiveSonarrBlock::AddRootFolderPrompt,
|
||||||
None,
|
None,
|
||||||
@@ -609,7 +610,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_str_eq!(
|
assert_str_eq!(
|
||||||
app.data.sonarr_data.edit_root_folder.as_ref().unwrap().text,
|
app.data.sonarr_data.edit_root_folder.as_ref().unwrap().text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -655,6 +656,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_root_folders_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = RootFoldersHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_root_folder_id() {
|
fn test_extract_root_folder_id() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ mod tests {
|
|||||||
use crate::test_handler_delegation;
|
use crate::test_handler_delegation;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
#[case(0, ActiveSonarrBlock::System, ActiveSonarrBlock::Downloads)]
|
#[case(0, ActiveSonarrBlock::System, ActiveSonarrBlock::Downloads)]
|
||||||
@@ -45,6 +46,77 @@ mod tests {
|
|||||||
assert_eq!(app.get_current_route(), right_block.into());
|
assert_eq!(app.get_current_route(), right_block.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(0, ActiveSonarrBlock::System, ActiveSonarrBlock::Downloads)]
|
||||||
|
#[case(1, ActiveSonarrBlock::Series, ActiveSonarrBlock::Blocklist)]
|
||||||
|
#[case(2, ActiveSonarrBlock::Downloads, ActiveSonarrBlock::History)]
|
||||||
|
#[case(3, ActiveSonarrBlock::Blocklist, ActiveSonarrBlock::RootFolders)]
|
||||||
|
#[case(4, ActiveSonarrBlock::History, ActiveSonarrBlock::Indexers)]
|
||||||
|
#[case(5, ActiveSonarrBlock::RootFolders, ActiveSonarrBlock::System)]
|
||||||
|
#[case(6, ActiveSonarrBlock::Indexers, ActiveSonarrBlock::Series)]
|
||||||
|
fn test_sonarr_handler_change_tab_left_right_keys_alt_navigation(
|
||||||
|
#[case] index: usize,
|
||||||
|
#[case] left_block: ActiveSonarrBlock,
|
||||||
|
#[case] right_block: ActiveSonarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.data.sonarr_data.main_tabs.set_index(index);
|
||||||
|
|
||||||
|
handle_change_tab_left_right_keys(&mut app, DEFAULT_KEYBINDINGS.left.alt.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.sonarr_data.main_tabs.get_active_route(),
|
||||||
|
left_block.into()
|
||||||
|
);
|
||||||
|
assert_eq!(app.get_current_route(), left_block.into());
|
||||||
|
|
||||||
|
app.data.sonarr_data.main_tabs.set_index(index);
|
||||||
|
|
||||||
|
handle_change_tab_left_right_keys(&mut app, DEFAULT_KEYBINDINGS.right.alt.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.sonarr_data.main_tabs.get_active_route(),
|
||||||
|
right_block.into()
|
||||||
|
);
|
||||||
|
assert_eq!(app.get_current_route(), right_block.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
#[case(0, ActiveSonarrBlock::Series)]
|
||||||
|
#[case(1, ActiveSonarrBlock::Downloads)]
|
||||||
|
#[case(2, ActiveSonarrBlock::Blocklist)]
|
||||||
|
#[case(3, ActiveSonarrBlock::History)]
|
||||||
|
#[case(4, ActiveSonarrBlock::RootFolders)]
|
||||||
|
#[case(5, ActiveSonarrBlock::Indexers)]
|
||||||
|
#[case(6, ActiveSonarrBlock::System)]
|
||||||
|
fn test_sonarr_handler_change_tab_left_right_keys_alt_navigation_no_op_when_ignoring_quit_key(
|
||||||
|
#[case] index: usize,
|
||||||
|
#[case] block: ActiveSonarrBlock,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.push_navigation_stack(block.into());
|
||||||
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
app.data.sonarr_data.main_tabs.set_index(index);
|
||||||
|
|
||||||
|
handle_change_tab_left_right_keys(&mut app, DEFAULT_KEYBINDINGS.left.alt.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.sonarr_data.main_tabs.get_active_route(),
|
||||||
|
block.into()
|
||||||
|
);
|
||||||
|
assert_eq!(app.get_current_route(), block.into());
|
||||||
|
|
||||||
|
app.data.sonarr_data.main_tabs.set_index(index);
|
||||||
|
|
||||||
|
handle_change_tab_left_right_keys(&mut app, DEFAULT_KEYBINDINGS.right.alt.unwrap());
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
app.data.sonarr_data.main_tabs.get_active_route(),
|
||||||
|
block.into()
|
||||||
|
);
|
||||||
|
assert_eq!(app.get_current_route(), block.into());
|
||||||
|
}
|
||||||
|
|
||||||
#[rstest]
|
#[rstest]
|
||||||
fn test_delegates_library_blocks_to_library_handler(
|
fn test_delegates_library_blocks_to_library_handler(
|
||||||
#[values(
|
#[values(
|
||||||
@@ -59,10 +131,10 @@ mod tests {
|
|||||||
ActiveSonarrBlock::AddSeriesSelectRootFolder,
|
ActiveSonarrBlock::AddSeriesSelectRootFolder,
|
||||||
ActiveSonarrBlock::AddSeriesSelectSeriesType,
|
ActiveSonarrBlock::AddSeriesSelectSeriesType,
|
||||||
ActiveSonarrBlock::AddSeriesTagsInput,
|
ActiveSonarrBlock::AddSeriesTagsInput,
|
||||||
// ActiveSonarrBlock::AutomaticallySearchEpisodePrompt,
|
ActiveSonarrBlock::AutomaticallySearchEpisodePrompt,
|
||||||
// ActiveSonarrBlock::AutomaticallySearchSeasonPrompt,
|
ActiveSonarrBlock::AutomaticallySearchSeasonPrompt,
|
||||||
// ActiveSonarrBlock::AutomaticallySearchSeriesPrompt,
|
ActiveSonarrBlock::AutomaticallySearchSeriesPrompt,
|
||||||
// ActiveSonarrBlock::DeleteEpisodeFilePrompt,
|
ActiveSonarrBlock::DeleteEpisodeFilePrompt,
|
||||||
ActiveSonarrBlock::DeleteSeriesPrompt,
|
ActiveSonarrBlock::DeleteSeriesPrompt,
|
||||||
ActiveSonarrBlock::EditSeriesPrompt,
|
ActiveSonarrBlock::EditSeriesPrompt,
|
||||||
ActiveSonarrBlock::EditSeriesPathInput,
|
ActiveSonarrBlock::EditSeriesPathInput,
|
||||||
@@ -70,39 +142,36 @@ mod tests {
|
|||||||
ActiveSonarrBlock::EditSeriesSelectQualityProfile,
|
ActiveSonarrBlock::EditSeriesSelectQualityProfile,
|
||||||
ActiveSonarrBlock::EditSeriesSelectLanguageProfile,
|
ActiveSonarrBlock::EditSeriesSelectLanguageProfile,
|
||||||
ActiveSonarrBlock::EditSeriesTagsInput,
|
ActiveSonarrBlock::EditSeriesTagsInput,
|
||||||
// ActiveSonarrBlock::EpisodeDetails,
|
ActiveSonarrBlock::EpisodeDetails,
|
||||||
// ActiveSonarrBlock::EpisodeFile,
|
ActiveSonarrBlock::EpisodeFile,
|
||||||
// ActiveSonarrBlock::EpisodeHistory,
|
ActiveSonarrBlock::EpisodeHistory,
|
||||||
// ActiveSonarrBlock::EpisodesSortPrompt,
|
|
||||||
// ActiveSonarrBlock::FilterEpisodes,
|
|
||||||
// ActiveSonarrBlock::FilterEpisodesError,
|
|
||||||
ActiveSonarrBlock::FilterSeries,
|
ActiveSonarrBlock::FilterSeries,
|
||||||
ActiveSonarrBlock::FilterSeriesError,
|
ActiveSonarrBlock::FilterSeriesError,
|
||||||
// ActiveSonarrBlock::FilterSeriesHistory,
|
ActiveSonarrBlock::FilterSeriesHistory,
|
||||||
// ActiveSonarrBlock::FilterSeriesHistoryError,
|
ActiveSonarrBlock::FilterSeriesHistoryError,
|
||||||
// ActiveSonarrBlock::ManualEpisodeSearch,
|
ActiveSonarrBlock::ManualEpisodeSearch,
|
||||||
// ActiveSonarrBlock::ManualEpisodeSearchConfirmPrompt,
|
ActiveSonarrBlock::ManualEpisodeSearchConfirmPrompt,
|
||||||
// ActiveSonarrBlock::ManualEpisodeSearchSortPrompt,
|
ActiveSonarrBlock::ManualEpisodeSearchSortPrompt,
|
||||||
// ActiveSonarrBlock::ManualSeasonSearch,
|
ActiveSonarrBlock::ManualSeasonSearch,
|
||||||
// ActiveSonarrBlock::ManualSeasonSearchConfirmPrompt,
|
ActiveSonarrBlock::ManualSeasonSearchConfirmPrompt,
|
||||||
// ActiveSonarrBlock::ManualSeasonSearchSortPrompt,
|
ActiveSonarrBlock::ManualSeasonSearchSortPrompt,
|
||||||
// ActiveSonarrBlock::SearchEpisodes,
|
ActiveSonarrBlock::SearchEpisodes,
|
||||||
// ActiveSonarrBlock::SearchEpisodesError,
|
ActiveSonarrBlock::SearchEpisodesError,
|
||||||
// ActiveSonarrBlock::SearchSeason,
|
ActiveSonarrBlock::SearchSeason,
|
||||||
// ActiveSonarrBlock::SearchSeasonError,
|
ActiveSonarrBlock::SearchSeasonError,
|
||||||
ActiveSonarrBlock::SearchSeries,
|
ActiveSonarrBlock::SearchSeries,
|
||||||
ActiveSonarrBlock::SearchSeriesError,
|
ActiveSonarrBlock::SearchSeriesError,
|
||||||
// ActiveSonarrBlock::SearchSeriesHistory,
|
ActiveSonarrBlock::SearchSeriesHistory,
|
||||||
// ActiveSonarrBlock::SearchSeriesHistoryError,
|
ActiveSonarrBlock::SearchSeriesHistoryError,
|
||||||
// ActiveSonarrBlock::SeasonDetails,
|
ActiveSonarrBlock::SeasonDetails,
|
||||||
ActiveSonarrBlock::Series,
|
ActiveSonarrBlock::Series,
|
||||||
// ActiveSonarrBlock::SeriesDetails,
|
ActiveSonarrBlock::SeriesDetails,
|
||||||
// ActiveSonarrBlock::SeriesHistory,
|
ActiveSonarrBlock::SeriesHistory,
|
||||||
// ActiveSonarrBlock::SeriesHistorySortPrompt,
|
ActiveSonarrBlock::SeriesHistorySortPrompt,
|
||||||
ActiveSonarrBlock::SeriesSortPrompt,
|
ActiveSonarrBlock::SeriesSortPrompt,
|
||||||
ActiveSonarrBlock::UpdateAllSeriesPrompt,
|
ActiveSonarrBlock::UpdateAllSeriesPrompt,
|
||||||
// ActiveSonarrBlock::UpdateAndScanSeriesPrompt
|
ActiveSonarrBlock::UpdateAndScanSeriesPrompt,
|
||||||
// ActiveSonarrBlock::SeriesHistoryDetails,
|
ActiveSonarrBlock::SeriesHistoryDetails
|
||||||
)]
|
)]
|
||||||
active_sonarr_block: ActiveSonarrBlock,
|
active_sonarr_block: ActiveSonarrBlock,
|
||||||
) {
|
) {
|
||||||
@@ -222,4 +291,45 @@ mod tests {
|
|||||||
active_sonarr_block
|
active_sonarr_block
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sonarr_handler_accepts() {
|
||||||
|
ActiveSonarrBlock::iter().for_each(|active_sonarr_block| {
|
||||||
|
assert!(SonarrHandler::accepts(active_sonarr_block));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_sonarr_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = SonarrHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_sonarr_handler_is_ready() {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.is_loading = true;
|
||||||
|
|
||||||
|
let handler = SonarrHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(handler.is_ready());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys;
|
use crate::handlers::sonarr_handlers::handle_change_tab_left_right_keys;
|
||||||
use crate::handlers::sonarr_handlers::system::system_details_handler::SystemDetailsHandler;
|
use crate::handlers::sonarr_handlers::system::system_details_handler::SystemDetailsHandler;
|
||||||
use crate::handlers::{handle_clear_errors, KeyEventHandler};
|
use crate::handlers::{handle_clear_errors, KeyEventHandler};
|
||||||
|
use crate::matches_key;
|
||||||
use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock;
|
use crate::models::servarr_data::sonarr::sonarr_data::ActiveSonarrBlock;
|
||||||
use crate::models::Scrollable;
|
use crate::models::Scrollable;
|
||||||
|
|
||||||
@@ -35,6 +35,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SystemHandler<'a, 'b
|
|||||||
SystemDetailsHandler::accepts(active_block) || active_block == ActiveSonarrBlock::System
|
SystemDetailsHandler::accepts(active_block) || active_block == ActiveSonarrBlock::System
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -86,15 +90,15 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SystemHandler<'a, 'b
|
|||||||
if self.active_sonarr_block == ActiveSonarrBlock::System {
|
if self.active_sonarr_block == ActiveSonarrBlock::System {
|
||||||
let key = self.key;
|
let key = self.key;
|
||||||
match self.key {
|
match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.refresh.key => {
|
_ if matches_key!(refresh, key) => {
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.events.key => {
|
_ if matches_key!(events, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::SystemQueuedEvents.into());
|
.push_navigation_stack(ActiveSonarrBlock::SystemQueuedEvents.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.logs.key => {
|
_ if matches_key!(logs, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::SystemLogs.into());
|
.push_navigation_stack(ActiveSonarrBlock::SystemLogs.into());
|
||||||
@@ -106,12 +110,12 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SystemHandler<'a, 'b
|
|||||||
.set_items(self.app.data.sonarr_data.logs.items.to_vec());
|
.set_items(self.app.data.sonarr_data.logs.items.to_vec());
|
||||||
self.app.data.sonarr_data.log_details.scroll_to_bottom();
|
self.app.data.sonarr_data.log_details.scroll_to_bottom();
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.tasks.key => {
|
_ if matches_key!(tasks, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::SystemTasks.into());
|
.push_navigation_stack(ActiveSonarrBlock::SystemTasks.into());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.update.key => {
|
_ if matches_key!(update, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.push_navigation_stack(ActiveSonarrBlock::SystemUpdates.into());
|
.push_navigation_stack(ActiveSonarrBlock::SystemUpdates.into());
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
|
||||||
use crate::app::App;
|
use crate::app::App;
|
||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
use crate::handlers::{handle_prompt_toggle, KeyEventHandler};
|
||||||
|
use crate::matches_key;
|
||||||
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SYSTEM_DETAILS_BLOCKS};
|
use crate::models::servarr_data::sonarr::sonarr_data::{ActiveSonarrBlock, SYSTEM_DETAILS_BLOCKS};
|
||||||
use crate::models::sonarr_models::SonarrTaskName;
|
use crate::models::sonarr_models::SonarrTaskName;
|
||||||
use crate::models::stateful_list::StatefulList;
|
use crate::models::stateful_list::StatefulList;
|
||||||
@@ -36,6 +36,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SystemDetailsHandler
|
|||||||
SYSTEM_DETAILS_BLOCKS.contains(&active_block)
|
SYSTEM_DETAILS_BLOCKS.contains(&active_block)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -114,7 +118,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SystemDetailsHandler
|
|||||||
|
|
||||||
match self.active_sonarr_block {
|
match self.active_sonarr_block {
|
||||||
ActiveSonarrBlock::SystemLogs => match self.key {
|
ActiveSonarrBlock::SystemLogs => match self.key {
|
||||||
_ if key == DEFAULT_KEYBINDINGS.left.key => {
|
_ if matches_key!(left, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.data
|
.data
|
||||||
@@ -124,7 +128,7 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SystemDetailsHandler
|
|||||||
.iter()
|
.iter()
|
||||||
.for_each(|log| log.scroll_right());
|
.for_each(|log| log.scroll_right());
|
||||||
}
|
}
|
||||||
_ if key == DEFAULT_KEYBINDINGS.right.key => {
|
_ if matches_key!(right, key) => {
|
||||||
self
|
self
|
||||||
.app
|
.app
|
||||||
.data
|
.data
|
||||||
@@ -178,14 +182,13 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SystemDetailsHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_char_key_event(&mut self) {
|
fn handle_char_key_event(&mut self) {
|
||||||
if SYSTEM_DETAILS_BLOCKS.contains(&self.active_sonarr_block)
|
if SYSTEM_DETAILS_BLOCKS.contains(&self.active_sonarr_block) && matches_key!(refresh, self.key)
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.refresh.key
|
|
||||||
{
|
{
|
||||||
self.app.should_refresh = true;
|
self.app.should_refresh = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.active_sonarr_block == ActiveSonarrBlock::SystemTaskStartConfirmPrompt
|
if self.active_sonarr_block == ActiveSonarrBlock::SystemTaskStartConfirmPrompt
|
||||||
&& self.key == DEFAULT_KEYBINDINGS.confirm.key
|
&& matches_key!(confirm, self.key)
|
||||||
{
|
{
|
||||||
self.app.data.sonarr_data.prompt_confirm = true;
|
self.app.data.sonarr_data.prompt_confirm = true;
|
||||||
self.app.data.sonarr_data.prompt_confirm_action =
|
self.app.data.sonarr_data.prompt_confirm_action =
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||||
|
use rstest::rstest;
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
@@ -960,6 +961,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_system_details_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = SystemDetailsHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extract_task_name() {
|
fn test_extract_task_name() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -456,6 +456,25 @@ mod tests {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rstest]
|
||||||
|
fn test_system_handler_ignore_special_keys(
|
||||||
|
#[values(true, false)] ignore_special_keys_for_textbox_input: bool,
|
||||||
|
) {
|
||||||
|
let mut app = App::test_default();
|
||||||
|
app.ignore_special_keys_for_textbox_input = ignore_special_keys_for_textbox_input;
|
||||||
|
let handler = SystemHandler::new(
|
||||||
|
DEFAULT_KEYBINDINGS.esc.key,
|
||||||
|
&mut app,
|
||||||
|
ActiveSonarrBlock::default(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
handler.ignore_special_keys(),
|
||||||
|
ignore_special_keys_for_textbox_input
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_system_handler_is_not_ready_when_loading() {
|
fn test_system_handler_is_not_ready_when_loading() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
|
|||||||
@@ -42,17 +42,17 @@ macro_rules! handle_table_events {
|
|||||||
fn [<handle_ $name _table_events>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
fn [<handle_ $name _table_events>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||||
if $self.is_ready() {
|
if $self.is_ready() {
|
||||||
match $self.key {
|
match $self.key {
|
||||||
_ if $self.key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.up.key => $self.[<handle_ $name _table_scroll_up>](config),
|
_ if $crate::matches_key!(up, $self.key, $self.ignore_special_keys()) => $self.[<handle_ $name _table_scroll_up>](config),
|
||||||
_ if $self.key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.down.key => $self.[<handle_ $name _table_scroll_down>](config),
|
_ if $crate::matches_key!(down, $self.key, $self.ignore_special_keys()) => $self.[<handle_ $name _table_scroll_down>](config),
|
||||||
_ if $self.key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.home.key => $self.[<handle_ $name _table_home>](config),
|
_ if $crate::matches_key!(home, $self.key) => $self.[<handle_ $name _table_home>](config),
|
||||||
_ if $self.key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.end.key => $self.[<handle_ $name _table_end>](config),
|
_ if $crate::matches_key!(end, $self.key) => $self.[<handle_ $name _table_end>](config),
|
||||||
_ if $self.key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.left.key
|
_ if $crate::matches_key!(left, $self.key, $self.ignore_special_keys())
|
||||||
|| $self.key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.right.key =>
|
|| $crate::matches_key!(right, $self.key, $self.ignore_special_keys()) =>
|
||||||
{
|
{
|
||||||
$self.[<handle_ $name _table_left_right>](config)
|
$self.[<handle_ $name _table_left_right>](config)
|
||||||
}
|
}
|
||||||
_ if $self.key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.submit.key => $self.[<handle_ $name _table_submit>](config),
|
_ if $crate::matches_key!(submit, $self.key) => $self.[<handle_ $name _table_submit>](config),
|
||||||
_ if $self.key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.esc.key => $self.[<handle_ $name _table_esc>](config),
|
_ if $crate::matches_key!(esc, $self.key) => $self.[<handle_ $name _table_esc>](config),
|
||||||
_ if config.searching_block.is_some()
|
_ if config.searching_block.is_some()
|
||||||
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() =>
|
||||||
{
|
{
|
||||||
@@ -63,11 +63,11 @@ macro_rules! handle_table_events {
|
|||||||
{
|
{
|
||||||
$self.[<handle_ $name _table_filter_box_input>]()
|
$self.[<handle_ $name _table_filter_box_input>]()
|
||||||
}
|
}
|
||||||
_ if $self.key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.filter.key
|
_ if $crate::matches_key!(filter, $self.key)
|
||||||
&& config.filtering_block.is_some() => $self.[<handle_ $name _table_filter_key>](config),
|
&& config.filtering_block.is_some() => $self.[<handle_ $name _table_filter_key>](config),
|
||||||
_ if $self.key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.search.key
|
_ if $crate::matches_key!(search, $self.key)
|
||||||
&& config.searching_block.is_some() => $self.[<handle_ $name _table_search_key>](config),
|
&& config.searching_block.is_some() => $self.[<handle_ $name _table_search_key>](config),
|
||||||
_ if $self.key == $crate::app::key_binding::DEFAULT_KEYBINDINGS.sort.key
|
_ if $crate::matches_key!(sort, $self.key)
|
||||||
&& config.sorting_block.is_some() => $self.[<handle_ $name _table_sort_key>](config),
|
&& config.sorting_block.is_some() => $self.[<handle_ $name _table_sort_key>](config),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
@@ -244,7 +244,7 @@ macro_rules! handle_table_events {
|
|||||||
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() =>
|
||||||
{
|
{
|
||||||
$self.app.pop_navigation_stack();
|
$self.app.pop_navigation_stack();
|
||||||
$self.app.should_ignore_quit_key = false;
|
$self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
|
|
||||||
if $table.search.is_some() {
|
if $table.search.is_some() {
|
||||||
let search_field_fn = config
|
let search_field_fn = config
|
||||||
@@ -267,7 +267,7 @@ macro_rules! handle_table_events {
|
|||||||
&& $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() =>
|
&& $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() =>
|
||||||
{
|
{
|
||||||
$self.app.pop_navigation_stack();
|
$self.app.pop_navigation_stack();
|
||||||
$self.app.should_ignore_quit_key = false;
|
$self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
|
|
||||||
if $table.filter.is_some() {
|
if $table.filter.is_some() {
|
||||||
let filter_field_fn = config
|
let filter_field_fn = config
|
||||||
@@ -305,7 +305,7 @@ macro_rules! handle_table_events {
|
|||||||
{
|
{
|
||||||
$self.app.pop_navigation_stack();
|
$self.app.pop_navigation_stack();
|
||||||
$table.reset_search();
|
$table.reset_search();
|
||||||
$self.app.should_ignore_quit_key = false;
|
$self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if (config.filtering_block.is_some()
|
_ if (config.filtering_block.is_some()
|
||||||
@@ -315,7 +315,7 @@ macro_rules! handle_table_events {
|
|||||||
{
|
{
|
||||||
$self.app.pop_navigation_stack();
|
$self.app.pop_navigation_stack();
|
||||||
$table.reset_filter();
|
$table.reset_filter();
|
||||||
$self.app.should_ignore_quit_key = false;
|
$self.app.ignore_special_keys_for_textbox_input = false;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
_ if config.table_block == $self.app.get_current_route()
|
_ if config.table_block == $self.app.get_current_route()
|
||||||
@@ -335,7 +335,7 @@ macro_rules! handle_table_events {
|
|||||||
.push_navigation_stack(config.filtering_block.expect("Filtering block is undefined").into());
|
.push_navigation_stack(config.filtering_block.expect("Filtering block is undefined").into());
|
||||||
$table.reset_filter();
|
$table.reset_filter();
|
||||||
$table.filter = Some($crate::models::HorizontallyScrollableText::default());
|
$table.filter = Some($crate::models::HorizontallyScrollableText::default());
|
||||||
$self.app.should_ignore_quit_key = true;
|
$self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
@@ -349,7 +349,7 @@ macro_rules! handle_table_events {
|
|||||||
.app
|
.app
|
||||||
.push_navigation_stack(config.searching_block.expect("Searching block is undefined"));
|
.push_navigation_stack(config.searching_block.expect("Searching block is undefined"));
|
||||||
$table.search = Some($crate::models::HorizontallyScrollableText::default());
|
$table.search = Some($crate::models::HorizontallyScrollableText::default());
|
||||||
$self.app.should_ignore_quit_key = true;
|
$self.app.ignore_special_keys_for_textbox_input = true;
|
||||||
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ mod tests {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn ignore_special_keys(&self) -> bool {
|
||||||
|
self.app.ignore_special_keys_for_textbox_input
|
||||||
|
}
|
||||||
|
|
||||||
fn new(
|
fn new(
|
||||||
key: Key,
|
key: Key,
|
||||||
app: &'a mut App<'b>,
|
app: &'a mut App<'b>,
|
||||||
@@ -648,7 +652,7 @@ mod tests {
|
|||||||
TableHandlerUnit::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::FilterMovies, None).handle();
|
TableHandlerUnit::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::FilterMovies, None).handle();
|
||||||
|
|
||||||
assert!(app.data.radarr_data.movies.filtered_items.is_some());
|
assert!(app.data.radarr_data.movies.filtered_items.is_some());
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
@@ -684,7 +688,7 @@ mod tests {
|
|||||||
|
|
||||||
TableHandlerUnit::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::FilterMovies, None).handle();
|
TableHandlerUnit::new(SUBMIT_KEY, &mut app, ActiveRadarrBlock::FilterMovies, None).handle();
|
||||||
|
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.radarr_data.movies.filtered_items.is_none());
|
assert!(app.data.radarr_data.movies.filtered_items.is_none());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
@@ -735,7 +739,7 @@ mod tests {
|
|||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
@@ -744,7 +748,7 @@ mod tests {
|
|||||||
TableHandlerUnit::new(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
TableHandlerUnit::new(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(app.data.radarr_data.movies.search, None);
|
assert_eq!(app.data.radarr_data.movies.search, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -754,7 +758,7 @@ mod tests {
|
|||||||
active_radarr_block: ActiveRadarrBlock,
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
) {
|
) {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.push_navigation_stack(active_radarr_block.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
@@ -773,7 +777,7 @@ mod tests {
|
|||||||
TableHandlerUnit::new(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
TableHandlerUnit::new(ESC_KEY, &mut app, active_radarr_block, None).handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(app.data.radarr_data.movies.filter, None);
|
assert_eq!(app.data.radarr_data.movies.filter, None);
|
||||||
assert_eq!(app.data.radarr_data.movies.filtered_items, None);
|
assert_eq!(app.data.radarr_data.movies.filtered_items, None);
|
||||||
assert_eq!(app.data.radarr_data.movies.filtered_state, None);
|
assert_eq!(app.data.radarr_data.movies.filtered_state, None);
|
||||||
@@ -820,7 +824,7 @@ mod tests {
|
|||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::SearchMovie.into()
|
ActiveRadarrBlock::SearchMovie.into()
|
||||||
);
|
);
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.data.radarr_data.movies.search,
|
app.data.radarr_data.movies.search,
|
||||||
Some(HorizontallyScrollableText::default())
|
Some(HorizontallyScrollableText::default())
|
||||||
@@ -847,7 +851,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(app.data.radarr_data.movies.search, None);
|
assert_eq!(app.data.radarr_data.movies.search, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -869,7 +873,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(app.data.radarr_data.movies.search, None);
|
assert_eq!(app.data.radarr_data.movies.search, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -894,7 +898,7 @@ mod tests {
|
|||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::FilterMovies.into()
|
ActiveRadarrBlock::FilterMovies.into()
|
||||||
);
|
);
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.radarr_data.movies.filter.is_some());
|
assert!(app.data.radarr_data.movies.filter.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -918,14 +922,14 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert!(app.data.radarr_data.movies.filter.is_none());
|
assert!(app.data.radarr_data.movies.filter.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_filter_table_key_resets_previous_filter() {
|
fn test_filter_table_key_resets_previous_filter() {
|
||||||
let mut app = App::test_default();
|
let mut app = App::test_default();
|
||||||
app.should_ignore_quit_key = true;
|
app.ignore_special_keys_for_textbox_input = true;
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
app.push_navigation_stack(ActiveRadarrBlock::Movies.into());
|
||||||
app.data.radarr_data = create_test_radarr_data();
|
app.data.radarr_data = create_test_radarr_data();
|
||||||
app
|
app
|
||||||
@@ -947,7 +951,7 @@ mod tests {
|
|||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
ActiveRadarrBlock::FilterMovies.into()
|
ActiveRadarrBlock::FilterMovies.into()
|
||||||
);
|
);
|
||||||
assert!(app.should_ignore_quit_key);
|
assert!(app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.data.radarr_data.movies.filter,
|
app.data.radarr_data.movies.filter,
|
||||||
Some(HorizontallyScrollableText::default())
|
Some(HorizontallyScrollableText::default())
|
||||||
@@ -974,7 +978,7 @@ mod tests {
|
|||||||
.handle();
|
.handle();
|
||||||
|
|
||||||
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
assert_eq!(app.get_current_route(), ActiveRadarrBlock::Movies.into());
|
||||||
assert!(!app.should_ignore_quit_key);
|
assert!(!app.ignore_special_keys_for_textbox_input);
|
||||||
assert_eq!(app.data.radarr_data.movies.filter, None);
|
assert_eq!(app.data.radarr_data.movies.filter, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1040,7 +1044,7 @@ mod tests {
|
|||||||
app.data.radarr_data.movies.search = Some(HorizontallyScrollableText::default());
|
app.data.radarr_data.movies.search = Some(HorizontallyScrollableText::default());
|
||||||
|
|
||||||
TableHandlerUnit::new(
|
TableHandlerUnit::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::SearchMovie,
|
ActiveRadarrBlock::SearchMovie,
|
||||||
None,
|
None,
|
||||||
@@ -1049,7 +1053,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_str_eq!(
|
assert_str_eq!(
|
||||||
app.data.radarr_data.movies.search.as_ref().unwrap().text,
|
app.data.radarr_data.movies.search.as_ref().unwrap().text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1065,7 +1069,7 @@ mod tests {
|
|||||||
app.data.radarr_data.movies.filter = Some(HorizontallyScrollableText::default());
|
app.data.radarr_data.movies.filter = Some(HorizontallyScrollableText::default());
|
||||||
|
|
||||||
TableHandlerUnit::new(
|
TableHandlerUnit::new(
|
||||||
Key::Char('h'),
|
Key::Char('a'),
|
||||||
&mut app,
|
&mut app,
|
||||||
ActiveRadarrBlock::FilterMovies,
|
ActiveRadarrBlock::FilterMovies,
|
||||||
None,
|
None,
|
||||||
@@ -1074,7 +1078,7 @@ mod tests {
|
|||||||
|
|
||||||
assert_str_eq!(
|
assert_str_eq!(
|
||||||
app.data.radarr_data.movies.filter.as_ref().unwrap().text,
|
app.data.radarr_data.movies.filter.as_ref().unwrap().text,
|
||||||
"h"
|
"a"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -246,7 +246,7 @@ async fn start_ui(
|
|||||||
|
|
||||||
match input_events.next()? {
|
match input_events.next()? {
|
||||||
InputEvent::KeyEvent(key) => {
|
InputEvent::KeyEvent(key) => {
|
||||||
if key == Key::Char('q') && !app.should_ignore_quit_key {
|
if key == Key::Char('q') && !app.ignore_special_keys_for_textbox_input {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user