feat(readarr): add the system handlers

SystemHandler owns the System tab: tab movement, the refresh key, and the
five keys that open the queued events, logs, tasks, and updates views. It
delegates every system detail block to SystemDetailsHandler, which scrolls
the log, task, queued event, and update views and drives the start task
confirmation prompt.

Both land together because SystemHandler::accepts covers the system detail
blocks that only SystemDetailsHandler implements, so landing the parent
alone would accept those blocks while doing nothing with them.
This commit is contained in:
Dark-Alex-17 committed 2026-09-08 09:33:26 -06:00
1 parent 58fe7d79ae
commit 24c5dedd0c
6 files changed
+2017

No files matched your search

+5
View File
@@ -4,6 +4,7 @@ use crate::handlers::readarr_handlers::downloads::DownloadsHandler;
use crate::handlers::readarr_handlers::history::HistoryHandler;
use crate::handlers::readarr_handlers::library::LibraryHandler;
use crate::handlers::readarr_handlers::root_folders::RootFoldersHandler;
use crate::handlers::readarr_handlers::system::SystemHandler;
use crate::models::Route;
use crate::{
app::App, event::Key, matches_key,
@@ -15,6 +16,7 @@ mod downloads;
mod history;
mod library;
mod root_folders;
mod system;
#[cfg(test)]
#[path = "readarr_handler_tests.rs"]
@@ -46,6 +48,9 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveReadarrBlock> for ReadarrHandler<'a,
RootFoldersHandler::new(self.key, self.app, self.active_readarr_block, self.context)
.handle();
}
_ if SystemHandler::accepts(self.active_readarr_block) => {
SystemHandler::new(self.key, self.app, self.active_readarr_block, self.context).handle();
}
_ => self.handle_key_event(),
}
}
@@ -246,4 +246,23 @@ mod tests {
active_readarr_block
);
}
#[rstest]
fn test_delegates_system_blocks_to_system_handler(
#[values(
ActiveReadarrBlock::System,
ActiveReadarrBlock::SystemLogs,
ActiveReadarrBlock::SystemQueuedEvents,
ActiveReadarrBlock::SystemTasks,
ActiveReadarrBlock::SystemTaskStartConfirmPrompt,
ActiveReadarrBlock::SystemUpdates
)]
active_readarr_block: ActiveReadarrBlock,
) {
test_handler_delegation!(
ReadarrHandler,
ActiveReadarrBlock::System,
active_readarr_block
);
}
}
+135
View File
@@ -0,0 +1,135 @@
use crate::app::App;
use crate::event::Key;
use crate::handlers::readarr_handlers::handle_change_tab_left_right_keys;
use crate::handlers::readarr_handlers::system::system_details_handler::SystemDetailsHandler;
use crate::handlers::{KeyEventHandler, handle_clear_errors};
use crate::matches_key;
use crate::models::servarr_data::readarr::readarr_data::ActiveReadarrBlock;
use crate::models::{Route, Scrollable};
mod system_details_handler;
#[cfg(test)]
#[path = "system_handler_tests.rs"]
mod system_handler_tests;
pub(super) struct SystemHandler<'a, 'b> {
key: Key,
app: &'a mut App<'b>,
active_readarr_block: ActiveReadarrBlock,
context: Option<ActiveReadarrBlock>,
}
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveReadarrBlock> for SystemHandler<'a, 'b> {
fn handle(&mut self) {
match self.active_readarr_block {
_ if SystemDetailsHandler::accepts(self.active_readarr_block) => {
SystemDetailsHandler::new(self.key, self.app, self.active_readarr_block, self.context)
.handle()
}
_ => self.handle_key_event(),
}
}
fn accepts(active_block: ActiveReadarrBlock) -> bool {
SystemDetailsHandler::accepts(active_block) || active_block == ActiveReadarrBlock::System
}
fn ignore_special_keys(&self) -> bool {
self.app.ignore_special_keys_for_textbox_input
}
fn new(
key: Key,
app: &'a mut App<'b>,
active_block: ActiveReadarrBlock,
context: Option<ActiveReadarrBlock>,
) -> SystemHandler<'a, 'b> {
SystemHandler {
key,
app,
active_readarr_block: active_block,
context,
}
}
fn get_key(&self) -> Key {
self.key
}
fn is_ready(&self) -> bool {
!self.app.is_loading
&& !self.app.data.readarr_data.logs.is_empty()
&& !self.app.data.readarr_data.queued_events.is_empty()
&& !self.app.data.readarr_data.tasks.is_empty()
}
fn handle_scroll_up(&mut self) {}
fn handle_scroll_down(&mut self) {}
fn handle_home(&mut self) {}
fn handle_end(&mut self) {}
fn handle_delete(&mut self) {}
fn handle_left_right_action(&mut self) {
if self.active_readarr_block == ActiveReadarrBlock::System {
handle_change_tab_left_right_keys(self.app, self.key);
}
}
fn handle_submit(&mut self) {}
fn handle_esc(&mut self) {
handle_clear_errors(self.app)
}
fn handle_char_key_event(&mut self) {
if self.active_readarr_block == ActiveReadarrBlock::System {
let key = self.key;
match self.key {
_ if matches_key!(refresh, key) => {
self.app.should_refresh = true;
}
_ if matches_key!(events, key) => {
self
.app
.push_navigation_stack(ActiveReadarrBlock::SystemQueuedEvents.into());
}
_ if matches_key!(logs, key) => {
self
.app
.push_navigation_stack(ActiveReadarrBlock::SystemLogs.into());
self
.app
.data
.readarr_data
.log_details
.set_items(self.app.data.readarr_data.logs.items.to_vec());
self.app.data.readarr_data.log_details.scroll_to_bottom();
}
_ if matches_key!(tasks, key) => {
self
.app
.push_navigation_stack(ActiveReadarrBlock::SystemTasks.into());
}
_ if matches_key!(update, key) => {
self
.app
.push_navigation_stack(ActiveReadarrBlock::SystemUpdates.into());
}
_ => (),
}
}
}
fn app_mut(&mut self) -> &mut App<'b> {
self.app
}
fn current_route(&self) -> Route {
self.app.get_current_route()
}
}
@@ -0,0 +1,211 @@
use crate::app::App;
use crate::event::Key;
use crate::handlers::{KeyEventHandler, handle_prompt_toggle};
use crate::matches_key;
use crate::models::readarr_models::ReadarrTaskName;
use crate::models::servarr_data::readarr::readarr_data::{
ActiveReadarrBlock, SYSTEM_DETAILS_BLOCKS,
};
use crate::models::stateful_list::StatefulList;
use crate::models::{Route, Scrollable};
use crate::network::readarr_network::ReadarrEvent;
#[cfg(test)]
#[path = "system_details_handler_tests.rs"]
mod system_details_handler_tests;
pub(super) struct SystemDetailsHandler<'a, 'b> {
key: Key,
app: &'a mut App<'b>,
active_readarr_block: ActiveReadarrBlock,
_context: Option<ActiveReadarrBlock>,
}
impl SystemDetailsHandler<'_, '_> {
fn extract_task_name(&self) -> ReadarrTaskName {
self
.app
.data
.readarr_data
.tasks
.current_selection()
.task_name
}
}
impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveReadarrBlock> for SystemDetailsHandler<'a, 'b> {
fn accepts(active_block: ActiveReadarrBlock) -> bool {
SYSTEM_DETAILS_BLOCKS.contains(&active_block)
}
fn ignore_special_keys(&self) -> bool {
self.app.ignore_special_keys_for_textbox_input
}
fn new(
key: Key,
app: &'a mut App<'b>,
active_block: ActiveReadarrBlock,
context: Option<ActiveReadarrBlock>,
) -> SystemDetailsHandler<'a, 'b> {
SystemDetailsHandler {
key,
app,
active_readarr_block: active_block,
_context: context,
}
}
fn get_key(&self) -> Key {
self.key
}
fn is_ready(&self) -> bool {
!self.app.is_loading
&& (!self.app.data.readarr_data.log_details.is_empty()
|| !self.app.data.readarr_data.tasks.is_empty()
|| !self.app.data.readarr_data.updates.is_empty())
}
fn handle_scroll_up(&mut self) {
match self.active_readarr_block {
ActiveReadarrBlock::SystemLogs => self.app.data.readarr_data.log_details.scroll_up(),
ActiveReadarrBlock::SystemTasks => self.app.data.readarr_data.tasks.scroll_up(),
ActiveReadarrBlock::SystemUpdates => self.app.data.readarr_data.updates.scroll_up(),
ActiveReadarrBlock::SystemQueuedEvents => {
self.app.data.readarr_data.queued_events.scroll_up()
}
_ => (),
}
}
fn handle_scroll_down(&mut self) {
match self.active_readarr_block {
ActiveReadarrBlock::SystemLogs => self.app.data.readarr_data.log_details.scroll_down(),
ActiveReadarrBlock::SystemTasks => self.app.data.readarr_data.tasks.scroll_down(),
ActiveReadarrBlock::SystemUpdates => self.app.data.readarr_data.updates.scroll_down(),
ActiveReadarrBlock::SystemQueuedEvents => {
self.app.data.readarr_data.queued_events.scroll_down()
}
_ => (),
}
}
fn handle_home(&mut self) {
match self.active_readarr_block {
ActiveReadarrBlock::SystemLogs => self.app.data.readarr_data.log_details.scroll_to_top(),
ActiveReadarrBlock::SystemTasks => self.app.data.readarr_data.tasks.scroll_to_top(),
ActiveReadarrBlock::SystemUpdates => self.app.data.readarr_data.updates.scroll_to_top(),
ActiveReadarrBlock::SystemQueuedEvents => {
self.app.data.readarr_data.queued_events.scroll_to_top()
}
_ => (),
}
}
fn handle_end(&mut self) {
match self.active_readarr_block {
ActiveReadarrBlock::SystemLogs => self.app.data.readarr_data.log_details.scroll_to_bottom(),
ActiveReadarrBlock::SystemTasks => self.app.data.readarr_data.tasks.scroll_to_bottom(),
ActiveReadarrBlock::SystemUpdates => self.app.data.readarr_data.updates.scroll_to_bottom(),
ActiveReadarrBlock::SystemQueuedEvents => {
self.app.data.readarr_data.queued_events.scroll_to_bottom()
}
_ => (),
}
}
fn handle_delete(&mut self) {}
fn handle_left_right_action(&mut self) {
let key = self.key;
match self.active_readarr_block {
ActiveReadarrBlock::SystemLogs => match self.key {
_ if matches_key!(left, key) => {
self
.app
.data
.readarr_data
.log_details
.items
.iter()
.for_each(|log| log.scroll_right());
}
_ if matches_key!(right, key) => {
self
.app
.data
.readarr_data
.log_details
.items
.iter()
.for_each(|log| log.scroll_left());
}
_ => (),
},
ActiveReadarrBlock::SystemTaskStartConfirmPrompt => handle_prompt_toggle(self.app, self.key),
_ => (),
}
}
fn handle_submit(&mut self) {
match self.active_readarr_block {
ActiveReadarrBlock::SystemTasks => {
self
.app
.push_navigation_stack(ActiveReadarrBlock::SystemTaskStartConfirmPrompt.into());
}
ActiveReadarrBlock::SystemTaskStartConfirmPrompt => {
if self.app.data.readarr_data.prompt_confirm {
self.app.data.readarr_data.prompt_confirm_action =
Some(ReadarrEvent::StartTask(self.extract_task_name()));
}
self.app.pop_navigation_stack();
}
_ => (),
}
}
fn handle_esc(&mut self) {
match self.active_readarr_block {
ActiveReadarrBlock::SystemLogs => {
self.app.data.readarr_data.log_details = StatefulList::default();
self.app.pop_navigation_stack()
}
ActiveReadarrBlock::SystemQueuedEvents
| ActiveReadarrBlock::SystemTasks
| ActiveReadarrBlock::SystemUpdates => self.app.pop_navigation_stack(),
ActiveReadarrBlock::SystemTaskStartConfirmPrompt => {
self.app.pop_navigation_stack();
self.app.data.readarr_data.prompt_confirm = false;
}
_ => (),
}
}
fn handle_char_key_event(&mut self) {
if SYSTEM_DETAILS_BLOCKS.contains(&self.active_readarr_block) && matches_key!(refresh, self.key)
{
self.app.should_refresh = true;
}
if self.active_readarr_block == ActiveReadarrBlock::SystemTaskStartConfirmPrompt
&& matches_key!(confirm, self.key)
{
self.app.data.readarr_data.prompt_confirm = true;
self.app.data.readarr_data.prompt_confirm_action =
Some(ReadarrEvent::StartTask(self.extract_task_name()));
self.app.pop_navigation_stack();
}
}
fn app_mut(&mut self) -> &mut App<'b> {
self.app
}
fn current_route(&self) -> Route {
self.app.get_current_route()
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,496 @@
#[cfg(test)]
mod tests {
use rstest::rstest;
use strum::IntoEnumIterator;
use crate::app::App;
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
use crate::assert_navigation_pushed;
use crate::event::Key;
use crate::handlers::KeyEventHandler;
use crate::handlers::readarr_handlers::system::SystemHandler;
use crate::models::HorizontallyScrollableText;
use crate::models::readarr_models::{ReadarrTask, ReadarrTaskName};
use crate::models::servarr_data::readarr::readarr_data::{
ActiveReadarrBlock, SYSTEM_DETAILS_BLOCKS,
};
use crate::models::servarr_models::QueueEvent;
use crate::test_handler_delegation;
mod test_handle_left_right_action {
use pretty_assertions::assert_eq;
use super::*;
use crate::assert_navigation_pushed;
#[rstest]
fn test_system_tab_left(#[values(true, false)] is_loading: bool) {
let mut app = App::test_default();
app.push_navigation_stack(ActiveReadarrBlock::System.into());
app.is_loading = is_loading;
app.data.readarr_data.main_tabs.set_index(6);
SystemHandler::new(
DEFAULT_KEYBINDINGS.left.key,
&mut app,
ActiveReadarrBlock::System,
None,
)
.handle();
assert_eq!(
app.data.readarr_data.main_tabs.get_active_route(),
ActiveReadarrBlock::Indexers.into()
);
assert_navigation_pushed!(app, ActiveReadarrBlock::Indexers.into());
}
#[rstest]
fn test_system_tab_right(#[values(true, false)] is_loading: bool) {
let mut app = App::test_default();
app.push_navigation_stack(ActiveReadarrBlock::System.into());
app.is_loading = is_loading;
app.data.readarr_data.main_tabs.set_index(6);
SystemHandler::new(
DEFAULT_KEYBINDINGS.right.key,
&mut app,
ActiveReadarrBlock::System,
None,
)
.handle();
assert_eq!(
app.data.readarr_data.main_tabs.get_active_route(),
ActiveReadarrBlock::Authors.into()
);
assert_navigation_pushed!(app, ActiveReadarrBlock::Authors.into());
}
}
mod test_handle_esc {
use super::*;
use crate::assert_navigation_popped;
const ESC_KEY: Key = DEFAULT_KEYBINDINGS.esc.key;
#[rstest]
fn test_default_esc(#[values(true, false)] is_loading: bool) {
let mut app = App::test_default();
app.is_loading = is_loading;
app.error = "test error".to_owned().into();
app.push_navigation_stack(ActiveReadarrBlock::System.into());
app.push_navigation_stack(ActiveReadarrBlock::System.into());
SystemHandler::new(ESC_KEY, &mut app, ActiveReadarrBlock::System, None).handle();
assert_navigation_popped!(app, ActiveReadarrBlock::System.into());
assert_is_empty!(app.error.text);
}
}
mod test_handle_key_char {
use pretty_assertions::{assert_eq, assert_str_eq};
use super::*;
#[test]
fn test_update_system_key() {
let mut app = App::test_default();
app.push_navigation_stack(ActiveReadarrBlock::System.into());
seed_system_data(&mut app);
SystemHandler::new(
DEFAULT_KEYBINDINGS.update.key,
&mut app,
ActiveReadarrBlock::System,
None,
)
.handle();
assert_navigation_pushed!(app, ActiveReadarrBlock::SystemUpdates.into());
}
#[test]
fn test_update_system_key_no_op_if_not_ready() {
let mut app = App::test_default();
app.is_loading = true;
app.push_navigation_stack(ActiveReadarrBlock::System.into());
seed_system_data(&mut app);
SystemHandler::new(
DEFAULT_KEYBINDINGS.update.key,
&mut app,
ActiveReadarrBlock::System,
None,
)
.handle();
assert_eq!(app.get_current_route(), ActiveReadarrBlock::System.into());
}
#[test]
fn test_queued_events_key() {
let mut app = App::test_default();
app.push_navigation_stack(ActiveReadarrBlock::System.into());
seed_system_data(&mut app);
SystemHandler::new(
DEFAULT_KEYBINDINGS.events.key,
&mut app,
ActiveReadarrBlock::System,
None,
)
.handle();
assert_navigation_pushed!(app, ActiveReadarrBlock::SystemQueuedEvents.into());
}
#[test]
fn test_queued_events_key_no_op_if_not_ready() {
let mut app = App::test_default();
app.is_loading = true;
app.push_navigation_stack(ActiveReadarrBlock::System.into());
seed_system_data(&mut app);
SystemHandler::new(
DEFAULT_KEYBINDINGS.events.key,
&mut app,
ActiveReadarrBlock::System,
None,
)
.handle();
assert_eq!(app.get_current_route(), ActiveReadarrBlock::System.into());
}
#[test]
fn test_refresh_system_key() {
let mut app = App::test_default();
seed_system_data(&mut app);
app.push_navigation_stack(ActiveReadarrBlock::System.into());
SystemHandler::new(
DEFAULT_KEYBINDINGS.refresh.key,
&mut app,
ActiveReadarrBlock::System,
None,
)
.handle();
assert_navigation_pushed!(app, ActiveReadarrBlock::System.into());
assert!(app.should_refresh);
}
#[test]
fn test_refresh_system_key_no_op_if_not_ready() {
let mut app = App::test_default();
app.is_loading = true;
seed_system_data(&mut app);
app.push_navigation_stack(ActiveReadarrBlock::System.into());
SystemHandler::new(
DEFAULT_KEYBINDINGS.refresh.key,
&mut app,
ActiveReadarrBlock::System,
None,
)
.handle();
assert_eq!(app.get_current_route(), ActiveReadarrBlock::System.into());
assert!(!app.should_refresh);
}
#[test]
fn test_logs_key() {
let mut app = App::test_default();
app.push_navigation_stack(ActiveReadarrBlock::System.into());
seed_system_data(&mut app);
SystemHandler::new(
DEFAULT_KEYBINDINGS.logs.key,
&mut app,
ActiveReadarrBlock::System,
None,
)
.handle();
assert_navigation_pushed!(app, ActiveReadarrBlock::SystemLogs.into());
assert_eq!(
app.data.readarr_data.log_details.items,
app.data.readarr_data.logs.items
);
assert_str_eq!(
app.data.readarr_data.log_details.current_selection().text,
"log line gamma"
);
}
#[test]
fn test_logs_key_no_op_when_not_ready() {
let mut app = App::test_default();
app.is_loading = true;
app.push_navigation_stack(ActiveReadarrBlock::System.into());
seed_system_data(&mut app);
SystemHandler::new(
DEFAULT_KEYBINDINGS.logs.key,
&mut app,
ActiveReadarrBlock::System,
None,
)
.handle();
assert_eq!(app.get_current_route(), ActiveReadarrBlock::System.into());
assert_is_empty!(app.data.readarr_data.log_details);
}
#[test]
fn test_tasks_key() {
let mut app = App::test_default();
app.push_navigation_stack(ActiveReadarrBlock::System.into());
seed_system_data(&mut app);
SystemHandler::new(
DEFAULT_KEYBINDINGS.tasks.key,
&mut app,
ActiveReadarrBlock::System,
None,
)
.handle();
assert_navigation_pushed!(app, ActiveReadarrBlock::SystemTasks.into());
}
#[test]
fn test_tasks_key_no_op_when_not_ready() {
let mut app = App::test_default();
app.is_loading = true;
app.push_navigation_stack(ActiveReadarrBlock::System.into());
seed_system_data(&mut app);
SystemHandler::new(
DEFAULT_KEYBINDINGS.tasks.key,
&mut app,
ActiveReadarrBlock::System,
None,
)
.handle();
assert_eq!(app.get_current_route(), ActiveReadarrBlock::System.into());
}
#[test]
fn test_unmapped_key_is_a_no_op() {
let mut app = App::test_default();
app.push_navigation_stack(ActiveReadarrBlock::System.into());
seed_system_data(&mut app);
SystemHandler::new(
DEFAULT_KEYBINDINGS.add.key,
&mut app,
ActiveReadarrBlock::System,
None,
)
.handle();
assert_eq!(app.get_current_route(), ActiveReadarrBlock::System.into());
assert!(!app.should_refresh);
assert_is_empty!(app.data.readarr_data.log_details);
}
}
#[rstest]
fn test_delegates_system_details_blocks_to_system_details_handler(
#[values(
ActiveReadarrBlock::SystemLogs,
ActiveReadarrBlock::SystemQueuedEvents,
ActiveReadarrBlock::SystemTasks,
ActiveReadarrBlock::SystemTaskStartConfirmPrompt,
ActiveReadarrBlock::SystemUpdates
)]
active_readarr_block: ActiveReadarrBlock,
) {
test_handler_delegation!(
SystemHandler,
ActiveReadarrBlock::System,
active_readarr_block
);
}
#[test]
fn test_system_handler_accepts() {
let mut system_blocks = vec![ActiveReadarrBlock::System];
system_blocks.extend(SYSTEM_DETAILS_BLOCKS);
ActiveReadarrBlock::iter().for_each(|active_readarr_block| {
if system_blocks.contains(&active_readarr_block) {
assert!(SystemHandler::accepts(active_readarr_block));
} else {
assert!(!SystemHandler::accepts(active_readarr_block));
}
})
}
#[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,
ActiveReadarrBlock::default(),
None,
);
assert_eq!(
handler.ignore_special_keys(),
ignore_special_keys_for_textbox_input
);
}
#[test]
fn test_system_handler_is_not_ready_when_loading() {
let mut app = App::test_default();
app.push_navigation_stack(ActiveReadarrBlock::System.into());
app.is_loading = true;
seed_system_data(&mut app);
let system_handler = SystemHandler::new(
DEFAULT_KEYBINDINGS.update.key,
&mut app,
ActiveReadarrBlock::System,
None,
);
assert!(!system_handler.is_ready());
}
#[test]
fn test_system_handler_is_not_ready_when_logs_is_empty() {
let mut app = App::test_default();
app.push_navigation_stack(ActiveReadarrBlock::System.into());
app.is_loading = false;
app.data.readarr_data.tasks.set_items(tasks_vec());
app
.data
.readarr_data
.queued_events
.set_items(queued_events_vec());
let system_handler = SystemHandler::new(
DEFAULT_KEYBINDINGS.update.key,
&mut app,
ActiveReadarrBlock::System,
None,
);
assert!(!system_handler.is_ready());
}
#[test]
fn test_system_handler_is_not_ready_when_tasks_is_empty() {
let mut app = App::test_default();
app.push_navigation_stack(ActiveReadarrBlock::System.into());
app.is_loading = false;
app.data.readarr_data.logs.set_items(logs_vec());
app
.data
.readarr_data
.queued_events
.set_items(queued_events_vec());
let system_handler = SystemHandler::new(
DEFAULT_KEYBINDINGS.update.key,
&mut app,
ActiveReadarrBlock::System,
None,
);
assert!(!system_handler.is_ready());
}
#[test]
fn test_system_handler_is_not_ready_when_queued_events_is_empty() {
let mut app = App::test_default();
app.push_navigation_stack(ActiveReadarrBlock::System.into());
app.is_loading = false;
app.data.readarr_data.logs.set_items(logs_vec());
app.data.readarr_data.tasks.set_items(tasks_vec());
let system_handler = SystemHandler::new(
DEFAULT_KEYBINDINGS.update.key,
&mut app,
ActiveReadarrBlock::System,
None,
);
assert!(!system_handler.is_ready());
}
#[test]
fn test_system_handler_is_ready_when_all_required_tables_are_not_empty() {
let mut app = App::test_default();
app.push_navigation_stack(ActiveReadarrBlock::System.into());
app.is_loading = false;
seed_system_data(&mut app);
let system_handler = SystemHandler::new(
DEFAULT_KEYBINDINGS.update.key,
&mut app,
ActiveReadarrBlock::System,
None,
);
assert!(system_handler.is_ready());
}
fn seed_system_data(app: &mut App<'_>) {
app.data.readarr_data.logs.set_items(logs_vec());
app
.data
.readarr_data
.queued_events
.set_items(queued_events_vec());
app.data.readarr_data.tasks.set_items(tasks_vec());
}
fn logs_vec() -> Vec<HorizontallyScrollableText> {
vec![
HorizontallyScrollableText::from("log line alpha"),
HorizontallyScrollableText::from("log line beta"),
HorizontallyScrollableText::from("log line gamma"),
]
}
fn queued_events_vec() -> Vec<QueueEvent> {
vec![
QueueEvent {
name: "queued event one".to_owned(),
..QueueEvent::default()
},
QueueEvent {
name: "queued event two".to_owned(),
..QueueEvent::default()
},
]
}
fn tasks_vec() -> Vec<ReadarrTask> {
vec![
ReadarrTask {
name: "Backup task".to_owned(),
task_name: ReadarrTaskName::Backup,
..ReadarrTask::default()
},
ReadarrTask {
name: "Rss sync task".to_owned(),
task_name: ReadarrTaskName::RssSync,
..ReadarrTask::default()
},
]
}
}