Full support for editing movies and managing tags
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "managarr"
|
name = "managarr"
|
||||||
version = "0.0.12"
|
version = "0.0.13"
|
||||||
authors = ["Alex Clarke <alex.j.tusa@gmail.com>"]
|
authors = ["Alex Clarke <alex.j.tusa@gmail.com>"]
|
||||||
description = "A TUI for managing *arr servers"
|
description = "A TUI for managing *arr servers"
|
||||||
keywords = ["managarr", "tui-rs", "dashboard", "servarr"]
|
keywords = ["managarr", "tui-rs", "dashboard", "servarr"]
|
||||||
|
|||||||
@@ -84,10 +84,10 @@ tautulli:
|
|||||||
- [x] Trigger automatic searches for movies
|
- [x] Trigger automatic searches for movies
|
||||||
- [x] Trigger refresh and disk scan for movies, downloads, and collections
|
- [x] Trigger refresh and disk scan for movies, downloads, and collections
|
||||||
- [x] Manually search for movies
|
- [x] Manually search for movies
|
||||||
- [ ] Edit movies
|
- [x] Edit movies
|
||||||
- [ ] Manage your quality profiles
|
- [ ] Manage your quality profiles
|
||||||
- [ ] Manage your quality definitions
|
- [ ] Manage your quality definitions
|
||||||
- [ ] Manage your tags
|
- [x] Manage your tags
|
||||||
- [ ] Manage your indexers
|
- [ ] Manage your indexers
|
||||||
|
|
||||||
### Sonarr
|
### Sonarr
|
||||||
|
|||||||
+43
-1
@@ -25,6 +25,7 @@ pub struct App {
|
|||||||
pub client: Client,
|
pub client: Client,
|
||||||
pub title: &'static str,
|
pub title: &'static str,
|
||||||
pub tick_until_poll: u64,
|
pub tick_until_poll: u64,
|
||||||
|
pub ticks_until_scroll: u64,
|
||||||
pub tick_count: u64,
|
pub tick_count: u64,
|
||||||
pub last_tick: Instant,
|
pub last_tick: Instant,
|
||||||
pub network_tick_frequency: Duration,
|
pub network_tick_frequency: Duration,
|
||||||
@@ -48,6 +49,7 @@ impl App {
|
|||||||
pub async fn dispatch_network_event(&mut self, action: NetworkEvent) {
|
pub async fn dispatch_network_event(&mut self, action: NetworkEvent) {
|
||||||
debug!("Dispatching network event: {:?}", action);
|
debug!("Dispatching network event: {:?}", action);
|
||||||
|
|
||||||
|
self.is_loading = true;
|
||||||
if let Some(network_tx) = &self.network_tx {
|
if let Some(network_tx) = &self.network_tx {
|
||||||
if let Err(e) = network_tx.send(action).await {
|
if let Err(e) = network_tx.send(action).await {
|
||||||
self.is_loading = false;
|
self.is_loading = false;
|
||||||
@@ -136,6 +138,7 @@ impl Default for App {
|
|||||||
client: Client::new(),
|
client: Client::new(),
|
||||||
title: "Managarr",
|
title: "Managarr",
|
||||||
tick_until_poll: 50,
|
tick_until_poll: 50,
|
||||||
|
ticks_until_scroll: 4,
|
||||||
tick_count: 0,
|
tick_count: 0,
|
||||||
network_tick_frequency: Duration::from_secs(20),
|
network_tick_frequency: Duration::from_secs(20),
|
||||||
last_tick: Instant::now(),
|
last_tick: Instant::now(),
|
||||||
@@ -178,16 +181,55 @@ impl Default for RadarrConfig {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
|
|
||||||
use crate::app::radarr::{ActiveRadarrBlock, RadarrData};
|
use crate::app::radarr::{ActiveRadarrBlock, RadarrData};
|
||||||
use crate::app::{App, Data, RadarrConfig, DEFAULT_ROUTE};
|
use crate::app::{App, Data, RadarrConfig, DEFAULT_ROUTE};
|
||||||
use crate::models::HorizontallyScrollableText;
|
use crate::models::{HorizontallyScrollableText, Route, TabRoute};
|
||||||
use crate::network::radarr_network::RadarrEvent;
|
use crate::network::radarr_network::RadarrEvent;
|
||||||
use crate::network::NetworkEvent;
|
use crate::network::NetworkEvent;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_app_default() {
|
||||||
|
let app = App::default();
|
||||||
|
|
||||||
|
assert_eq!(app.navigation_stack, vec![DEFAULT_ROUTE]);
|
||||||
|
assert!(app.network_tx.is_none());
|
||||||
|
assert_eq!(app.error, HorizontallyScrollableText::default());
|
||||||
|
assert_eq!(app.response, String::default());
|
||||||
|
assert_eq!(app.server_tabs.index, 0);
|
||||||
|
assert_eq!(
|
||||||
|
app.server_tabs.tabs,
|
||||||
|
vec![
|
||||||
|
TabRoute {
|
||||||
|
title: "Radarr".to_owned(),
|
||||||
|
route: ActiveRadarrBlock::Movies.into(),
|
||||||
|
help: "<↑↓> scroll | ←→ change tab | <tab> change servarr | <q> quit ".to_owned(),
|
||||||
|
contextual_help: None,
|
||||||
|
},
|
||||||
|
TabRoute {
|
||||||
|
title: "Sonarr".to_owned(),
|
||||||
|
route: Route::Sonarr,
|
||||||
|
help: "<tab> change servarr | <q> quit ".to_owned(),
|
||||||
|
contextual_help: None,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
);
|
||||||
|
assert_str_eq!(app.title, "Managarr");
|
||||||
|
assert_eq!(app.tick_until_poll, 50);
|
||||||
|
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);
|
||||||
|
assert!(!app.should_ignore_quit_key);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_navigation_stack_methods() {
|
fn test_navigation_stack_methods() {
|
||||||
let mut app = App::default();
|
let mut app = App::default();
|
||||||
|
|||||||
+55
-32
@@ -1,4 +1,3 @@
|
|||||||
use std::collections::HashMap;
|
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use bimap::BiMap;
|
use bimap::BiMap;
|
||||||
@@ -28,7 +27,7 @@ pub struct RadarrData {
|
|||||||
pub movie_quality_profile_list: StatefulList<String>,
|
pub movie_quality_profile_list: StatefulList<String>,
|
||||||
pub selected_block: ActiveRadarrBlock,
|
pub selected_block: ActiveRadarrBlock,
|
||||||
pub downloads: StatefulTable<DownloadRecord>,
|
pub downloads: StatefulTable<DownloadRecord>,
|
||||||
pub quality_profile_map: HashMap<u64, String>,
|
pub quality_profile_map: BiMap<u64, String>,
|
||||||
pub tags_map: BiMap<u64, String>,
|
pub tags_map: BiMap<u64, String>,
|
||||||
pub movie_details: ScrollableText,
|
pub movie_details: ScrollableText,
|
||||||
pub file_details: String,
|
pub file_details: String,
|
||||||
@@ -112,7 +111,7 @@ impl RadarrData {
|
|||||||
.movie_minimum_availability_list
|
.movie_minimum_availability_list
|
||||||
.set_items(Vec::from_iter(MinimumAvailability::iter()));
|
.set_items(Vec::from_iter(MinimumAvailability::iter()));
|
||||||
let mut quality_profile_names: Vec<String> =
|
let mut quality_profile_names: Vec<String> =
|
||||||
self.quality_profile_map.values().cloned().collect();
|
self.quality_profile_map.right_values().cloned().collect();
|
||||||
quality_profile_names.sort();
|
quality_profile_names.sort();
|
||||||
self
|
self
|
||||||
.movie_quality_profile_list
|
.movie_quality_profile_list
|
||||||
@@ -161,7 +160,7 @@ impl RadarrData {
|
|||||||
|
|
||||||
let quality_profile_name = self
|
let quality_profile_name = self
|
||||||
.quality_profile_map
|
.quality_profile_map
|
||||||
.get(&quality_profile_id.as_u64().unwrap())
|
.get_by_left(&quality_profile_id.as_u64().unwrap())
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let quality_profile_index = self
|
let quality_profile_index = self
|
||||||
.movie_quality_profile_list
|
.movie_quality_profile_list
|
||||||
@@ -190,7 +189,7 @@ impl Default for RadarrData {
|
|||||||
selected_block: ActiveRadarrBlock::AddMovieSelectMonitor,
|
selected_block: ActiveRadarrBlock::AddMovieSelectMonitor,
|
||||||
filtered_movies: StatefulTable::default(),
|
filtered_movies: StatefulTable::default(),
|
||||||
downloads: StatefulTable::default(),
|
downloads: StatefulTable::default(),
|
||||||
quality_profile_map: HashMap::default(),
|
quality_profile_map: BiMap::default(),
|
||||||
tags_map: BiMap::default(),
|
tags_map: BiMap::default(),
|
||||||
file_details: String::default(),
|
file_details: String::default(),
|
||||||
audio_details: String::default(),
|
audio_details: String::default(),
|
||||||
@@ -289,6 +288,7 @@ pub enum ActiveRadarrBlock {
|
|||||||
AddMovieSelectMonitor,
|
AddMovieSelectMonitor,
|
||||||
AddMovieConfirmPrompt,
|
AddMovieConfirmPrompt,
|
||||||
AddMovieTagsInput,
|
AddMovieTagsInput,
|
||||||
|
AddMovieEmptySearchResults,
|
||||||
AutomaticallySearchMoviePrompt,
|
AutomaticallySearchMoviePrompt,
|
||||||
Collections,
|
Collections,
|
||||||
CollectionDetails,
|
CollectionDetails,
|
||||||
@@ -322,9 +322,10 @@ pub enum ActiveRadarrBlock {
|
|||||||
ViewMovieOverview,
|
ViewMovieOverview,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const ADD_MOVIE_BLOCKS: [ActiveRadarrBlock; 8] = [
|
pub const ADD_MOVIE_BLOCKS: [ActiveRadarrBlock; 9] = [
|
||||||
ActiveRadarrBlock::AddMovieSearchInput,
|
ActiveRadarrBlock::AddMovieSearchInput,
|
||||||
ActiveRadarrBlock::AddMovieSearchResults,
|
ActiveRadarrBlock::AddMovieSearchResults,
|
||||||
|
ActiveRadarrBlock::AddMovieEmptySearchResults,
|
||||||
ActiveRadarrBlock::AddMoviePrompt,
|
ActiveRadarrBlock::AddMoviePrompt,
|
||||||
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
|
ActiveRadarrBlock::AddMovieSelectMinimumAvailability,
|
||||||
ActiveRadarrBlock::AddMovieSelectMonitor,
|
ActiveRadarrBlock::AddMovieSelectMonitor,
|
||||||
@@ -444,24 +445,19 @@ impl App {
|
|||||||
pub(super) async fn dispatch_by_radarr_block(&mut self, active_radarr_block: &ActiveRadarrBlock) {
|
pub(super) async fn dispatch_by_radarr_block(&mut self, active_radarr_block: &ActiveRadarrBlock) {
|
||||||
match active_radarr_block {
|
match active_radarr_block {
|
||||||
ActiveRadarrBlock::Collections => {
|
ActiveRadarrBlock::Collections => {
|
||||||
self.is_loading = true;
|
|
||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::GetCollections.into())
|
.dispatch_network_event(RadarrEvent::GetCollections.into())
|
||||||
.await;
|
.await;
|
||||||
self.check_for_prompt_action().await;
|
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::CollectionDetails => {
|
ActiveRadarrBlock::CollectionDetails => {
|
||||||
self.is_loading = true;
|
self.is_loading = true;
|
||||||
self.populate_movie_collection_table().await;
|
self.populate_movie_collection_table().await;
|
||||||
self.is_loading = false;
|
self.is_loading = false;
|
||||||
self.check_for_prompt_action().await;
|
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::Downloads => {
|
ActiveRadarrBlock::Downloads => {
|
||||||
self.is_loading = true;
|
|
||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::GetDownloads.into())
|
.dispatch_network_event(RadarrEvent::GetDownloads.into())
|
||||||
.await;
|
.await;
|
||||||
self.check_for_prompt_action().await;
|
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::Movies => {
|
ActiveRadarrBlock::Movies => {
|
||||||
self
|
self
|
||||||
@@ -470,54 +466,42 @@ impl App {
|
|||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::GetDownloads.into())
|
.dispatch_network_event(RadarrEvent::GetDownloads.into())
|
||||||
.await;
|
.await;
|
||||||
self.check_for_prompt_action().await;
|
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::AddMovieSearchResults => {
|
ActiveRadarrBlock::AddMovieSearchResults => {
|
||||||
self.is_loading = true;
|
|
||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::SearchNewMovie.into())
|
.dispatch_network_event(RadarrEvent::SearchNewMovie.into())
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
self.check_for_prompt_action().await;
|
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::MovieDetails | ActiveRadarrBlock::FileInfo => {
|
ActiveRadarrBlock::MovieDetails | ActiveRadarrBlock::FileInfo => {
|
||||||
self.is_loading = true;
|
|
||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::GetMovieDetails.into())
|
.dispatch_network_event(RadarrEvent::GetMovieDetails.into())
|
||||||
.await;
|
.await;
|
||||||
self.check_for_prompt_action().await;
|
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::MovieHistory => {
|
ActiveRadarrBlock::MovieHistory => {
|
||||||
self.is_loading = true;
|
|
||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::GetMovieHistory.into())
|
.dispatch_network_event(RadarrEvent::GetMovieHistory.into())
|
||||||
.await;
|
.await;
|
||||||
self.check_for_prompt_action().await;
|
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::Cast | ActiveRadarrBlock::Crew => {
|
ActiveRadarrBlock::Cast | ActiveRadarrBlock::Crew => {
|
||||||
if self.data.radarr_data.movie_cast.items.is_empty()
|
if self.data.radarr_data.movie_cast.items.is_empty()
|
||||||
|| self.data.radarr_data.movie_crew.items.is_empty()
|
|| self.data.radarr_data.movie_crew.items.is_empty()
|
||||||
{
|
{
|
||||||
self.is_loading = true;
|
|
||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::GetMovieCredits.into())
|
.dispatch_network_event(RadarrEvent::GetMovieCredits.into())
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
self.check_for_prompt_action().await;
|
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::ManualSearch => {
|
ActiveRadarrBlock::ManualSearch => {
|
||||||
if self.data.radarr_data.movie_releases.items.is_empty() && !self.is_loading {
|
if self.data.radarr_data.movie_releases.items.is_empty() && !self.is_loading {
|
||||||
self.is_loading = true;
|
|
||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::GetReleases.into())
|
.dispatch_network_event(RadarrEvent::GetReleases.into())
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.check_for_prompt_action().await;
|
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.check_for_prompt_action().await;
|
||||||
self.reset_tick_count();
|
self.reset_tick_count();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -563,14 +547,18 @@ impl App {
|
|||||||
.unwrap_or_else(|| Duration::from_secs(0))
|
.unwrap_or_else(|| Duration::from_secs(0))
|
||||||
.is_zero()
|
.is_zero()
|
||||||
{
|
{
|
||||||
|
self.refresh_metadata().await;
|
||||||
|
self.dispatch_by_radarr_block(&active_radarr_block).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn refresh_metadata(&mut self) {
|
||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::GetQualityProfiles.into())
|
.dispatch_network_event(RadarrEvent::GetQualityProfiles.into())
|
||||||
.await;
|
.await;
|
||||||
self
|
self
|
||||||
.dispatch_network_event(RadarrEvent::GetTags.into())
|
.dispatch_network_event(RadarrEvent::GetTags.into())
|
||||||
.await;
|
.await;
|
||||||
self.dispatch_by_radarr_block(&active_radarr_block).await;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn populate_movie_collection_table(&mut self) {
|
async fn populate_movie_collection_table(&mut self) {
|
||||||
@@ -735,8 +723,6 @@ pub mod radarr_test_utils {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
mod radarr_data_tests {
|
mod radarr_data_tests {
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
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 rstest::rstest;
|
||||||
@@ -824,7 +810,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_populate_movie_preferences_lists() {
|
fn test_populate_movie_preferences_lists() {
|
||||||
let mut radarr_data = RadarrData {
|
let mut radarr_data = RadarrData {
|
||||||
quality_profile_map: HashMap::from([
|
quality_profile_map: BiMap::from_iter([
|
||||||
(2222, "HD - 1080p".to_owned()),
|
(2222, "HD - 1080p".to_owned()),
|
||||||
(1111, "Any".to_owned()),
|
(1111, "Any".to_owned()),
|
||||||
]),
|
]),
|
||||||
@@ -853,7 +839,7 @@ mod tests {
|
|||||||
edit_path: HorizontallyScrollableText::default(),
|
edit_path: HorizontallyScrollableText::default(),
|
||||||
edit_tags: HorizontallyScrollableText::default(),
|
edit_tags: HorizontallyScrollableText::default(),
|
||||||
edit_monitored: None,
|
edit_monitored: None,
|
||||||
quality_profile_map: HashMap::from([
|
quality_profile_map: BiMap::from_iter([
|
||||||
(2222, "HD - 1080p".to_owned()),
|
(2222, "HD - 1080p".to_owned()),
|
||||||
(1111, "Any".to_owned()),
|
(1111, "Any".to_owned()),
|
||||||
]),
|
]),
|
||||||
@@ -1064,6 +1050,25 @@ mod tests {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_dispatch_by_collection_details_block() {
|
async fn test_dispatch_by_collection_details_block() {
|
||||||
|
let (mut app, _) = construct_app_unit();
|
||||||
|
|
||||||
|
app.data.radarr_data.collections.set_items(vec![Collection {
|
||||||
|
movies: Some(vec![CollectionMovie::default()]),
|
||||||
|
..Collection::default()
|
||||||
|
}]);
|
||||||
|
|
||||||
|
app
|
||||||
|
.dispatch_by_radarr_block(&ActiveRadarrBlock::CollectionDetails)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
assert!(!app.is_loading);
|
||||||
|
assert!(!app.data.radarr_data.collection_movies.items.is_empty());
|
||||||
|
assert_eq!(app.tick_count, 0);
|
||||||
|
assert!(!app.data.radarr_data.prompt_confirm);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_dispatch_by_collection_details_block_with_add_movie() {
|
||||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||||
app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::AddMovie);
|
app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::AddMovie);
|
||||||
|
|
||||||
@@ -1076,7 +1081,7 @@ mod tests {
|
|||||||
.dispatch_by_radarr_block(&ActiveRadarrBlock::CollectionDetails)
|
.dispatch_by_radarr_block(&ActiveRadarrBlock::CollectionDetails)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert!(!app.is_loading);
|
assert!(app.is_loading);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
RadarrEvent::AddMovie.into()
|
RadarrEvent::AddMovie.into()
|
||||||
@@ -1111,7 +1116,7 @@ mod tests {
|
|||||||
.dispatch_by_radarr_block(&ActiveRadarrBlock::Movies)
|
.dispatch_by_radarr_block(&ActiveRadarrBlock::Movies)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
assert!(!app.is_loading);
|
assert!(app.is_loading);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
sync_network_rx.recv().await.unwrap(),
|
sync_network_rx.recv().await.unwrap(),
|
||||||
RadarrEvent::GetMovies.into()
|
RadarrEvent::GetMovies.into()
|
||||||
@@ -1360,6 +1365,24 @@ mod tests {
|
|||||||
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
assert_eq!(app.data.radarr_data.prompt_confirm_action, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_radarr_refresh_metadata() {
|
||||||
|
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||||
|
app.is_routing = true;
|
||||||
|
|
||||||
|
app.refresh_metadata().await;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
sync_network_rx.recv().await.unwrap(),
|
||||||
|
RadarrEvent::GetQualityProfiles.into()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
sync_network_rx.recv().await.unwrap(),
|
||||||
|
RadarrEvent::GetTags.into()
|
||||||
|
);
|
||||||
|
assert!(app.is_loading);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_radarr_on_tick_first_render() {
|
async fn test_radarr_on_tick_first_render() {
|
||||||
let (mut app, mut sync_network_rx) = construct_app_unit();
|
let (mut app, mut sync_network_rx) = construct_app_unit();
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> {
|
|||||||
self.app.data.radarr_data.reset_search();
|
self.app.data.radarr_data.reset_search();
|
||||||
self.app.should_ignore_quit_key = false;
|
self.app.should_ignore_quit_key = false;
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::AddMovieSearchResults => {
|
ActiveRadarrBlock::AddMovieSearchResults | ActiveRadarrBlock::AddMovieEmptySearchResults => {
|
||||||
self.app.pop_navigation_stack();
|
self.app.pop_navigation_stack();
|
||||||
self.app.data.radarr_data.add_searched_movies = StatefulTable::default();
|
self.app.data.radarr_data.add_searched_movies = StatefulTable::default();
|
||||||
self.app.should_ignore_quit_key = true;
|
self.app.should_ignore_quit_key = true;
|
||||||
@@ -295,7 +295,6 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for AddMovieHandler<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[allow(unused_imports)]
|
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_str_eq;
|
use pretty_assertions::assert_str_eq;
|
||||||
|
|
||||||
@@ -376,7 +375,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod test_handle_home_end {
|
mod test_handle_home_end {
|
||||||
use rstest::rstest;
|
|
||||||
use strum::IntoEnumIterator;
|
use strum::IntoEnumIterator;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
@@ -482,8 +480,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod test_handle_submit {
|
mod test_handle_submit {
|
||||||
use std::collections::HashMap;
|
use bimap::BiMap;
|
||||||
|
|
||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
use pretty_assertions::{assert_eq, assert_str_eq};
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
|
|
||||||
@@ -524,7 +521,7 @@ mod tests {
|
|||||||
.add_searched_movies
|
.add_searched_movies
|
||||||
.set_items(vec![AddMovieSearchResult::default()]);
|
.set_items(vec![AddMovieSearchResult::default()]);
|
||||||
app.data.radarr_data.quality_profile_map =
|
app.data.radarr_data.quality_profile_map =
|
||||||
HashMap::from([(1, "B - Test 2".to_owned()), (0, "A - Test 1".to_owned())]);
|
BiMap::from_iter([(1, "B - Test 2".to_owned()), (0, "A - Test 1".to_owned())]);
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::with(
|
||||||
&SUBMIT_KEY,
|
&SUBMIT_KEY,
|
||||||
@@ -782,11 +779,17 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[rstest]
|
||||||
fn test_add_movie_search_results_esc() {
|
fn test_add_movie_search_results_esc(
|
||||||
|
#[values(
|
||||||
|
ActiveRadarrBlock::AddMovieSearchResults,
|
||||||
|
ActiveRadarrBlock::AddMovieEmptySearchResults
|
||||||
|
)]
|
||||||
|
active_radarr_block: ActiveRadarrBlock,
|
||||||
|
) {
|
||||||
let mut app = App::default();
|
let mut app = App::default();
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchInput.into());
|
||||||
app.push_navigation_stack(ActiveRadarrBlock::AddMovieSearchResults.into());
|
app.push_navigation_stack(active_radarr_block.into());
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
@@ -796,13 +799,7 @@ mod tests {
|
|||||||
HorizontallyScrollableText
|
HorizontallyScrollableText
|
||||||
));
|
));
|
||||||
|
|
||||||
AddMovieHandler::with(
|
AddMovieHandler::with(&ESC_KEY, &mut app, &active_radarr_block, &None).handle();
|
||||||
&ESC_KEY,
|
|
||||||
&mut app,
|
|
||||||
&ActiveRadarrBlock::AddMovieSearchResults,
|
|
||||||
&None,
|
|
||||||
)
|
|
||||||
.handle();
|
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app.get_current_route(),
|
app.get_current_route(),
|
||||||
|
|||||||
@@ -164,8 +164,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod test_handle_submit {
|
mod test_handle_submit {
|
||||||
use std::collections::HashMap;
|
use bimap::BiMap;
|
||||||
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use crate::models::radarr_models::Movie;
|
use crate::models::radarr_models::Movie;
|
||||||
@@ -183,7 +182,7 @@ mod tests {
|
|||||||
.collection_movies
|
.collection_movies
|
||||||
.set_items(vec![CollectionMovie::default()]);
|
.set_items(vec![CollectionMovie::default()]);
|
||||||
app.data.radarr_data.quality_profile_map =
|
app.data.radarr_data.quality_profile_map =
|
||||||
HashMap::from([(1, "B - Test 2".to_owned()), (0, "A - Test 1".to_owned())]);
|
BiMap::from_iter([(1, "B - Test 2".to_owned()), (0, "A - Test 1".to_owned())]);
|
||||||
app.data.radarr_data.selected_block = ActiveRadarrBlock::AddMovieConfirmPrompt;
|
app.data.radarr_data.selected_block = ActiveRadarrBlock::AddMovieConfirmPrompt;
|
||||||
|
|
||||||
CollectionDetailsHandler::with(
|
CollectionDetailsHandler::with(
|
||||||
|
|||||||
@@ -211,7 +211,6 @@ impl<'a> KeyEventHandler<'a, ActiveRadarrBlock> for EditMovieHandler<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[allow(unused_imports)]
|
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_str_eq;
|
use pretty_assertions::assert_str_eq;
|
||||||
|
|
||||||
@@ -221,7 +220,7 @@ mod tests {
|
|||||||
use crate::event::Key;
|
use crate::event::Key;
|
||||||
use crate::handlers::radarr_handlers::edit_movie_handler::EditMovieHandler;
|
use crate::handlers::radarr_handlers::edit_movie_handler::EditMovieHandler;
|
||||||
use crate::handlers::KeyEventHandler;
|
use crate::handlers::KeyEventHandler;
|
||||||
use crate::models::radarr_models::{MinimumAvailability, Monitor};
|
use crate::models::radarr_models::MinimumAvailability;
|
||||||
|
|
||||||
mod test_handle_scroll_up_and_down {
|
mod test_handle_scroll_up_and_down {
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
@@ -316,7 +315,7 @@ mod tests {
|
|||||||
mod test_handle_left_right_action {
|
mod test_handle_left_right_action {
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
|
|
||||||
use crate::{test_text_box_home_end_keys, test_text_box_left_right_keys};
|
use crate::test_text_box_left_right_keys;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@@ -353,9 +352,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod test_handle_submit {
|
mod test_handle_submit {
|
||||||
use std::collections::HashMap;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
|
|
||||||
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
use crate::app::key_binding::DEFAULT_KEYBINDINGS;
|
||||||
|
|||||||
@@ -543,7 +543,7 @@ mod radarr_handler_test_utils {
|
|||||||
edit_path: HorizontallyScrollableText::default(),
|
edit_path: HorizontallyScrollableText::default(),
|
||||||
edit_tags: HorizontallyScrollableText::default(),
|
edit_tags: HorizontallyScrollableText::default(),
|
||||||
edit_monitored: None,
|
edit_monitored: None,
|
||||||
quality_profile_map: HashMap::from([
|
quality_profile_map: BiMap::from_iter([
|
||||||
(2222, "HD - 1080p".to_owned()),
|
(2222, "HD - 1080p".to_owned()),
|
||||||
(1111, "Any".to_owned()),
|
(1111, "Any".to_owned()),
|
||||||
]),
|
]),
|
||||||
@@ -1249,8 +1249,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod test_handle_key_char {
|
mod test_handle_key_char {
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
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 rstest::rstest;
|
||||||
|
|||||||
@@ -326,7 +326,6 @@ fn sort_releases_by_selected_field(
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[allow(unused_imports)]
|
|
||||||
mod tests {
|
mod tests {
|
||||||
use pretty_assertions::assert_str_eq;
|
use pretty_assertions::assert_str_eq;
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
@@ -712,13 +711,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod test_handle_esc {
|
mod test_handle_esc {
|
||||||
use bimap::BiMap;
|
use pretty_assertions::assert_eq;
|
||||||
use pretty_assertions::{assert_eq, assert_str_eq};
|
|
||||||
use rstest::rstest;
|
use rstest::rstest;
|
||||||
|
|
||||||
use crate::app::radarr::radarr_test_utils::create_test_radarr_data;
|
use crate::app::radarr::radarr_test_utils::create_test_radarr_data;
|
||||||
use crate::assert_movie_info_tabs_reset;
|
use crate::assert_movie_info_tabs_reset;
|
||||||
use crate::models::HorizontallyScrollableText;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@@ -770,8 +767,6 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mod test_handle_key_char {
|
mod test_handle_key_char {
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
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 rstest::rstest;
|
||||||
@@ -779,7 +774,6 @@ mod tests {
|
|||||||
|
|
||||||
use crate::app::radarr::radarr_test_utils::create_test_radarr_data;
|
use crate::app::radarr::radarr_test_utils::create_test_radarr_data;
|
||||||
use crate::app::radarr::RadarrData;
|
use crate::app::radarr::RadarrData;
|
||||||
use crate::handlers::radarr_handlers::RadarrHandler;
|
|
||||||
use crate::models::radarr_models::{MinimumAvailability, Movie};
|
use crate::models::radarr_models::{MinimumAvailability, Movie};
|
||||||
use crate::models::HorizontallyScrollableText;
|
use crate::models::HorizontallyScrollableText;
|
||||||
use crate::models::StatefulTable;
|
use crate::models::StatefulTable;
|
||||||
|
|||||||
@@ -81,10 +81,6 @@ async fn start_ui(app: &Arc<Mutex<App>>) -> Result<()> {
|
|||||||
loop {
|
loop {
|
||||||
let mut app = app.lock().await;
|
let mut app = app.lock().await;
|
||||||
|
|
||||||
if is_first_render {
|
|
||||||
app.is_loading = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
terminal.draw(|f| ui(f, &mut app))?;
|
terminal.draw(|f| ui(f, &mut app))?;
|
||||||
|
|
||||||
match input_events.next()? {
|
match input_events.next()? {
|
||||||
|
|||||||
+13
-6
@@ -218,13 +218,16 @@ impl HorizontallyScrollableText {
|
|||||||
*self.offset.borrow_mut() = 0;
|
*self.offset.borrow_mut() = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scroll_left_or_reset(&self, width: usize, is_current_selection: bool) {
|
pub fn scroll_left_or_reset(&self, width: usize, is_current_selection: bool, can_scroll: bool) {
|
||||||
if is_current_selection && self.text.len() >= width && *self.offset.borrow() < self.text.len() {
|
if can_scroll {
|
||||||
|
if is_current_selection && self.text.len() >= width && *self.offset.borrow() < self.text.len()
|
||||||
|
{
|
||||||
self.scroll_left();
|
self.scroll_left();
|
||||||
} else {
|
} else {
|
||||||
self.reset_offset();
|
self.reset_offset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn drain(&mut self) -> String {
|
pub fn drain(&mut self) -> String {
|
||||||
self.reset_offset();
|
self.reset_offset();
|
||||||
@@ -554,19 +557,23 @@ mod tests {
|
|||||||
let test_text = "Test string";
|
let test_text = "Test string";
|
||||||
let horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
|
let horizontally_scrollable_text = HorizontallyScrollableText::from(test_text.to_owned());
|
||||||
|
|
||||||
horizontally_scrollable_text.scroll_left_or_reset(width, true);
|
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(), 1);
|
||||||
|
|
||||||
horizontally_scrollable_text.scroll_left_or_reset(width, false);
|
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(), 0);
|
||||||
|
|
||||||
horizontally_scrollable_text.scroll_left_or_reset(width, true);
|
horizontally_scrollable_text.scroll_left_or_reset(width, true, false);
|
||||||
|
|
||||||
|
assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0);
|
||||||
|
|
||||||
|
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(), 1);
|
||||||
|
|
||||||
horizontally_scrollable_text.scroll_left_or_reset(test_text.len(), false);
|
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(), 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -224,11 +224,15 @@ impl<'a> Network<'a> {
|
|||||||
|
|
||||||
self
|
self
|
||||||
.handle_request::<(), Vec<AddMovieSearchResult>>(request_props, |movie_vec, mut app| {
|
.handle_request::<(), Vec<AddMovieSearchResult>>(request_props, |movie_vec, mut app| {
|
||||||
|
if movie_vec.is_empty() {
|
||||||
|
app.pop_and_push_navigation_stack(ActiveRadarrBlock::AddMovieEmptySearchResults.into());
|
||||||
|
} else {
|
||||||
app
|
app
|
||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.add_searched_movies
|
.add_searched_movies
|
||||||
.set_items(movie_vec)
|
.set_items(movie_vec);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@@ -371,7 +375,7 @@ impl<'a> Network<'a> {
|
|||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.quality_profile_map
|
.quality_profile_map
|
||||||
.get(&quality_profile_id.as_u64().unwrap())
|
.get_by_left(&quality_profile_id.as_u64().unwrap())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let imdb_rating = if let Some(rating) = ratings.imdb {
|
let imdb_rating = if let Some(rating) = ratings.imdb {
|
||||||
@@ -1040,7 +1044,6 @@ fn get_movie_status(has_file: bool, downloads_vec: &[DownloadRecord], movie_id:
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use bimap::BiMap;
|
use bimap::BiMap;
|
||||||
@@ -1417,6 +1420,41 @@ mod test {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_handle_search_new_movie_event_no_results() {
|
||||||
|
let (async_server, app_arc, _server) = mock_radarr_api(
|
||||||
|
RequestMethod::Get,
|
||||||
|
None,
|
||||||
|
Some(json!([])),
|
||||||
|
format!(
|
||||||
|
"{}?term=test%20term",
|
||||||
|
RadarrEvent::SearchNewMovie.resource()
|
||||||
|
)
|
||||||
|
.as_str(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
app_arc.lock().await.data.radarr_data.search = "test term".to_owned().into();
|
||||||
|
let network = Network::new(reqwest::Client::new(), &app_arc);
|
||||||
|
|
||||||
|
network
|
||||||
|
.handle_radarr_event(RadarrEvent::SearchNewMovie)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
async_server.assert_async().await;
|
||||||
|
assert!(app_arc
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.data
|
||||||
|
.radarr_data
|
||||||
|
.add_searched_movies
|
||||||
|
.items
|
||||||
|
.is_empty());
|
||||||
|
assert_eq!(
|
||||||
|
app_arc.lock().await.get_current_route(),
|
||||||
|
&ActiveRadarrBlock::AddMovieEmptySearchResults.into()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_handle_trigger_automatic_search_event() {
|
async fn test_handle_trigger_automatic_search_event() {
|
||||||
let (async_server, app_arc, _server) = mock_radarr_api(
|
let (async_server, app_arc, _server) = mock_radarr_api(
|
||||||
@@ -1551,7 +1589,7 @@ mod test {
|
|||||||
.movies
|
.movies
|
||||||
.set_items(vec![movie()]);
|
.set_items(vec![movie()]);
|
||||||
app_arc.lock().await.data.radarr_data.quality_profile_map =
|
app_arc.lock().await.data.radarr_data.quality_profile_map =
|
||||||
HashMap::from([(2222, "HD - 1080p".to_owned())]);
|
BiMap::from_iter([(2222, "HD - 1080p".to_owned())]);
|
||||||
let network = Network::new(reqwest::Client::new(), &app_arc);
|
let network = Network::new(reqwest::Client::new(), &app_arc);
|
||||||
|
|
||||||
network
|
network
|
||||||
@@ -1657,7 +1695,7 @@ mod test {
|
|||||||
.movies
|
.movies
|
||||||
.set_items(vec![movie()]);
|
.set_items(vec![movie()]);
|
||||||
app_arc.lock().await.data.radarr_data.quality_profile_map =
|
app_arc.lock().await.data.radarr_data.quality_profile_map =
|
||||||
HashMap::from([(2222, "HD - 1080p".to_owned())]);
|
BiMap::from_iter([(2222, "HD - 1080p".to_owned())]);
|
||||||
let network = Network::new(reqwest::Client::new(), &app_arc);
|
let network = Network::new(reqwest::Client::new(), &app_arc);
|
||||||
|
|
||||||
network
|
network
|
||||||
@@ -1852,7 +1890,7 @@ mod test {
|
|||||||
async_server.assert_async().await;
|
async_server.assert_async().await;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
app_arc.lock().await.data.radarr_data.quality_profile_map,
|
app_arc.lock().await.data.radarr_data.quality_profile_map,
|
||||||
HashMap::from([(2222u64, "HD - 1080p".to_owned())])
|
BiMap::from_iter([(2222u64, "HD - 1080p".to_owned())])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2064,7 +2102,8 @@ mod test {
|
|||||||
free_space: Number::from(21990232555520u64),
|
free_space: Number::from(21990232555520u64),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
app.data.radarr_data.quality_profile_map = HashMap::from([(2222, "HD - 1080p".to_owned())]);
|
app.data.radarr_data.quality_profile_map =
|
||||||
|
BiMap::from_iter([(2222, "HD - 1080p".to_owned())]);
|
||||||
app.data.radarr_data.tags_map =
|
app.data.radarr_data.tags_map =
|
||||||
BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]);
|
BiMap::from_iter([(1, "usenet".to_owned()), (2, "testing".to_owned())]);
|
||||||
app.data.radarr_data.edit_tags = "usenet, testing".to_owned().into();
|
app.data.radarr_data.edit_tags = "usenet, testing".to_owned().into();
|
||||||
@@ -2153,7 +2192,7 @@ mod test {
|
|||||||
..movie()
|
..movie()
|
||||||
}]);
|
}]);
|
||||||
app.data.radarr_data.quality_profile_map =
|
app.data.radarr_data.quality_profile_map =
|
||||||
HashMap::from([(1111, "Any".to_owned()), (2222, "HD - 1080p".to_owned())]);
|
BiMap::from_iter([(1111, "Any".to_owned()), (2222, "HD - 1080p".to_owned())]);
|
||||||
}
|
}
|
||||||
let network = Network::new(reqwest::Client::new(), &app_arc);
|
let network = Network::new(reqwest::Client::new(), &app_arc);
|
||||||
|
|
||||||
@@ -2208,7 +2247,7 @@ mod test {
|
|||||||
.movie_quality_profile_list
|
.movie_quality_profile_list
|
||||||
.set_items(vec!["Any".to_owned(), "HD - 1080p".to_owned()]);
|
.set_items(vec!["Any".to_owned(), "HD - 1080p".to_owned()]);
|
||||||
app.data.radarr_data.quality_profile_map =
|
app.data.radarr_data.quality_profile_map =
|
||||||
HashMap::from_iter([(1, "Any".to_owned()), (2, "HD - 1080p".to_owned())]);
|
BiMap::from_iter([(1, "Any".to_owned()), (2, "HD - 1080p".to_owned())]);
|
||||||
}
|
}
|
||||||
let network = Network::new(reqwest::Client::new(), &app_arc);
|
let network = Network::new(reqwest::Client::new(), &app_arc);
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ pub(super) fn draw_add_movie_search_popup<B: Backend>(
|
|||||||
) {
|
) {
|
||||||
if let Route::Radarr(active_radarr_block, context_option) = *app.get_current_route() {
|
if let Route::Radarr(active_radarr_block, context_option) = *app.get_current_route() {
|
||||||
match active_radarr_block {
|
match active_radarr_block {
|
||||||
ActiveRadarrBlock::AddMovieSearchInput | ActiveRadarrBlock::AddMovieSearchResults => {
|
ActiveRadarrBlock::AddMovieSearchInput
|
||||||
|
| ActiveRadarrBlock::AddMovieSearchResults
|
||||||
|
| ActiveRadarrBlock::AddMovieEmptySearchResults => {
|
||||||
draw_add_movie_search(f, app, area);
|
draw_add_movie_search(f, app, area);
|
||||||
}
|
}
|
||||||
ActiveRadarrBlock::AddMoviePrompt
|
ActiveRadarrBlock::AddMoviePrompt
|
||||||
@@ -108,6 +110,10 @@ fn draw_add_movie_search<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area:
|
|||||||
.alignment(Alignment::Center);
|
.alignment(Alignment::Center);
|
||||||
f.render_widget(help_paragraph, chunks[2]);
|
f.render_widget(help_paragraph, chunks[2]);
|
||||||
}
|
}
|
||||||
|
ActiveRadarrBlock::AddMovieEmptySearchResults => {
|
||||||
|
f.render_widget(layout_block(), chunks[1]);
|
||||||
|
draw_error_popup(f, "No movies found matching your query!");
|
||||||
|
}
|
||||||
ActiveRadarrBlock::AddMovieSearchResults
|
ActiveRadarrBlock::AddMovieSearchResults
|
||||||
| ActiveRadarrBlock::AddMoviePrompt
|
| ActiveRadarrBlock::AddMoviePrompt
|
||||||
| ActiveRadarrBlock::AddMovieSelectMonitor
|
| ActiveRadarrBlock::AddMovieSelectMonitor
|
||||||
@@ -122,13 +128,6 @@ fn draw_add_movie_search<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area:
|
|||||||
.alignment(Alignment::Center);
|
.alignment(Alignment::Center);
|
||||||
f.render_widget(help_paragraph, chunks[2]);
|
f.render_widget(help_paragraph, chunks[2]);
|
||||||
|
|
||||||
if app.data.radarr_data.add_searched_movies.items.is_empty()
|
|
||||||
&& !app.is_loading
|
|
||||||
&& !app.is_routing
|
|
||||||
{
|
|
||||||
f.render_widget(layout_block(), chunks[1]);
|
|
||||||
draw_error_popup(f, "No movies found matching your query!");
|
|
||||||
} else {
|
|
||||||
draw_table(
|
draw_table(
|
||||||
f,
|
f,
|
||||||
chunks[1],
|
chunks[1],
|
||||||
@@ -199,6 +198,7 @@ fn draw_add_movie_search<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area:
|
|||||||
movie.title.scroll_left_or_reset(
|
movie.title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 27),
|
get_width_from_percentage(area, 27),
|
||||||
*movie == current_selection,
|
*movie == current_selection,
|
||||||
|
app.tick_count % app.ticks_until_scroll == 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
Row::new(vec![
|
Row::new(vec![
|
||||||
@@ -215,7 +215,6 @@ fn draw_add_movie_search<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area:
|
|||||||
app.is_loading,
|
app.is_loading,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ pub(super) fn draw_collection_details<B: Backend>(
|
|||||||
.data
|
.data
|
||||||
.radarr_data
|
.radarr_data
|
||||||
.quality_profile_map
|
.quality_profile_map
|
||||||
.get(&collection_selection.quality_profile_id.as_u64().unwrap())
|
.get_by_left(&collection_selection.quality_profile_id.as_u64().unwrap())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let current_selection = if app.data.radarr_data.collection_movies.items.is_empty() {
|
let current_selection = if app.data.radarr_data.collection_movies.items.is_empty() {
|
||||||
@@ -155,6 +155,7 @@ pub(super) fn draw_collection_details<B: Backend>(
|
|||||||
movie.title.scroll_left_or_reset(
|
movie.title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(chunks[1], 20),
|
get_width_from_percentage(chunks[1], 20),
|
||||||
current_selection == *movie,
|
current_selection == *movie,
|
||||||
|
app.tick_count % app.ticks_until_scroll == 0,
|
||||||
);
|
);
|
||||||
let (hours, minutes) = convert_runtime(movie.runtime.as_u64().unwrap());
|
let (hours, minutes) = convert_runtime(movie.runtime.as_u64().unwrap());
|
||||||
let imdb_rating = movie
|
let imdb_rating = movie
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ fn draw_library<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
|
|||||||
let file_size: f64 = convert_to_gb(movie.size_on_disk.as_u64().unwrap());
|
let file_size: f64 = convert_to_gb(movie.size_on_disk.as_u64().unwrap());
|
||||||
let certification = movie.certification.clone().unwrap_or_else(|| "".to_owned());
|
let certification = movie.certification.clone().unwrap_or_else(|| "".to_owned());
|
||||||
let quality_profile = quality_profile_map
|
let quality_profile = quality_profile_map
|
||||||
.get(&movie.quality_profile_id.as_u64().unwrap())
|
.get_by_left(&movie.quality_profile_id.as_u64().unwrap())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_owned();
|
.to_owned();
|
||||||
let tags = movie
|
let tags = movie
|
||||||
@@ -475,6 +475,7 @@ fn draw_downloads<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect) {
|
|||||||
path.scroll_left_or_reset(
|
path.scroll_left_or_reset(
|
||||||
get_width_from_percentage(area, 18),
|
get_width_from_percentage(area, 18),
|
||||||
current_selection == *download_record,
|
current_selection == *download_record,
|
||||||
|
app.tick_count % app.ticks_until_scroll == 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
let percent = 1f64 - (sizeleft.as_f64().unwrap() / size.as_f64().unwrap());
|
let percent = 1f64 - (sizeleft.as_f64().unwrap() / size.as_f64().unwrap());
|
||||||
@@ -533,7 +534,7 @@ fn draw_collections<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, area: Rect)
|
|||||||
Cell::from(collection.root_folder_path.clone().unwrap_or_default()),
|
Cell::from(collection.root_folder_path.clone().unwrap_or_default()),
|
||||||
Cell::from(
|
Cell::from(
|
||||||
quality_profile_map
|
quality_profile_map
|
||||||
.get(&collection.quality_profile_id.as_u64().unwrap())
|
.get_by_left(&collection.quality_profile_id.as_u64().unwrap())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -271,6 +271,7 @@ fn draw_movie_history<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_a
|
|||||||
movie_history_item.source_title.scroll_left_or_reset(
|
movie_history_item.source_title.scroll_left_or_reset(
|
||||||
get_width_from_percentage(content_area, 34),
|
get_width_from_percentage(content_area, 34),
|
||||||
current_selection == *movie_history_item,
|
current_selection == *movie_history_item,
|
||||||
|
app.tick_count % app.ticks_until_scroll == 0,
|
||||||
);
|
);
|
||||||
|
|
||||||
Row::new(vec![
|
Row::new(vec![
|
||||||
@@ -322,7 +323,7 @@ fn draw_movie_cast<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_area
|
|||||||
.style(style_success())
|
.style(style_success())
|
||||||
},
|
},
|
||||||
app.is_loading,
|
app.is_loading,
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_movie_crew<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_area: Rect) {
|
fn draw_movie_crew<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_area: Rect) {
|
||||||
@@ -442,6 +443,7 @@ fn draw_movie_releases<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_
|
|||||||
get_width_from_percentage(content_area, 30),
|
get_width_from_percentage(content_area, 30),
|
||||||
current_selection == *release
|
current_selection == *release
|
||||||
&& current_route != ActiveRadarrBlock::ManualSearchConfirmPrompt.into(),
|
&& current_route != ActiveRadarrBlock::ManualSearchConfirmPrompt.into(),
|
||||||
|
app.tick_count % app.ticks_until_scroll == 0,
|
||||||
);
|
);
|
||||||
let size = convert_to_gb(size.as_u64().unwrap());
|
let size = convert_to_gb(size.as_u64().unwrap());
|
||||||
let rejected_str = if *rejected { "⛔" } else { "" };
|
let rejected_str = if *rejected { "⛔" } else { "" };
|
||||||
@@ -477,7 +479,7 @@ fn draw_movie_releases<B: Backend>(f: &mut Frame<'_, B>, app: &mut App, content_
|
|||||||
.style(style_primary())
|
.style(style_primary())
|
||||||
},
|
},
|
||||||
app.is_loading,
|
app.is_loading,
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_manual_search_confirm_prompt<B: Backend>(
|
fn draw_manual_search_confirm_prompt<B: Backend>(
|
||||||
|
|||||||
Reference in New Issue
Block a user