Added horizontal scrolling for long movie titles, a refresh key, and fixed the network issues so that network requests are sent once every 20 seconds by default to not stress out the server.
This commit is contained in:
@@ -20,6 +20,7 @@ generate_keybindings! {
|
||||
sort,
|
||||
edit,
|
||||
refresh,
|
||||
update,
|
||||
home,
|
||||
end,
|
||||
delete,
|
||||
@@ -78,6 +79,10 @@ pub const DEFAULT_KEYBINDINGS: KeyBindings = KeyBindings {
|
||||
key: Key::Char('r'),
|
||||
desc: "Refresh",
|
||||
},
|
||||
update: KeyBinding {
|
||||
key: Key::Char('u'),
|
||||
desc: "Update All",
|
||||
},
|
||||
home: KeyBinding {
|
||||
key: Key::Home,
|
||||
desc: "Home",
|
||||
|
||||
+2
-9
@@ -1,5 +1,3 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use log::{debug, error};
|
||||
use reqwest::Client;
|
||||
@@ -28,7 +26,6 @@ pub struct App {
|
||||
pub ticks_until_scroll: u64,
|
||||
pub tick_count: u64,
|
||||
pub last_tick: Instant,
|
||||
pub network_tick_frequency: Duration,
|
||||
pub is_routing: bool,
|
||||
pub is_loading: bool,
|
||||
pub should_refresh: bool,
|
||||
@@ -137,10 +134,9 @@ impl Default for App {
|
||||
]),
|
||||
client: Client::new(),
|
||||
title: "Managarr",
|
||||
tick_until_poll: 50,
|
||||
tick_until_poll: 400,
|
||||
ticks_until_scroll: 4,
|
||||
tick_count: 0,
|
||||
network_tick_frequency: Duration::from_secs(20),
|
||||
last_tick: Instant::now(),
|
||||
is_loading: false,
|
||||
is_routing: false,
|
||||
@@ -181,8 +177,6 @@ impl Default for RadarrConfig {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||
use tokio::sync::mpsc;
|
||||
@@ -220,10 +214,9 @@ mod tests {
|
||||
]
|
||||
);
|
||||
assert_str_eq!(app.title, "Managarr");
|
||||
assert_eq!(app.tick_until_poll, 50);
|
||||
assert_eq!(app.tick_until_poll, 400);
|
||||
assert_eq!(app.ticks_until_scroll, 4);
|
||||
assert_eq!(app.tick_count, 0);
|
||||
assert_eq!(app.network_tick_frequency, Duration::from_secs(20));
|
||||
assert!(!app.is_loading);
|
||||
assert!(!app.is_routing);
|
||||
assert!(!app.should_refresh);
|
||||
|
||||
+19
-25
@@ -1,5 +1,3 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use bimap::BiMap;
|
||||
use chrono::{DateTime, Utc};
|
||||
use strum::IntoEnumIterator;
|
||||
@@ -218,7 +216,7 @@ impl Default for RadarrData {
|
||||
title: "Library".to_owned(),
|
||||
route: ActiveRadarrBlock::Movies.into(),
|
||||
help: String::default(),
|
||||
contextual_help: Some("<a> add | <e> edit | <s> search | <f> filter | <r> refresh | <enter> details | <esc> cancel filter | <del> delete"
|
||||
contextual_help: Some("<a> add | <e> edit | <s> search | <f> filter | <r> refresh | <u> update all | <enter> details | <esc> cancel filter | <del> delete"
|
||||
.to_owned()),
|
||||
},
|
||||
TabRoute {
|
||||
@@ -231,7 +229,7 @@ impl Default for RadarrData {
|
||||
title: "Collections".to_owned(),
|
||||
route: ActiveRadarrBlock::Collections.into(),
|
||||
help: String::default(),
|
||||
contextual_help: Some("<s> search | <f> filter | <r> refresh | <enter> details | <esc> cancel filter"
|
||||
contextual_help: Some("<s> search | <f> filter | <r> refresh | <u> update all | <enter> details | <esc> cancel filter"
|
||||
.to_owned()),
|
||||
},
|
||||
]),
|
||||
@@ -239,37 +237,37 @@ impl Default for RadarrData {
|
||||
TabRoute {
|
||||
title: "Details".to_owned(),
|
||||
route: ActiveRadarrBlock::MovieDetails.into(),
|
||||
help: "<r> refresh | <e> edit | <s> auto search | <esc> close".to_owned(),
|
||||
help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close".to_owned(),
|
||||
contextual_help: None
|
||||
},
|
||||
TabRoute {
|
||||
title: "History".to_owned(),
|
||||
route: ActiveRadarrBlock::MovieHistory.into(),
|
||||
help: "<r> refresh | <e> edit | <s> auto search | <esc> close".to_owned(),
|
||||
help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close".to_owned(),
|
||||
contextual_help: None
|
||||
},
|
||||
TabRoute {
|
||||
title: "File".to_owned(),
|
||||
route: ActiveRadarrBlock::FileInfo.into(),
|
||||
help: "<r> refresh | <e> edit | <s> auto search | <esc> close".to_owned(),
|
||||
help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close".to_owned(),
|
||||
contextual_help: None,
|
||||
},
|
||||
TabRoute {
|
||||
title: "Cast".to_owned(),
|
||||
route: ActiveRadarrBlock::Cast.into(),
|
||||
help: "<r> refresh | <e> edit | <s> auto search | <esc> close".to_owned(),
|
||||
help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close".to_owned(),
|
||||
contextual_help: None,
|
||||
},
|
||||
TabRoute {
|
||||
title: "Crew".to_owned(),
|
||||
route: ActiveRadarrBlock::Crew.into(),
|
||||
help: "<r> refresh | <e> edit | <s> auto search | <esc> close".to_owned(),
|
||||
help: "<r> refresh | <u> update | <e> edit | <s> auto search | <esc> close".to_owned(),
|
||||
contextual_help: None,
|
||||
},
|
||||
TabRoute {
|
||||
title: "Manual Search".to_owned(),
|
||||
route: ActiveRadarrBlock::ManualSearch.into(),
|
||||
help: "<r> refresh | <e> edit | <o> sort | <s> auto search | <esc> close".to_owned(),
|
||||
help: "<r> refresh | <u> update | <e> edit | <o> sort | <s> auto search | <esc> close".to_owned(),
|
||||
contextual_help: Some("<enter> details".to_owned())
|
||||
}
|
||||
]),
|
||||
@@ -313,10 +311,10 @@ pub enum ActiveRadarrBlock {
|
||||
MovieDetails,
|
||||
MovieHistory,
|
||||
Movies,
|
||||
RefreshAndScanPrompt,
|
||||
RefreshAllCollectionsPrompt,
|
||||
RefreshAllMoviesPrompt,
|
||||
RefreshDownloadsPrompt,
|
||||
UpdateAndScanPrompt,
|
||||
UpdateAllCollectionsPrompt,
|
||||
UpdateAllMoviesPrompt,
|
||||
UpdateDownloadsPrompt,
|
||||
SearchMovie,
|
||||
SearchCollection,
|
||||
ViewMovieOverview,
|
||||
@@ -349,7 +347,7 @@ pub const MOVIE_DETAILS_BLOCKS: [ActiveRadarrBlock; 10] = [
|
||||
ActiveRadarrBlock::Cast,
|
||||
ActiveRadarrBlock::Crew,
|
||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
|
||||
ActiveRadarrBlock::RefreshAndScanPrompt,
|
||||
ActiveRadarrBlock::UpdateAndScanPrompt,
|
||||
ActiveRadarrBlock::ManualSearch,
|
||||
ActiveRadarrBlock::ManualSearchSortPrompt,
|
||||
ActiveRadarrBlock::ManualSearchConfirmPrompt,
|
||||
@@ -540,13 +538,7 @@ impl App {
|
||||
self.dispatch_by_radarr_block(&active_radarr_block).await;
|
||||
}
|
||||
|
||||
if self.is_routing
|
||||
|| self
|
||||
.network_tick_frequency
|
||||
.checked_sub(self.last_tick.elapsed())
|
||||
.unwrap_or_else(|| Duration::from_secs(0))
|
||||
.is_zero()
|
||||
{
|
||||
if self.is_routing || self.tick_count % self.tick_until_poll == 0 {
|
||||
self.refresh_metadata().await;
|
||||
self.dispatch_by_radarr_block(&active_radarr_block).await;
|
||||
}
|
||||
@@ -559,6 +551,9 @@ impl App {
|
||||
self
|
||||
.dispatch_network_event(RadarrEvent::GetTags.into())
|
||||
.await;
|
||||
self
|
||||
.dispatch_network_event(RadarrEvent::GetDownloads.into())
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn populate_movie_collection_table(&mut self) {
|
||||
@@ -1019,8 +1014,6 @@ mod tests {
|
||||
}
|
||||
|
||||
mod radarr_tests {
|
||||
use std::time::Duration;
|
||||
|
||||
use pretty_assertions::assert_eq;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
@@ -1456,7 +1449,8 @@ mod tests {
|
||||
#[tokio::test]
|
||||
async fn test_radarr_on_tick_network_tick_frequency() {
|
||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||
app.network_tick_frequency = Duration::from_secs(0);
|
||||
app.tick_count = 2;
|
||||
app.tick_until_poll = 2;
|
||||
|
||||
app
|
||||
.radarr_on_tick(ActiveRadarrBlock::Downloads, false)
|
||||
|
||||
@@ -231,9 +231,9 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
|
||||
}
|
||||
ActiveRadarrBlock::DeleteMoviePrompt
|
||||
| ActiveRadarrBlock::DeleteDownloadPrompt
|
||||
| ActiveRadarrBlock::RefreshAllMoviesPrompt
|
||||
| ActiveRadarrBlock::RefreshAllCollectionsPrompt
|
||||
| ActiveRadarrBlock::RefreshDownloadsPrompt => handle_prompt_toggle(self.app, self.key),
|
||||
| ActiveRadarrBlock::UpdateAllMoviesPrompt
|
||||
| ActiveRadarrBlock::UpdateAllCollectionsPrompt
|
||||
| ActiveRadarrBlock::UpdateDownloadsPrompt => handle_prompt_toggle(self.app, self.key),
|
||||
ActiveRadarrBlock::SearchMovie | ActiveRadarrBlock::SearchCollection => {
|
||||
handle_text_box_left_right_keys!(self, self.key, self.app.data.radarr_data.search)
|
||||
}
|
||||
@@ -256,7 +256,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
|
||||
if self.app.data.radarr_data.filtered_movies.items.is_empty() {
|
||||
let selected_index = self
|
||||
.search_table(&self.app.data.radarr_data.movies.items.clone(), |movie| {
|
||||
&movie.title
|
||||
&movie.title.text
|
||||
});
|
||||
self
|
||||
.app
|
||||
@@ -267,7 +267,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
|
||||
} else {
|
||||
let selected_index = self.search_table(
|
||||
&self.app.data.radarr_data.filtered_movies.items.clone(),
|
||||
|movie| &movie.title,
|
||||
|movie| &movie.title.text,
|
||||
);
|
||||
self
|
||||
.app
|
||||
@@ -288,7 +288,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
|
||||
{
|
||||
let selected_index = self.search_table(
|
||||
&self.app.data.radarr_data.collections.items.clone(),
|
||||
|collection| &collection.title,
|
||||
|collection| &collection.title.text,
|
||||
);
|
||||
self
|
||||
.app
|
||||
@@ -299,7 +299,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
|
||||
} else {
|
||||
let selected_index = self.search_table(
|
||||
&self.app.data.radarr_data.filtered_collections.items.clone(),
|
||||
|collection| &collection.title,
|
||||
|collection| &collection.title.text,
|
||||
);
|
||||
self
|
||||
.app
|
||||
@@ -312,7 +312,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
|
||||
ActiveRadarrBlock::FilterMovies => {
|
||||
let filtered_movies = self
|
||||
.filter_table(&self.app.data.radarr_data.movies.items.clone(), |movie| {
|
||||
&movie.title
|
||||
&movie.title.text
|
||||
});
|
||||
|
||||
if !filtered_movies.is_empty() {
|
||||
@@ -327,7 +327,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
|
||||
ActiveRadarrBlock::FilterCollections => {
|
||||
let filtered_collections = self.filter_table(
|
||||
&self.app.data.radarr_data.collections.items.clone(),
|
||||
|collection| &collection.title,
|
||||
|collection| &collection.title.text,
|
||||
);
|
||||
|
||||
if !filtered_collections.is_empty() {
|
||||
@@ -353,23 +353,23 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
ActiveRadarrBlock::RefreshAllMoviesPrompt => {
|
||||
ActiveRadarrBlock::UpdateAllMoviesPrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateAllMovies);
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
ActiveRadarrBlock::RefreshDownloadsPrompt => {
|
||||
ActiveRadarrBlock::UpdateDownloadsPrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::RefreshDownloads);
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateDownloads);
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
ActiveRadarrBlock::RefreshAllCollectionsPrompt => {
|
||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::RefreshCollections);
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateCollections);
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -392,9 +392,9 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
|
||||
}
|
||||
ActiveRadarrBlock::DeleteMoviePrompt
|
||||
| ActiveRadarrBlock::DeleteDownloadPrompt
|
||||
| ActiveRadarrBlock::RefreshAllMoviesPrompt
|
||||
| ActiveRadarrBlock::RefreshAllCollectionsPrompt
|
||||
| ActiveRadarrBlock::RefreshDownloadsPrompt => {
|
||||
| ActiveRadarrBlock::UpdateAllMoviesPrompt
|
||||
| ActiveRadarrBlock::UpdateAllCollectionsPrompt
|
||||
| ActiveRadarrBlock::UpdateDownloadsPrompt => {
|
||||
self.app.pop_navigation_stack();
|
||||
self.app.data.radarr_data.prompt_confirm = false;
|
||||
}
|
||||
@@ -441,18 +441,28 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
|
||||
.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
||||
self.app.should_ignore_quit_key = true;
|
||||
}
|
||||
_ if *key == DEFAULT_KEYBINDINGS.update.key => {
|
||||
self
|
||||
.app
|
||||
.push_navigation_stack(ActiveRadarrBlock::UpdateAllMoviesPrompt.into());
|
||||
}
|
||||
_ if *key == DEFAULT_KEYBINDINGS.refresh.key => {
|
||||
self
|
||||
.app
|
||||
.push_navigation_stack(ActiveRadarrBlock::RefreshAllMoviesPrompt.into());
|
||||
.pop_and_push_navigation_stack((*self.active_radarr_block).into());
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
ActiveRadarrBlock::Downloads => match self.key {
|
||||
_ if *key == DEFAULT_KEYBINDINGS.update.key => {
|
||||
self
|
||||
.app
|
||||
.push_navigation_stack(ActiveRadarrBlock::UpdateDownloadsPrompt.into());
|
||||
}
|
||||
_ if *key == DEFAULT_KEYBINDINGS.refresh.key => {
|
||||
self
|
||||
.app
|
||||
.push_navigation_stack(ActiveRadarrBlock::RefreshDownloadsPrompt.into());
|
||||
.pop_and_push_navigation_stack((*self.active_radarr_block).into());
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
@@ -471,10 +481,15 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for RadarrHandler<'a> {
|
||||
self.app.data.radarr_data.is_filtering = true;
|
||||
self.app.should_ignore_quit_key = true;
|
||||
}
|
||||
_ if *key == DEFAULT_KEYBINDINGS.update.key => {
|
||||
self
|
||||
.app
|
||||
.push_navigation_stack(ActiveRadarrBlock::UpdateAllCollectionsPrompt.into());
|
||||
}
|
||||
_ if *key == DEFAULT_KEYBINDINGS.refresh.key => {
|
||||
self
|
||||
.app
|
||||
.push_navigation_stack(ActiveRadarrBlock::RefreshAllCollectionsPrompt.into());
|
||||
.pop_and_push_navigation_stack((*self.active_radarr_block).into());
|
||||
}
|
||||
_ => (),
|
||||
},
|
||||
@@ -614,6 +629,7 @@ mod tests {
|
||||
use crate::handlers::radarr_handlers::RadarrHandler;
|
||||
use crate::handlers::KeyEventHandler;
|
||||
use crate::models::radarr_models::{Collection, Movie};
|
||||
use crate::models::HorizontallyScrollableText;
|
||||
use crate::{extended_stateful_iterable_vec, test_handler_delegation};
|
||||
|
||||
mod test_handle_scroll_up_and_down {
|
||||
@@ -628,40 +644,44 @@ mod tests {
|
||||
test_collections_scroll,
|
||||
RadarrHandler,
|
||||
collections,
|
||||
Collection,
|
||||
simple_stateful_iterable_vec!(Collection, HorizontallyScrollableText),
|
||||
ActiveRadarrBlock::Collections,
|
||||
None,
|
||||
title
|
||||
title,
|
||||
to_string
|
||||
);
|
||||
|
||||
test_iterable_scroll!(
|
||||
test_filtered_collections_scroll,
|
||||
RadarrHandler,
|
||||
filtered_collections,
|
||||
Collection,
|
||||
simple_stateful_iterable_vec!(Collection, HorizontallyScrollableText),
|
||||
ActiveRadarrBlock::Collections,
|
||||
None,
|
||||
title
|
||||
title,
|
||||
to_string
|
||||
);
|
||||
|
||||
test_iterable_scroll!(
|
||||
test_movies_scroll,
|
||||
RadarrHandler,
|
||||
movies,
|
||||
Movie,
|
||||
simple_stateful_iterable_vec!(Movie, HorizontallyScrollableText),
|
||||
ActiveRadarrBlock::Movies,
|
||||
None,
|
||||
title
|
||||
title,
|
||||
to_string
|
||||
);
|
||||
|
||||
test_iterable_scroll!(
|
||||
test_filtered_movies_scroll,
|
||||
RadarrHandler,
|
||||
filtered_movies,
|
||||
Movie,
|
||||
simple_stateful_iterable_vec!(Movie, HorizontallyScrollableText),
|
||||
ActiveRadarrBlock::Movies,
|
||||
None,
|
||||
title
|
||||
title,
|
||||
to_string
|
||||
);
|
||||
|
||||
test_iterable_scroll!(
|
||||
@@ -689,40 +709,44 @@ mod tests {
|
||||
test_collections_home_end,
|
||||
RadarrHandler,
|
||||
collections,
|
||||
Collection,
|
||||
extended_stateful_iterable_vec!(Collection, HorizontallyScrollableText),
|
||||
ActiveRadarrBlock::Collections,
|
||||
None,
|
||||
title
|
||||
title,
|
||||
to_string
|
||||
);
|
||||
|
||||
test_iterable_home_and_end!(
|
||||
test_filtered_collections_home_end,
|
||||
RadarrHandler,
|
||||
filtered_collections,
|
||||
Collection,
|
||||
extended_stateful_iterable_vec!(Collection, HorizontallyScrollableText),
|
||||
ActiveRadarrBlock::Collections,
|
||||
None,
|
||||
title
|
||||
title,
|
||||
to_string
|
||||
);
|
||||
|
||||
test_iterable_home_and_end!(
|
||||
test_movies_home_end,
|
||||
RadarrHandler,
|
||||
movies,
|
||||
Movie,
|
||||
extended_stateful_iterable_vec!(Movie, HorizontallyScrollableText),
|
||||
ActiveRadarrBlock::Movies,
|
||||
None,
|
||||
title
|
||||
title,
|
||||
to_string
|
||||
);
|
||||
|
||||
test_iterable_home_and_end!(
|
||||
test_filtered_movies_home_end,
|
||||
RadarrHandler,
|
||||
filtered_movies,
|
||||
Movie,
|
||||
extended_stateful_iterable_vec!(Movie, HorizontallyScrollableText),
|
||||
ActiveRadarrBlock::Movies,
|
||||
None,
|
||||
title
|
||||
title,
|
||||
to_string
|
||||
);
|
||||
|
||||
test_iterable_home_and_end!(
|
||||
@@ -851,9 +875,9 @@ mod tests {
|
||||
#[values(
|
||||
ActiveRadarrBlock::DeleteMoviePrompt,
|
||||
ActiveRadarrBlock::DeleteDownloadPrompt,
|
||||
ActiveRadarrBlock::RefreshAllMoviesPrompt,
|
||||
ActiveRadarrBlock::RefreshAllCollectionsPrompt,
|
||||
ActiveRadarrBlock::RefreshDownloadsPrompt
|
||||
ActiveRadarrBlock::UpdateAllMoviesPrompt,
|
||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
|
||||
ActiveRadarrBlock::UpdateDownloadsPrompt
|
||||
)]
|
||||
active_radarr_block: ActiveRadarrBlock,
|
||||
#[values(DEFAULT_KEYBINDINGS.left.key, DEFAULT_KEYBINDINGS.right.key)] key: Key,
|
||||
@@ -917,7 +941,10 @@ mod tests {
|
||||
.data
|
||||
.radarr_data
|
||||
.movies
|
||||
.set_items(extended_stateful_iterable_vec!(Movie));
|
||||
.set_items(extended_stateful_iterable_vec!(
|
||||
Movie,
|
||||
HorizontallyScrollableText
|
||||
));
|
||||
app.data.radarr_data.search = "Test 2".to_owned().into();
|
||||
|
||||
RadarrHandler::with(
|
||||
@@ -929,7 +956,7 @@ mod tests {
|
||||
.handle();
|
||||
|
||||
assert_str_eq!(
|
||||
app.data.radarr_data.movies.current_selection().title,
|
||||
app.data.radarr_data.movies.current_selection().title.text,
|
||||
"Test 2"
|
||||
);
|
||||
}
|
||||
@@ -941,7 +968,10 @@ mod tests {
|
||||
.data
|
||||
.radarr_data
|
||||
.filtered_movies
|
||||
.set_items(extended_stateful_iterable_vec!(Movie));
|
||||
.set_items(extended_stateful_iterable_vec!(
|
||||
Movie,
|
||||
HorizontallyScrollableText
|
||||
));
|
||||
app.data.radarr_data.search = "Test 2".to_owned().into();
|
||||
|
||||
RadarrHandler::with(
|
||||
@@ -958,7 +988,8 @@ mod tests {
|
||||
.radarr_data
|
||||
.filtered_movies
|
||||
.current_selection()
|
||||
.title,
|
||||
.title
|
||||
.text,
|
||||
"Test 2"
|
||||
);
|
||||
}
|
||||
@@ -970,7 +1001,10 @@ mod tests {
|
||||
.data
|
||||
.radarr_data
|
||||
.collections
|
||||
.set_items(extended_stateful_iterable_vec!(Collection));
|
||||
.set_items(extended_stateful_iterable_vec!(
|
||||
Collection,
|
||||
HorizontallyScrollableText
|
||||
));
|
||||
app.data.radarr_data.search = "Test 2".to_owned().into();
|
||||
|
||||
RadarrHandler::with(
|
||||
@@ -982,7 +1016,13 @@ mod tests {
|
||||
.handle();
|
||||
|
||||
assert_str_eq!(
|
||||
app.data.radarr_data.collections.current_selection().title,
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
.collections
|
||||
.current_selection()
|
||||
.title
|
||||
.text,
|
||||
"Test 2"
|
||||
);
|
||||
}
|
||||
@@ -994,7 +1034,10 @@ mod tests {
|
||||
.data
|
||||
.radarr_data
|
||||
.filtered_collections
|
||||
.set_items(extended_stateful_iterable_vec!(Collection));
|
||||
.set_items(extended_stateful_iterable_vec!(
|
||||
Collection,
|
||||
HorizontallyScrollableText
|
||||
));
|
||||
app.data.radarr_data.search = "Test 2".to_owned().into();
|
||||
|
||||
RadarrHandler::with(
|
||||
@@ -1011,7 +1054,8 @@ mod tests {
|
||||
.radarr_data
|
||||
.filtered_collections
|
||||
.current_selection()
|
||||
.title,
|
||||
.title
|
||||
.text,
|
||||
"Test 2"
|
||||
);
|
||||
}
|
||||
@@ -1023,7 +1067,10 @@ mod tests {
|
||||
.data
|
||||
.radarr_data
|
||||
.movies
|
||||
.set_items(extended_stateful_iterable_vec!(Movie));
|
||||
.set_items(extended_stateful_iterable_vec!(
|
||||
Movie,
|
||||
HorizontallyScrollableText
|
||||
));
|
||||
app.data.radarr_data.filter = "Test".to_owned().into();
|
||||
|
||||
RadarrHandler::with(
|
||||
@@ -1041,7 +1088,8 @@ mod tests {
|
||||
.radarr_data
|
||||
.filtered_movies
|
||||
.current_selection()
|
||||
.title,
|
||||
.title
|
||||
.text,
|
||||
"Test 1"
|
||||
);
|
||||
}
|
||||
@@ -1053,7 +1101,10 @@ mod tests {
|
||||
.data
|
||||
.radarr_data
|
||||
.collections
|
||||
.set_items(extended_stateful_iterable_vec!(Collection));
|
||||
.set_items(extended_stateful_iterable_vec!(
|
||||
Collection,
|
||||
HorizontallyScrollableText
|
||||
));
|
||||
app.data.radarr_data.filter = "Test".to_owned().into();
|
||||
|
||||
RadarrHandler::with(
|
||||
@@ -1071,7 +1122,8 @@ mod tests {
|
||||
.radarr_data
|
||||
.filtered_collections
|
||||
.current_selection()
|
||||
.title,
|
||||
.title
|
||||
.text,
|
||||
"Test 1"
|
||||
);
|
||||
}
|
||||
@@ -1089,18 +1141,18 @@ mod tests {
|
||||
)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::Movies,
|
||||
ActiveRadarrBlock::RefreshAllMoviesPrompt,
|
||||
ActiveRadarrBlock::UpdateAllMoviesPrompt,
|
||||
RadarrEvent::UpdateAllMovies
|
||||
)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::Downloads,
|
||||
ActiveRadarrBlock::RefreshDownloadsPrompt,
|
||||
RadarrEvent::RefreshDownloads
|
||||
ActiveRadarrBlock::UpdateDownloadsPrompt,
|
||||
RadarrEvent::UpdateDownloads
|
||||
)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::Collections,
|
||||
ActiveRadarrBlock::RefreshAllCollectionsPrompt,
|
||||
RadarrEvent::RefreshCollections
|
||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt,
|
||||
RadarrEvent::UpdateCollections
|
||||
)]
|
||||
fn test_prompt_confirm_submit(
|
||||
#[case] base_route: ActiveRadarrBlock,
|
||||
@@ -1125,14 +1177,11 @@ mod tests {
|
||||
#[rstest]
|
||||
#[case(ActiveRadarrBlock::Movies, ActiveRadarrBlock::DeleteMoviePrompt)]
|
||||
#[case(ActiveRadarrBlock::Downloads, ActiveRadarrBlock::DeleteDownloadPrompt)]
|
||||
#[case(ActiveRadarrBlock::Movies, ActiveRadarrBlock::RefreshAllMoviesPrompt)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::Downloads,
|
||||
ActiveRadarrBlock::RefreshDownloadsPrompt
|
||||
)]
|
||||
#[case(ActiveRadarrBlock::Movies, ActiveRadarrBlock::UpdateAllMoviesPrompt)]
|
||||
#[case(ActiveRadarrBlock::Downloads, ActiveRadarrBlock::UpdateDownloadsPrompt)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::Collections,
|
||||
ActiveRadarrBlock::RefreshAllCollectionsPrompt
|
||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt
|
||||
)]
|
||||
fn test_prompt_decline_submit(
|
||||
#[case] base_route: ActiveRadarrBlock,
|
||||
@@ -1203,15 +1252,12 @@ mod tests {
|
||||
|
||||
#[rstest]
|
||||
#[case(ActiveRadarrBlock::Movies, ActiveRadarrBlock::DeleteMoviePrompt)]
|
||||
#[case(ActiveRadarrBlock::Movies, ActiveRadarrBlock::RefreshAllMoviesPrompt)]
|
||||
#[case(ActiveRadarrBlock::Movies, ActiveRadarrBlock::UpdateAllMoviesPrompt)]
|
||||
#[case(ActiveRadarrBlock::Downloads, ActiveRadarrBlock::DeleteDownloadPrompt)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::Downloads,
|
||||
ActiveRadarrBlock::RefreshDownloadsPrompt
|
||||
)]
|
||||
#[case(ActiveRadarrBlock::Downloads, ActiveRadarrBlock::UpdateDownloadsPrompt)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::Collections,
|
||||
ActiveRadarrBlock::RefreshAllCollectionsPrompt
|
||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt
|
||||
)]
|
||||
fn test_prompt_blocks_esc(
|
||||
#[case] base_block: ActiveRadarrBlock,
|
||||
@@ -1337,21 +1383,40 @@ mod tests {
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
#[case(ActiveRadarrBlock::Movies, ActiveRadarrBlock::RefreshAllMoviesPrompt)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::Downloads,
|
||||
ActiveRadarrBlock::RefreshDownloadsPrompt
|
||||
)]
|
||||
#[case(ActiveRadarrBlock::Movies, ActiveRadarrBlock::UpdateAllMoviesPrompt)]
|
||||
#[case(ActiveRadarrBlock::Downloads, ActiveRadarrBlock::UpdateDownloadsPrompt)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::Collections,
|
||||
ActiveRadarrBlock::RefreshAllCollectionsPrompt
|
||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt
|
||||
)]
|
||||
fn test_refresh_key(
|
||||
fn test_update_key(
|
||||
#[case] active_radarr_block: ActiveRadarrBlock,
|
||||
#[case] expected_radarr_block: ActiveRadarrBlock,
|
||||
) {
|
||||
let mut app = App::default();
|
||||
|
||||
RadarrHandler::with(
|
||||
&DEFAULT_KEYBINDINGS.update.key,
|
||||
&mut app,
|
||||
&active_radarr_block,
|
||||
&None,
|
||||
)
|
||||
.handle();
|
||||
|
||||
assert_eq!(app.get_current_route(), &expected_radarr_block.into());
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn test_refresh_key(
|
||||
#[values(
|
||||
ActiveRadarrBlock::Movies,
|
||||
ActiveRadarrBlock::Collections,
|
||||
ActiveRadarrBlock::Downloads
|
||||
)]
|
||||
active_radarr_block: ActiveRadarrBlock,
|
||||
) {
|
||||
let mut app = App::default();
|
||||
|
||||
RadarrHandler::with(
|
||||
&DEFAULT_KEYBINDINGS.refresh.key,
|
||||
&mut app,
|
||||
@@ -1360,7 +1425,8 @@ mod tests {
|
||||
)
|
||||
.handle();
|
||||
|
||||
assert_eq!(app.get_current_route(), &expected_radarr_block.into());
|
||||
assert_eq!(app.get_current_route(), &active_radarr_block.into());
|
||||
assert!(app.is_routing);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
@@ -1433,7 +1499,10 @@ mod tests {
|
||||
.data
|
||||
.radarr_data
|
||||
.movies
|
||||
.set_items(extended_stateful_iterable_vec!(Movie));
|
||||
.set_items(extended_stateful_iterable_vec!(
|
||||
Movie,
|
||||
HorizontallyScrollableText
|
||||
));
|
||||
app.data.radarr_data.search = "Test 2".to_owned().into();
|
||||
app.data.radarr_data.is_searching = true;
|
||||
app.should_ignore_quit_key = true;
|
||||
@@ -1447,7 +1516,7 @@ mod tests {
|
||||
&ActiveRadarrBlock::SearchMovie,
|
||||
&None,
|
||||
)
|
||||
.search_table(movies, |movie| &movie.title);
|
||||
.search_table(movies, |movie| &movie.title.text);
|
||||
|
||||
assert_eq!(index, Some(1));
|
||||
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
|
||||
@@ -1463,7 +1532,10 @@ mod tests {
|
||||
.data
|
||||
.radarr_data
|
||||
.movies
|
||||
.set_items(extended_stateful_iterable_vec!(Movie));
|
||||
.set_items(extended_stateful_iterable_vec!(
|
||||
Movie,
|
||||
HorizontallyScrollableText
|
||||
));
|
||||
app.data.radarr_data.search = "Test 5".to_owned().into();
|
||||
app.data.radarr_data.is_searching = true;
|
||||
app.should_ignore_quit_key = true;
|
||||
@@ -1477,7 +1549,7 @@ mod tests {
|
||||
&ActiveRadarrBlock::SearchMovie,
|
||||
&None,
|
||||
)
|
||||
.search_table(movies, |movie| &movie.title);
|
||||
.search_table(movies, |movie| &movie.title.text);
|
||||
|
||||
assert_eq!(index, None);
|
||||
assert_eq!(
|
||||
@@ -1496,7 +1568,10 @@ mod tests {
|
||||
.data
|
||||
.radarr_data
|
||||
.movies
|
||||
.set_items(extended_stateful_iterable_vec!(Movie));
|
||||
.set_items(extended_stateful_iterable_vec!(
|
||||
Movie,
|
||||
HorizontallyScrollableText
|
||||
));
|
||||
app.data.radarr_data.filter = "Test 2".to_owned().into();
|
||||
app.data.radarr_data.is_searching = true;
|
||||
app.should_ignore_quit_key = true;
|
||||
@@ -1510,10 +1585,10 @@ mod tests {
|
||||
&ActiveRadarrBlock::FilterMovies,
|
||||
&None,
|
||||
)
|
||||
.filter_table(movies, |movie| &movie.title);
|
||||
.filter_table(movies, |movie| &movie.title.text);
|
||||
|
||||
assert_eq!(filter_matches.len(), 1);
|
||||
assert_str_eq!(filter_matches[0].title, "Test 2");
|
||||
assert_str_eq!(filter_matches[0].title.text, "Test 2");
|
||||
assert_eq!(app.get_current_route(), &ActiveRadarrBlock::Movies.into());
|
||||
assert!(!app.data.radarr_data.is_filtering);
|
||||
assert!(!app.should_ignore_quit_key);
|
||||
@@ -1527,7 +1602,10 @@ mod tests {
|
||||
.data
|
||||
.radarr_data
|
||||
.movies
|
||||
.set_items(extended_stateful_iterable_vec!(Movie));
|
||||
.set_items(extended_stateful_iterable_vec!(
|
||||
Movie,
|
||||
HorizontallyScrollableText
|
||||
));
|
||||
app.data.radarr_data.filter = "Test 5".to_owned().into();
|
||||
app.data.radarr_data.is_filtering = true;
|
||||
app.should_ignore_quit_key = true;
|
||||
@@ -1541,7 +1619,7 @@ mod tests {
|
||||
&ActiveRadarrBlock::FilterMovies,
|
||||
&None,
|
||||
)
|
||||
.filter_table(movies, |movie| &movie.title);
|
||||
.filter_table(movies, |movie| &movie.title.text);
|
||||
|
||||
assert!(filter_matches.is_empty());
|
||||
assert_eq!(
|
||||
@@ -1590,7 +1668,7 @@ mod tests {
|
||||
ActiveRadarrBlock::Cast,
|
||||
ActiveRadarrBlock::Crew,
|
||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
|
||||
ActiveRadarrBlock::RefreshAndScanPrompt,
|
||||
ActiveRadarrBlock::UpdateAndScanPrompt,
|
||||
ActiveRadarrBlock::ManualSearch,
|
||||
ActiveRadarrBlock::ManualSearchConfirmPrompt
|
||||
)]
|
||||
|
||||
@@ -127,7 +127,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for MovieDetailsHandler<'a> {
|
||||
_ => (),
|
||||
},
|
||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt
|
||||
| ActiveRadarrBlock::RefreshAndScanPrompt
|
||||
| ActiveRadarrBlock::UpdateAndScanPrompt
|
||||
| ActiveRadarrBlock::ManualSearchConfirmPrompt => handle_prompt_toggle(self.app, self.key),
|
||||
_ => (),
|
||||
}
|
||||
@@ -143,9 +143,9 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for MovieDetailsHandler<'a> {
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
}
|
||||
ActiveRadarrBlock::RefreshAndScanPrompt => {
|
||||
ActiveRadarrBlock::UpdateAndScanPrompt => {
|
||||
if self.app.data.radarr_data.prompt_confirm {
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::RefreshAndScan);
|
||||
self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::UpdateAndScan);
|
||||
}
|
||||
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -201,7 +201,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for MovieDetailsHandler<'a> {
|
||||
self.app.data.radarr_data.reset_movie_info_tabs();
|
||||
}
|
||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt
|
||||
| ActiveRadarrBlock::RefreshAndScanPrompt
|
||||
| ActiveRadarrBlock::UpdateAndScanPrompt
|
||||
| ActiveRadarrBlock::ManualSearchConfirmPrompt
|
||||
| ActiveRadarrBlock::ManualSearchSortPrompt => {
|
||||
self.app.pop_navigation_stack();
|
||||
@@ -236,10 +236,15 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for MovieDetailsHandler<'a> {
|
||||
self.app.data.radarr_data.populate_edit_movie_fields();
|
||||
self.app.data.radarr_data.selected_block = ActiveRadarrBlock::EditMovieToggleMonitored;
|
||||
}
|
||||
_ if *key == DEFAULT_KEYBINDINGS.update.key => {
|
||||
self
|
||||
.app
|
||||
.push_navigation_stack(ActiveRadarrBlock::UpdateAndScanPrompt.into());
|
||||
}
|
||||
_ if *key == DEFAULT_KEYBINDINGS.refresh.key => {
|
||||
self
|
||||
.app
|
||||
.push_navigation_stack(ActiveRadarrBlock::RefreshAndScanPrompt.into());
|
||||
.pop_and_push_navigation_stack((*self.active_radarr_block).into());
|
||||
}
|
||||
_ if *key == DEFAULT_KEYBINDINGS.sort.key => {
|
||||
self
|
||||
@@ -534,7 +539,7 @@ mod tests {
|
||||
fn test_left_right_prompt_toggle(
|
||||
#[values(
|
||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
|
||||
ActiveRadarrBlock::RefreshAndScanPrompt,
|
||||
ActiveRadarrBlock::UpdateAndScanPrompt,
|
||||
ActiveRadarrBlock::ManualSearchConfirmPrompt
|
||||
)]
|
||||
active_radarr_block: ActiveRadarrBlock,
|
||||
@@ -628,7 +633,7 @@ mod tests {
|
||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
|
||||
RadarrEvent::TriggerAutomaticSearch
|
||||
)]
|
||||
#[case(ActiveRadarrBlock::RefreshAndScanPrompt, RadarrEvent::RefreshAndScan)]
|
||||
#[case(ActiveRadarrBlock::UpdateAndScanPrompt, RadarrEvent::UpdateAndScan)]
|
||||
#[case(
|
||||
ActiveRadarrBlock::ManualSearchConfirmPrompt,
|
||||
RadarrEvent::DownloadRelease
|
||||
@@ -659,7 +664,7 @@ mod tests {
|
||||
fn test_movie_info_prompt_decline_submit(
|
||||
#[values(
|
||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
|
||||
ActiveRadarrBlock::RefreshAndScanPrompt,
|
||||
ActiveRadarrBlock::UpdateAndScanPrompt,
|
||||
ActiveRadarrBlock::ManualSearchConfirmPrompt
|
||||
)]
|
||||
prompt_block: ActiveRadarrBlock,
|
||||
@@ -748,7 +753,7 @@ mod tests {
|
||||
fn test_movie_info_prompts_esc(
|
||||
#[values(
|
||||
ActiveRadarrBlock::AutomaticallySearchMoviePrompt,
|
||||
ActiveRadarrBlock::RefreshAndScanPrompt,
|
||||
ActiveRadarrBlock::UpdateAndScanPrompt,
|
||||
ActiveRadarrBlock::ManualSearchConfirmPrompt,
|
||||
ActiveRadarrBlock::ManualSearchSortPrompt
|
||||
)]
|
||||
@@ -849,6 +854,34 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn test_update_key(
|
||||
#[values(
|
||||
ActiveRadarrBlock::MovieDetails,
|
||||
ActiveRadarrBlock::MovieHistory,
|
||||
ActiveRadarrBlock::FileInfo,
|
||||
ActiveRadarrBlock::Cast,
|
||||
ActiveRadarrBlock::Crew,
|
||||
ActiveRadarrBlock::ManualSearch
|
||||
)]
|
||||
active_radarr_block: ActiveRadarrBlock,
|
||||
) {
|
||||
let mut app = App::default();
|
||||
|
||||
MovieDetailsHandler::with(
|
||||
&DEFAULT_KEYBINDINGS.update.key,
|
||||
&mut app,
|
||||
&active_radarr_block,
|
||||
&None,
|
||||
)
|
||||
.handle();
|
||||
|
||||
assert_eq!(
|
||||
app.get_current_route(),
|
||||
&ActiveRadarrBlock::UpdateAndScanPrompt.into()
|
||||
);
|
||||
}
|
||||
|
||||
#[rstest]
|
||||
fn test_refresh_key(
|
||||
#[values(
|
||||
@@ -871,10 +904,8 @@ mod tests {
|
||||
)
|
||||
.handle();
|
||||
|
||||
assert_eq!(
|
||||
app.get_current_route(),
|
||||
&ActiveRadarrBlock::RefreshAndScanPrompt.into()
|
||||
);
|
||||
assert_eq!(app.get_current_route(), &active_radarr_block.into());
|
||||
assert!(app.is_routing);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-7
@@ -219,9 +219,8 @@ impl HorizontallyScrollableText {
|
||||
}
|
||||
|
||||
pub fn scroll_left_or_reset(&self, width: usize, is_current_selection: bool, can_scroll: bool) {
|
||||
if can_scroll {
|
||||
if is_current_selection && self.text.len() >= width && *self.offset.borrow() < self.text.len()
|
||||
{
|
||||
if can_scroll && is_current_selection && self.text.len() >= width {
|
||||
if *self.offset.borrow() < self.text.len() {
|
||||
self.scroll_left();
|
||||
} else {
|
||||
self.reset_offset();
|
||||
@@ -563,19 +562,19 @@ mod tests {
|
||||
|
||||
horizontally_scrollable_text.scroll_left_or_reset(width, false, true);
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
|
||||
|
||||
horizontally_scrollable_text.scroll_left_or_reset(width, true, false);
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
|
||||
|
||||
horizontally_scrollable_text.scroll_left_or_reset(width, true, true);
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1);
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 2);
|
||||
|
||||
horizontally_scrollable_text.scroll_left_or_reset(test_text.len(), false, true);
|
||||
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -36,7 +36,7 @@ pub struct RootFolder {
|
||||
pub struct Movie {
|
||||
#[derivative(Default(value = "Number::from(0)"))]
|
||||
pub id: Number,
|
||||
pub title: String,
|
||||
pub title: HorizontallyScrollableText,
|
||||
pub original_language: Language,
|
||||
#[derivative(Default(value = "Number::from(0)"))]
|
||||
pub size_on_disk: Number,
|
||||
@@ -84,7 +84,7 @@ pub struct CollectionMovie {
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct Collection {
|
||||
#[serde(default)]
|
||||
pub title: String,
|
||||
pub title: HorizontallyScrollableText,
|
||||
pub root_folder_path: Option<String>,
|
||||
pub search_on_add: bool,
|
||||
pub overview: Option<String>,
|
||||
|
||||
@@ -37,12 +37,12 @@ pub enum RadarrEvent {
|
||||
GetStatus,
|
||||
GetTags,
|
||||
HealthCheck,
|
||||
RefreshAndScan,
|
||||
RefreshCollections,
|
||||
RefreshDownloads,
|
||||
SearchNewMovie,
|
||||
TriggerAutomaticSearch,
|
||||
UpdateAllMovies,
|
||||
UpdateAndScan,
|
||||
UpdateCollections,
|
||||
UpdateDownloads,
|
||||
}
|
||||
|
||||
impl RadarrEvent {
|
||||
@@ -65,10 +65,10 @@ impl RadarrEvent {
|
||||
RadarrEvent::GetStatus => "/system/status",
|
||||
RadarrEvent::GetTags => "/tag",
|
||||
RadarrEvent::TriggerAutomaticSearch
|
||||
| RadarrEvent::RefreshAndScan
|
||||
| RadarrEvent::UpdateAndScan
|
||||
| RadarrEvent::UpdateAllMovies
|
||||
| RadarrEvent::RefreshDownloads
|
||||
| RadarrEvent::RefreshCollections => "/command",
|
||||
| RadarrEvent::UpdateDownloads
|
||||
| RadarrEvent::UpdateCollections => "/command",
|
||||
RadarrEvent::HealthCheck => "/health",
|
||||
}
|
||||
}
|
||||
@@ -101,12 +101,12 @@ impl<'a> Network<'a> {
|
||||
RadarrEvent::GetStatus => self.get_status().await,
|
||||
RadarrEvent::GetTags => self.get_tags().await,
|
||||
RadarrEvent::HealthCheck => self.get_healthcheck().await,
|
||||
RadarrEvent::RefreshAndScan => self.refresh_and_scan().await,
|
||||
RadarrEvent::RefreshCollections => self.refresh_collections().await,
|
||||
RadarrEvent::RefreshDownloads => self.refresh_downloads().await,
|
||||
RadarrEvent::SearchNewMovie => self.search_movie().await,
|
||||
RadarrEvent::TriggerAutomaticSearch => self.trigger_automatic_search().await,
|
||||
RadarrEvent::UpdateAllMovies => self.update_all_movies().await,
|
||||
RadarrEvent::UpdateAndScan => self.update_and_scan().await,
|
||||
RadarrEvent::UpdateCollections => self.update_collections().await,
|
||||
RadarrEvent::UpdateDownloads => self.update_downloads().await,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -258,9 +258,9 @@ impl<'a> Network<'a> {
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn refresh_and_scan(&self) {
|
||||
async fn update_and_scan(&self) {
|
||||
let movie_id = self.extract_movie_id().await;
|
||||
info!("Refreshing and scanning movie with id: {}", movie_id);
|
||||
info!("Updating and scanning movie with id: {}", movie_id);
|
||||
let body = MovieCommandBody {
|
||||
name: "RefreshMovie".to_owned(),
|
||||
movie_ids: vec![movie_id],
|
||||
@@ -268,7 +268,7 @@ impl<'a> Network<'a> {
|
||||
|
||||
let request_props = self
|
||||
.radarr_request_props_from(
|
||||
RadarrEvent::RefreshAndScan.resource(),
|
||||
RadarrEvent::UpdateAndScan.resource(),
|
||||
RequestMethod::Post,
|
||||
Some(body),
|
||||
)
|
||||
@@ -299,15 +299,15 @@ impl<'a> Network<'a> {
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn refresh_downloads(&self) {
|
||||
info!("Refreshing downloads");
|
||||
async fn update_downloads(&self) {
|
||||
info!("Updating downloads");
|
||||
let body = CommandBody {
|
||||
name: "RefreshMonitoredDownloads".to_owned(),
|
||||
};
|
||||
|
||||
let request_props = self
|
||||
.radarr_request_props_from(
|
||||
RadarrEvent::RefreshDownloads.resource(),
|
||||
RadarrEvent::UpdateDownloads.resource(),
|
||||
RequestMethod::Post,
|
||||
Some(body),
|
||||
)
|
||||
@@ -318,15 +318,15 @@ impl<'a> Network<'a> {
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn refresh_collections(&self) {
|
||||
info!("Refreshing collections");
|
||||
async fn update_collections(&self) {
|
||||
info!("Updating collections");
|
||||
let body = CommandBody {
|
||||
name: "RefreshCollections".to_owned(),
|
||||
};
|
||||
|
||||
let request_props = self
|
||||
.radarr_request_props_from(
|
||||
RadarrEvent::RefreshCollections.resource(),
|
||||
RadarrEvent::UpdateCollections.resource(),
|
||||
RequestMethod::Post,
|
||||
Some(body),
|
||||
)
|
||||
@@ -1176,10 +1176,10 @@ mod test {
|
||||
fn test_resource_command(
|
||||
#[values(
|
||||
RadarrEvent::TriggerAutomaticSearch,
|
||||
RadarrEvent::RefreshAndScan,
|
||||
RadarrEvent::UpdateAndScan,
|
||||
RadarrEvent::UpdateAllMovies,
|
||||
RadarrEvent::RefreshDownloads,
|
||||
RadarrEvent::RefreshCollections
|
||||
RadarrEvent::UpdateDownloads,
|
||||
RadarrEvent::UpdateCollections
|
||||
)]
|
||||
event: RadarrEvent,
|
||||
) {
|
||||
@@ -1484,7 +1484,7 @@ mod test {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_refresh_and_scan_event() {
|
||||
async fn test_handle_update_and_scan_event() {
|
||||
let (async_server, app_arc, _server) = mock_radarr_api(
|
||||
RequestMethod::Post,
|
||||
Some(json!({
|
||||
@@ -1492,7 +1492,7 @@ mod test {
|
||||
"movieIds": [ 1 ]
|
||||
})),
|
||||
None,
|
||||
RadarrEvent::RefreshAndScan.resource(),
|
||||
RadarrEvent::UpdateAndScan.resource(),
|
||||
)
|
||||
.await;
|
||||
app_arc
|
||||
@@ -1505,7 +1505,7 @@ mod test {
|
||||
let network = Network::new(reqwest::Client::new(), &app_arc);
|
||||
|
||||
network
|
||||
.handle_radarr_event(RadarrEvent::RefreshAndScan)
|
||||
.handle_radarr_event(RadarrEvent::UpdateAndScan)
|
||||
.await;
|
||||
|
||||
async_server.assert_async().await;
|
||||
@@ -1533,40 +1533,40 @@ mod test {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_refresh_downloads_event() {
|
||||
async fn test_handle_update_downloads_event() {
|
||||
let (async_server, app_arc, _server) = mock_radarr_api(
|
||||
RequestMethod::Post,
|
||||
Some(json!({
|
||||
"name": "RefreshMonitoredDownloads"
|
||||
})),
|
||||
None,
|
||||
RadarrEvent::RefreshDownloads.resource(),
|
||||
RadarrEvent::UpdateDownloads.resource(),
|
||||
)
|
||||
.await;
|
||||
let network = Network::new(reqwest::Client::new(), &app_arc);
|
||||
|
||||
network
|
||||
.handle_radarr_event(RadarrEvent::RefreshDownloads)
|
||||
.handle_radarr_event(RadarrEvent::UpdateDownloads)
|
||||
.await;
|
||||
|
||||
async_server.assert_async().await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_refresh_collections_event() {
|
||||
async fn test_handle_update_collections_event() {
|
||||
let (async_server, app_arc, _server) = mock_radarr_api(
|
||||
RequestMethod::Post,
|
||||
Some(json!({
|
||||
"name": "RefreshCollections"
|
||||
})),
|
||||
None,
|
||||
RadarrEvent::RefreshCollections.resource(),
|
||||
RadarrEvent::UpdateCollections.resource(),
|
||||
)
|
||||
.await;
|
||||
let network = Network::new(reqwest::Client::new(), &app_arc);
|
||||
|
||||
network
|
||||
.handle_radarr_event(RadarrEvent::RefreshCollections)
|
||||
.handle_radarr_event(RadarrEvent::UpdateCollections)
|
||||
.await;
|
||||
|
||||
async_server.assert_async().await;
|
||||
@@ -2562,7 +2562,7 @@ mod test {
|
||||
|
||||
fn collection() -> Collection {
|
||||
Collection {
|
||||
title: "Test Collection".to_owned(),
|
||||
title: "Test Collection".to_owned().into(),
|
||||
root_folder_path: None,
|
||||
search_on_add: true,
|
||||
overview: Some("Collection blah blah blah".to_owned()),
|
||||
@@ -2574,7 +2574,7 @@ mod test {
|
||||
fn movie() -> Movie {
|
||||
Movie {
|
||||
id: Number::from(1),
|
||||
title: "Test".to_owned(),
|
||||
title: "Test".to_owned().into(),
|
||||
original_language: language(),
|
||||
size_on_disk: Number::from(3543348019u64),
|
||||
status: "Downloaded".to_owned(),
|
||||
|
||||
+5
-3
@@ -92,9 +92,11 @@ fn draw_error<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
|
||||
.style(style_failure())
|
||||
.borders(Borders::ALL);
|
||||
|
||||
if app.error.text.len() > area.width as usize {
|
||||
app.error.scroll_left();
|
||||
}
|
||||
app.error.scroll_left_or_reset(
|
||||
area.width as usize,
|
||||
true,
|
||||
app.tick_count % app.ticks_until_scroll == 0,
|
||||
);
|
||||
|
||||
let mut text = Text::from(app.error.to_string());
|
||||
text.patch_style(style_failure());
|
||||
|
||||
@@ -108,7 +108,7 @@ pub(super) fn draw_collection_details<B: Backend>(
|
||||
.block(borderless_block())
|
||||
.alignment(Alignment::Center);
|
||||
|
||||
f.render_widget(title_block(&collection_selection.title), content_area);
|
||||
f.render_widget(title_block(&collection_selection.title.text), content_area);
|
||||
|
||||
f.render_widget(description_paragraph, chunks[0]);
|
||||
f.render_widget(help_paragraph, chunks[2]);
|
||||
|
||||
+52
-18
@@ -15,7 +15,7 @@ use crate::app::radarr::{
|
||||
};
|
||||
use crate::app::App;
|
||||
use crate::logos::RADARR_LOGO;
|
||||
use crate::models::radarr_models::{DiskSpace, DownloadRecord, Movie};
|
||||
use crate::models::radarr_models::{Collection, DiskSpace, DownloadRecord, Movie};
|
||||
use crate::models::Route;
|
||||
use crate::ui::radarr_ui::add_movie_ui::draw_add_movie_search_popup;
|
||||
use crate::ui::radarr_ui::collection_details_ui::draw_collection_details_popup;
|
||||
@@ -123,26 +123,26 @@ pub(super) fn draw_radarr_ui<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, ar
|
||||
draw_downloads,
|
||||
draw_delete_download_prompt,
|
||||
),
|
||||
ActiveRadarrBlock::RefreshDownloadsPrompt => draw_prompt_popup_over(
|
||||
ActiveRadarrBlock::UpdateDownloadsPrompt => draw_prompt_popup_over(
|
||||
f,
|
||||
app,
|
||||
content_rect,
|
||||
draw_downloads,
|
||||
draw_refresh_downloads_prompt,
|
||||
draw_update_downloads_prompt,
|
||||
),
|
||||
ActiveRadarrBlock::RefreshAllMoviesPrompt => draw_prompt_popup_over(
|
||||
ActiveRadarrBlock::UpdateAllMoviesPrompt => draw_prompt_popup_over(
|
||||
f,
|
||||
app,
|
||||
content_rect,
|
||||
draw_library,
|
||||
draw_refresh_all_movies_prompt,
|
||||
draw_update_all_movies_prompt,
|
||||
),
|
||||
ActiveRadarrBlock::RefreshAllCollectionsPrompt => draw_prompt_popup_over(
|
||||
ActiveRadarrBlock::UpdateAllCollectionsPrompt => draw_prompt_popup_over(
|
||||
f,
|
||||
app,
|
||||
content_rect,
|
||||
draw_collections,
|
||||
draw_refresh_all_collections_prompt,
|
||||
draw_update_all_collections_prompt,
|
||||
),
|
||||
_ => (),
|
||||
}
|
||||
@@ -157,6 +157,18 @@ pub(super) fn draw_radarr_context_row<B: Backend>(f: &mut Frame<'_, B>, app: &Ap
|
||||
}
|
||||
|
||||
fn draw_library<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
|
||||
let current_selection = if !app.data.radarr_data.filtered_movies.items.is_empty() {
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
.filtered_movies
|
||||
.current_selection()
|
||||
.clone()
|
||||
} else if !app.data.radarr_data.movies.items.is_empty() {
|
||||
app.data.radarr_data.movies.current_selection().clone()
|
||||
} else {
|
||||
Movie::default()
|
||||
};
|
||||
let quality_profile_map = &app.data.radarr_data.quality_profile_map;
|
||||
let tags_map = &app.data.radarr_data.tags_map;
|
||||
let downloads_vec = &app.data.radarr_data.downloads.items;
|
||||
@@ -205,6 +217,11 @@ fn draw_library<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
|
||||
.get_active_tab_contextual_help(),
|
||||
},
|
||||
|movie| {
|
||||
movie.title.scroll_left_or_reset(
|
||||
get_width_from_percentage(area, 27),
|
||||
*movie == current_selection,
|
||||
app.tick_count % app.ticks_until_scroll == 0,
|
||||
);
|
||||
let monitored = if movie.monitored { "🏷" } else { "" };
|
||||
let (hours, minutes) = convert_runtime(movie.runtime.as_u64().unwrap());
|
||||
let file_size: f64 = convert_to_gb(movie.size_on_disk.as_u64().unwrap());
|
||||
@@ -226,7 +243,7 @@ fn draw_library<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
|
||||
.join(", ");
|
||||
|
||||
Row::new(vec![
|
||||
Cell::from(movie.title.to_owned()),
|
||||
Cell::from(movie.title.to_string()),
|
||||
Cell::from(movie.year.to_string()),
|
||||
Cell::from(movie.studio.to_string()),
|
||||
Cell::from(format!("{}h {}m", hours, minutes)),
|
||||
@@ -243,7 +260,7 @@ fn draw_library<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
|
||||
);
|
||||
}
|
||||
|
||||
fn draw_refresh_all_movies_prompt<B: Backend>(
|
||||
fn draw_update_all_movies_prompt<B: Backend>(
|
||||
f: &mut Frame<'_, B>,
|
||||
app: &mut App,
|
||||
prompt_area: Rect,
|
||||
@@ -251,13 +268,13 @@ fn draw_refresh_all_movies_prompt<B: Backend>(
|
||||
draw_prompt_box(
|
||||
f,
|
||||
prompt_area,
|
||||
"Refresh All Movies",
|
||||
"Do you want to refresh info and scan your disks for all of your movies?",
|
||||
"Update All Movies",
|
||||
"Do you want to update info and scan your disks for all of your movies?",
|
||||
&app.data.radarr_data.prompt_confirm,
|
||||
);
|
||||
}
|
||||
|
||||
fn draw_refresh_downloads_prompt<B: Backend>(
|
||||
fn draw_update_downloads_prompt<B: Backend>(
|
||||
f: &mut Frame<'_, B>,
|
||||
app: &mut App,
|
||||
prompt_area: Rect,
|
||||
@@ -265,13 +282,13 @@ fn draw_refresh_downloads_prompt<B: Backend>(
|
||||
draw_prompt_box(
|
||||
f,
|
||||
prompt_area,
|
||||
"Refresh Downloads",
|
||||
"Do you want to refresh your downloads?",
|
||||
"Update Downloads",
|
||||
"Do you want to update your downloads?",
|
||||
&app.data.radarr_data.prompt_confirm,
|
||||
);
|
||||
}
|
||||
|
||||
fn draw_refresh_all_collections_prompt<B: Backend>(
|
||||
fn draw_update_all_collections_prompt<B: Backend>(
|
||||
f: &mut Frame<'_, B>,
|
||||
app: &mut App,
|
||||
prompt_area: Rect,
|
||||
@@ -279,8 +296,8 @@ fn draw_refresh_all_collections_prompt<B: Backend>(
|
||||
draw_prompt_box(
|
||||
f,
|
||||
prompt_area,
|
||||
"Refresh All Collections",
|
||||
"Do you want to refresh all of your collections?",
|
||||
"Update All Collections",
|
||||
"Do you want to update all of your collections?",
|
||||
&app.data.radarr_data.prompt_confirm,
|
||||
);
|
||||
}
|
||||
@@ -496,6 +513,18 @@ fn draw_downloads<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
|
||||
}
|
||||
|
||||
fn draw_collections<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
|
||||
let current_selection = if !app.data.radarr_data.filtered_collections.items.is_empty() {
|
||||
app
|
||||
.data
|
||||
.radarr_data
|
||||
.filtered_collections
|
||||
.current_selection()
|
||||
.clone()
|
||||
} else if !app.data.radarr_data.collections.items.is_empty() {
|
||||
app.data.radarr_data.collections.current_selection().clone()
|
||||
} else {
|
||||
Collection::default()
|
||||
};
|
||||
let quality_profile_map = &app.data.radarr_data.quality_profile_map;
|
||||
let content = if !app.data.radarr_data.filtered_collections.items.is_empty()
|
||||
&& !app.data.radarr_data.is_filtering
|
||||
@@ -526,9 +555,14 @@ fn draw_collections<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect)
|
||||
},
|
||||
|collection| {
|
||||
let number_of_movies = collection.movies.clone().unwrap_or_default().len();
|
||||
collection.title.scroll_left_or_reset(
|
||||
get_width_from_percentage(area, 100 / 5),
|
||||
*collection == current_selection,
|
||||
app.tick_count % app.ticks_until_scroll == 0,
|
||||
);
|
||||
|
||||
Row::new(vec![
|
||||
Cell::from(collection.title.to_owned()),
|
||||
Cell::from(collection.title.to_string()),
|
||||
Cell::from(collection.search_on_add.to_string()),
|
||||
Cell::from(number_of_movies.to_string()),
|
||||
Cell::from(collection.root_folder_path.clone().unwrap_or_default()),
|
||||
|
||||
@@ -39,12 +39,12 @@ pub(super) fn draw_movie_info_popup<B: Backend>(f: &mut Frame<'_, B>, app: &mut
|
||||
draw_movie_info,
|
||||
draw_search_movie_prompt,
|
||||
),
|
||||
ActiveRadarrBlock::RefreshAndScanPrompt => draw_prompt_popup_over(
|
||||
ActiveRadarrBlock::UpdateAndScanPrompt => draw_prompt_popup_over(
|
||||
f,
|
||||
app,
|
||||
content_area,
|
||||
draw_movie_info,
|
||||
draw_refresh_and_scan_prompt,
|
||||
draw_update_and_scan_prompt,
|
||||
),
|
||||
ActiveRadarrBlock::ManualSearchSortPrompt => draw_drop_down_popup(
|
||||
f,
|
||||
@@ -102,17 +102,13 @@ fn draw_search_movie_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, pro
|
||||
);
|
||||
}
|
||||
|
||||
fn draw_refresh_and_scan_prompt<B: Backend>(
|
||||
f: &mut Frame<'_, B>,
|
||||
app: &mut App,
|
||||
prompt_area: Rect,
|
||||
) {
|
||||
fn draw_update_and_scan_prompt<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, prompt_area: Rect) {
|
||||
draw_prompt_box(
|
||||
f,
|
||||
prompt_area,
|
||||
"Refresh and Scan",
|
||||
"Update and Scan",
|
||||
format!(
|
||||
"Do you want to trigger a refresh and disk scan for the movie: {}?",
|
||||
"Do you want to trigger an update and disk scan for the movie: {}?",
|
||||
app.data.radarr_data.movies.current_selection().title
|
||||
)
|
||||
.as_str(),
|
||||
|
||||
Reference in New Issue
Block a user