diff --git a/Cargo.toml b/Cargo.toml index bdccade..706caa2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,9 @@ [package] name = "managarr" -version = "0.0.22" +version = "0.0.26" authors = ["Alex Clarke "] description = "A TUI for managing *arr servers" -keywords = ["managarr", "tui-rs", "dashboard", "servarr"] +keywords = ["managarr", "tui-rs", "dashboard", "servarr", "tui", "terminal"] documentation = "https://github.com/Dark-Alex-17/managarr" repository = "https://github.com/Dark-Alex-17/managarr" homepage = "https://github.com/Dark-Alex-17/managarr" diff --git a/src/models/mod.rs b/src/models/mod.rs index e247be2..d2ff36c 100644 --- a/src/models/mod.rs +++ b/src/models/mod.rs @@ -270,14 +270,49 @@ impl HorizontallyScrollableText { pub fn pop(&mut self) { if *self.offset.borrow() < self.len() { - self.text.remove(self.len() - *self.offset.borrow() - 1); + let (index, _) = self + .text + .chars() + .enumerate() + .nth(self.len() - *self.offset.borrow() - 1) + .unwrap(); + self.text = self + .text + .chars() + .enumerate() + .filter(|(idx, _)| *idx != index) + .map(|tuple| tuple.1) + .collect(); } } pub fn push(&mut self, character: char) { - self - .text - .insert(self.len() - *self.offset.borrow(), character); + if self.text.is_empty() { + self.text.push(character); + } else { + let index = self.len() - *self.offset.borrow(); + + if index == self.len() { + self.text.push(character); + } else { + let mut new_text = String::new(); + self + .text + .chars() + .collect::>() + .iter() + .enumerate() + .for_each(|(idx, &c)| { + if idx == index { + new_text.push(character); + } + + new_text.push(c); + }); + + self.text = new_text; + } + } } } diff --git a/src/models/model_tests.rs b/src/models/model_tests.rs index 7bea973..4305d7a 100644 --- a/src/models/model_tests.rs +++ b/src/models/model_tests.rs @@ -340,10 +340,11 @@ mod tests { #[test] fn test_horizontally_scrollable_text_len() { - let test_text = "우리 생애 최고의 해 The.Best"; + let test_text = "우리 생애 최고의 해Test.Text"; let horizontally_scrollable_text = HorizontallyScrollableText::new(test_text.to_owned()); assert_eq!(horizontally_scrollable_text.len(), 20); + assert_eq!(horizontally_scrollable_text.text.len(), 36); assert_str_eq!(horizontally_scrollable_text.text, test_text); } @@ -367,6 +368,26 @@ mod tests { ); } + #[test] + fn test_horizontally_scrollable_text_scroll_text_left_uses_len_method() { + let horizontally_scrollable_text = HorizontallyScrollableText::from("우리"); + + horizontally_scrollable_text.scroll_left(); + + assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1); + assert_str_eq!(horizontally_scrollable_text.to_string(), "리"); + + horizontally_scrollable_text.scroll_left(); + + assert_eq!(*horizontally_scrollable_text.offset.borrow(), 2); + assert_str_eq!(horizontally_scrollable_text.to_string(), ""); + + horizontally_scrollable_text.scroll_left(); + + assert_eq!(*horizontally_scrollable_text.offset.borrow(), 2); + assert!(horizontally_scrollable_text.to_string().is_empty()); + } + #[test] fn test_horizontally_scrollable_text_scroll_text_right() { let horizontally_scrollable_text = HorizontallyScrollableText::from("Test string"); @@ -398,6 +419,15 @@ mod tests { ); } + #[test] + fn test_horizontally_scrollable_text_scroll_home_uses_len_method() { + let horizontally_scrollable_text = HorizontallyScrollableText::from("우리"); + + horizontally_scrollable_text.scroll_home(); + + assert_eq!(*horizontally_scrollable_text.offset.borrow(), 2); + } + #[test] fn test_horizontally_scrollable_text_reset_offset() { let horizontally_scrollable_text = HorizontallyScrollableText { @@ -411,7 +441,7 @@ mod tests { } #[test] - fn test_horizontally_scrollable_text_scroll_or_reset() { + fn test_horizontally_scrollable_text_scroll_left_or_reset() { let width = 3; let test_text = "Test string"; let horizontally_scrollable_text = HorizontallyScrollableText::from(test_text); @@ -438,7 +468,7 @@ mod tests { } #[test] - fn test_horizontally_scrollable_test_scroll_or_reset_resets_when_text_unselected() { + fn test_horizontally_scrollable_text_scroll_left_or_reset_resets_when_text_unselected() { let horizontally_scrollable_test = HorizontallyScrollableText::from("Test string"); horizontally_scrollable_test.scroll_left(); @@ -449,55 +479,98 @@ mod tests { assert_eq!(*horizontally_scrollable_test.offset.borrow(), 0); } + #[test] + fn test_horizontally_scrollable_text_scroll_left_or_reset_uses_len_method() { + let horizontally_scrollable_text = HorizontallyScrollableText::from("우리"); + let width = 1; + + horizontally_scrollable_text.scroll_left_or_reset(width, true, true); + + 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(), 2); + + horizontally_scrollable_text.scroll_left_or_reset(width, true, true); + + assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0); + } + #[test] fn test_horizontally_scrollable_text_pop() { - let test_text = "Test string"; + let test_text = "Test sTrin우gs"; let mut horizontally_scrollable_text = HorizontallyScrollableText::from(test_text); horizontally_scrollable_text.pop(); - assert_str_eq!(horizontally_scrollable_text.text, "Test strin"); + assert_str_eq!(horizontally_scrollable_text.text, "Test sTrin우g"); assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0); horizontally_scrollable_text.scroll_left(); horizontally_scrollable_text.pop(); - assert_str_eq!(horizontally_scrollable_text.text, "Test strn"); + assert_str_eq!(horizontally_scrollable_text.text, "Test sTring"); assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1); horizontally_scrollable_text.scroll_right(); horizontally_scrollable_text.scroll_right(); horizontally_scrollable_text.pop(); - assert_str_eq!(horizontally_scrollable_text.text, "Test str"); + assert_str_eq!(horizontally_scrollable_text.text, "Test sTrin"); assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0); horizontally_scrollable_text.scroll_home(); horizontally_scrollable_text.pop(); - assert_str_eq!(horizontally_scrollable_text.text, "Test str"); - assert_eq!(*horizontally_scrollable_text.offset.borrow(), 8); + assert_str_eq!(horizontally_scrollable_text.text, "Test sTrin"); + assert_eq!(*horizontally_scrollable_text.offset.borrow(), 10); + + horizontally_scrollable_text.scroll_right(); + horizontally_scrollable_text.pop(); + + assert_str_eq!(horizontally_scrollable_text.text, "est sTrin"); + assert_eq!(*horizontally_scrollable_text.offset.borrow(), 9); + } + + #[test] + fn test_horizontally_scrollable_text_pop_uses_len_method() { + let mut horizontally_scrollable_text = HorizontallyScrollableText::from("우리"); + horizontally_scrollable_text.pop(); + + assert_str_eq!(horizontally_scrollable_text.text, "우"); + assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0); + + horizontally_scrollable_text.pop(); + + assert!(horizontally_scrollable_text.text.is_empty()); + assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0); + + horizontally_scrollable_text.pop(); + + assert!(horizontally_scrollable_text.text.is_empty()); + assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0); } #[test] fn test_horizontally_scrollable_text_push() { - let test_text = "Test string"; + let test_text = "Test stri우ng"; let mut horizontally_scrollable_text = HorizontallyScrollableText::from(test_text); horizontally_scrollable_text.push('h'); - assert_str_eq!(horizontally_scrollable_text.text, "Test stringh"); + assert_str_eq!(horizontally_scrollable_text.text, "Test stri우ngh"); assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0); horizontally_scrollable_text.scroll_left(); horizontally_scrollable_text.push('l'); - assert_str_eq!(horizontally_scrollable_text.text, "Test stringlh"); + assert_str_eq!(horizontally_scrollable_text.text, "Test stri우nglh"); assert_eq!(*horizontally_scrollable_text.offset.borrow(), 1); horizontally_scrollable_text.scroll_right(); horizontally_scrollable_text.scroll_right(); - horizontally_scrollable_text.push('0'); + horizontally_scrollable_text.push('리'); - assert_str_eq!(horizontally_scrollable_text.text, "Test stringlh0"); + assert_str_eq!(horizontally_scrollable_text.text, "Test stri우nglh리"); assert_eq!(*horizontally_scrollable_text.offset.borrow(), 0); } diff --git a/src/ui/radarr_ui/collections/mod.rs b/src/ui/radarr_ui/collections/mod.rs index b8dc22d..43a5baf 100644 --- a/src/ui/radarr_ui/collections/mod.rs +++ b/src/ui/radarr_ui/collections/mod.rs @@ -47,7 +47,7 @@ impl DrawUi for CollectionsUi { draw_collections, draw_search_box, 30, - 11, + 13, ), ActiveRadarrBlock::FilterCollections => draw_popup_over( f, @@ -56,7 +56,7 @@ impl DrawUi for CollectionsUi { draw_collections, draw_filter_box, 30, - 11, + 13, ), ActiveRadarrBlock::UpdateAllCollectionsPrompt => draw_prompt_popup_over( f, diff --git a/src/ui/radarr_ui/library/mod.rs b/src/ui/radarr_ui/library/mod.rs index bf58b8f..1199d32 100644 --- a/src/ui/radarr_ui/library/mod.rs +++ b/src/ui/radarr_ui/library/mod.rs @@ -48,10 +48,10 @@ impl DrawUi for LibraryUi { { ActiveRadarrBlock::Movies => draw_library(f, app, content_rect), ActiveRadarrBlock::SearchMovie => { - draw_popup_over(f, app, content_rect, draw_library, draw_search_box, 30, 11) + draw_popup_over(f, app, content_rect, draw_library, draw_search_box, 30, 13) } ActiveRadarrBlock::FilterMovies => { - draw_popup_over(f, app, content_rect, draw_library, draw_filter_box, 30, 11) + draw_popup_over(f, app, content_rect, draw_library, draw_filter_box, 30, 13) } ActiveRadarrBlock::UpdateAllMoviesPrompt => draw_prompt_popup_over( f, diff --git a/src/ui/radarr_ui/mod.rs b/src/ui/radarr_ui/mod.rs index 59c3bd3..cf85680 100644 --- a/src/ui/radarr_ui/mod.rs +++ b/src/ui/radarr_ui/mod.rs @@ -25,8 +25,9 @@ use crate::ui::radarr_ui::root_folders::RootFoldersUi; use crate::ui::radarr_ui::system::SystemUi; use crate::ui::utils::{ borderless_block, horizontal_chunks, layout_block, line_gauge_with_label, line_gauge_with_title, - show_cursor, style_awaiting_import, style_bold, style_default, style_failure, style_success, - style_unmonitored, style_warning, title_block, title_block_centered, vertical_chunks_with_margin, + show_cursor, style_awaiting_import, style_bold, style_default, style_failure, style_help, + style_success, style_unmonitored, style_warning, title_block, title_block_centered, + vertical_chunks_with_margin, }; use crate::ui::DrawUi; use crate::utils::convert_to_gb; @@ -231,8 +232,15 @@ fn determine_row_style(downloads_vec: &[DownloadRecord], movie: &Movie) -> Style } fn draw_search_box(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) { - let chunks = - vertical_chunks_with_margin(vec![Constraint::Length(3), Constraint::Min(0)], area, 1); + let chunks = vertical_chunks_with_margin( + vec![ + Constraint::Length(3), + Constraint::Length(1), + Constraint::Min(0), + ], + area, + 1, + ); if !app.data.radarr_data.is_searching { let error_msg = match app.get_current_route() { Route::Radarr(active_radarr_block, _) => match active_radarr_block { @@ -272,15 +280,27 @@ fn draw_search_box(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Re let input = Paragraph::new(block_content.as_str()) .style(style_default()) .block(title_block_centered(block_title)); + let help = Paragraph::new(" cancel") + .style(style_help()) + .alignment(Alignment::Center) + .block(borderless_block()); show_cursor(f, chunks[0], offset, block_content); f.render_widget(input, chunks[0]); + f.render_widget(help, chunks[1]); } } fn draw_filter_box(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Rect) { - let chunks = - vertical_chunks_with_margin(vec![Constraint::Length(3), Constraint::Min(0)], area, 1); + let chunks = vertical_chunks_with_margin( + vec![ + Constraint::Length(3), + Constraint::Length(1), + Constraint::Min(0), + ], + area, + 1, + ); if !app.data.radarr_data.is_filtering { let error_msg = match app.get_current_route() { Route::Radarr(active_radarr_block, _) => match active_radarr_block { @@ -320,9 +340,14 @@ fn draw_filter_box(f: &mut Frame<'_, B>, app: &mut App<'_>, area: Re let input = Paragraph::new(block_content.as_str()) .style(style_default()) .block(title_block_centered(block_title)); + let help = Paragraph::new(" cancel") + .style(style_help()) + .alignment(Alignment::Center) + .block(borderless_block()); show_cursor(f, chunks[0], offset, block_content); f.render_widget(input, chunks[0]); + f.render_widget(help, chunks[1]); } } diff --git a/src/ui/radarr_ui/root_folders/mod.rs b/src/ui/radarr_ui/root_folders/mod.rs index ae17ccf..9cd5acc 100644 --- a/src/ui/radarr_ui/root_folders/mod.rs +++ b/src/ui/radarr_ui/root_folders/mod.rs @@ -42,7 +42,7 @@ impl DrawUi for RootFoldersUi { draw_root_folders, draw_add_root_folder_prompt_box, 30, - 15, + 13, ), ActiveRadarrBlock::DeleteRootFolderPrompt => draw_prompt_popup_over( f,