refactor: Simplified both the table_handler macro and the stateful_table implementation
This commit is contained in:
@@ -38,7 +38,6 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for BlocklistHandler<'a,
|
||||
let blocklist_table_handling_config =
|
||||
TableHandlingConfig::new(ActiveRadarrBlock::Blocklist.into())
|
||||
.sorting_block(ActiveRadarrBlock::BlocklistSortPrompt.into())
|
||||
.sort_by_fn(|a: &BlocklistItem, b: &BlocklistItem| a.id.cmp(&b.id))
|
||||
.sort_options(blocklist_sorting_options());
|
||||
|
||||
if !self.handle_blocklist_table_events(blocklist_table_handling_config) {
|
||||
|
||||
@@ -42,7 +42,6 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for CollectionsHandler<'
|
||||
let collections_table_handling_config =
|
||||
TableHandlingConfig::new(ActiveRadarrBlock::Collections.into())
|
||||
.sorting_block(ActiveRadarrBlock::CollectionsSortPrompt.into())
|
||||
.sort_by_fn(|a: &Collection, b: &Collection| a.id.cmp(&b.id))
|
||||
.sort_options(collections_sorting_options())
|
||||
.searching_block(ActiveRadarrBlock::SearchCollection.into())
|
||||
.search_error_block(ActiveRadarrBlock::SearchCollectionError.into())
|
||||
|
||||
@@ -7,7 +7,6 @@ use crate::models::servarr_data::radarr::modals::AddMovieModal;
|
||||
use crate::models::servarr_data::radarr::radarr_data::{
|
||||
ADD_MOVIE_BLOCKS, ADD_MOVIE_SELECTION_BLOCKS, ActiveRadarrBlock,
|
||||
};
|
||||
use crate::models::stateful_table::StatefulTable;
|
||||
use crate::models::{BlockSelectionState, Scrollable};
|
||||
use crate::network::radarr_network::RadarrEvent;
|
||||
use crate::{
|
||||
@@ -35,7 +34,7 @@ impl AddMovieHandler<'_, '_> {
|
||||
.radarr_data
|
||||
.add_searched_movies
|
||||
.as_mut()
|
||||
.unwrap_or(&mut StatefulTable::default()),
|
||||
.expect("add_searched_movies should be initialized"),
|
||||
AddMovieSearchResult
|
||||
);
|
||||
|
||||
|
||||
@@ -44,7 +44,6 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for LibraryHandler<'a, '
|
||||
fn handle(&mut self) {
|
||||
let movie_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::Movies.into())
|
||||
.sorting_block(ActiveRadarrBlock::MoviesSortPrompt.into())
|
||||
.sort_by_fn(|a: &Movie, b: &Movie| a.id.cmp(&b.id))
|
||||
.sort_options(movies_sorting_options())
|
||||
.searching_block(ActiveRadarrBlock::SearchMovie.into())
|
||||
.search_error_block(ActiveRadarrBlock::SearchMovieError.into())
|
||||
|
||||
@@ -38,7 +38,6 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for BlocklistHandler<'a,
|
||||
let blocklist_table_handling_config =
|
||||
TableHandlingConfig::new(ActiveSonarrBlock::Blocklist.into())
|
||||
.sorting_block(ActiveSonarrBlock::BlocklistSortPrompt.into())
|
||||
.sort_by_fn(|a: &BlocklistItem, b: &BlocklistItem| a.id.cmp(&b.id))
|
||||
.sort_options(blocklist_sorting_options());
|
||||
|
||||
if !self.handle_blocklist_table_events(blocklist_table_handling_config) {
|
||||
|
||||
@@ -33,7 +33,6 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for HistoryHandler<'a, '
|
||||
fn handle(&mut self) {
|
||||
let history_table_handling_config = TableHandlingConfig::new(ActiveSonarrBlock::History.into())
|
||||
.sorting_block(ActiveSonarrBlock::HistorySortPrompt.into())
|
||||
.sort_by_fn(|a: &SonarrHistoryItem, b: &SonarrHistoryItem| a.id.cmp(&b.id))
|
||||
.sort_options(history_sorting_options())
|
||||
.searching_block(ActiveSonarrBlock::SearchHistory.into())
|
||||
.search_error_block(ActiveSonarrBlock::SearchHistoryError.into())
|
||||
|
||||
@@ -5,7 +5,6 @@ use crate::models::servarr_data::sonarr::sonarr_data::{
|
||||
ADD_SERIES_BLOCKS, ADD_SERIES_SELECTION_BLOCKS, ActiveSonarrBlock,
|
||||
};
|
||||
use crate::models::sonarr_models::{AddSeriesBody, AddSeriesOptions, AddSeriesSearchResult};
|
||||
use crate::models::stateful_table::StatefulTable;
|
||||
use crate::models::{BlockSelectionState, Scrollable};
|
||||
use crate::network::sonarr_network::SonarrEvent;
|
||||
use crate::{
|
||||
@@ -33,7 +32,7 @@ impl AddSeriesHandler<'_, '_> {
|
||||
.sonarr_data
|
||||
.add_searched_series
|
||||
.as_mut()
|
||||
.unwrap_or(&mut StatefulTable::default()),
|
||||
.expect("add_searched_series should be initialized"),
|
||||
AddSeriesSearchResult
|
||||
);
|
||||
|
||||
|
||||
@@ -55,7 +55,6 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for LibraryHandler<'a, '
|
||||
fn handle(&mut self) {
|
||||
let series_table_handling_config = TableHandlingConfig::new(ActiveSonarrBlock::Series.into())
|
||||
.sorting_block(ActiveSonarrBlock::SeriesSortPrompt.into())
|
||||
.sort_by_fn(|a: &Series, b: &Series| a.id.cmp(&b.id))
|
||||
.sort_options(series_sorting_options())
|
||||
.searching_block(ActiveSonarrBlock::SearchSeries.into())
|
||||
.search_error_block(ActiveSonarrBlock::SearchSeriesError.into())
|
||||
|
||||
@@ -115,7 +115,6 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeasonDetailsHandler
|
||||
TableHandlingConfig::new(ActiveSonarrBlock::SeasonHistory.into())
|
||||
.sorting_block(ActiveSonarrBlock::SeasonHistorySortPrompt.into())
|
||||
.sort_options(history_sorting_options())
|
||||
.sort_by_fn(|a: &SonarrHistoryItem, b: &SonarrHistoryItem| a.id.cmp(&b.id))
|
||||
.searching_block(ActiveSonarrBlock::SearchSeasonHistory.into())
|
||||
.search_error_block(ActiveSonarrBlock::SearchSeasonHistoryError.into())
|
||||
.search_field_fn(|history_item: &SonarrHistoryItem| &history_item.source_title.text)
|
||||
|
||||
@@ -71,7 +71,6 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for SeriesDetailsHandler
|
||||
TableHandlingConfig::new(ActiveSonarrBlock::SeriesHistory.into())
|
||||
.sorting_block(ActiveSonarrBlock::SeriesHistorySortPrompt.into())
|
||||
.sort_options(history_sorting_options())
|
||||
.sort_by_fn(|a: &SonarrHistoryItem, b: &SonarrHistoryItem| a.id.cmp(&b.id))
|
||||
.searching_block(ActiveSonarrBlock::SearchSeriesHistory.into())
|
||||
.search_error_block(ActiveSonarrBlock::SearchSeriesHistoryError.into())
|
||||
.search_field_fn(|history_item: &SonarrHistoryItem| &history_item.source_title.text)
|
||||
|
||||
+126
-193
@@ -1,7 +1,6 @@
|
||||
use crate::models::Route;
|
||||
use crate::models::stateful_table::SortOption;
|
||||
use derive_setters::Setters;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::Debug;
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -18,8 +17,6 @@ where
|
||||
#[setters(strip_option)]
|
||||
pub sort_options: Option<Vec<SortOption<T>>>,
|
||||
#[setters(strip_option)]
|
||||
pub sort_by_fn: Option<fn(&T, &T) -> Ordering>,
|
||||
#[setters(strip_option)]
|
||||
pub searching_block: Option<Route>,
|
||||
#[setters(strip_option)]
|
||||
pub search_error_block: Option<Route>,
|
||||
@@ -56,16 +53,12 @@ macro_rules! handle_table_events {
|
||||
_ if $crate::matches_key!(submit, $self.key) => $self.[<handle_ $name _table_submit>](config),
|
||||
_ if $crate::matches_key!(esc, $self.key) => $self.[<handle_ $name _table_esc>](config),
|
||||
_ if config.searching_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.searching_block
|
||||
.as_ref()
|
||||
.expect("searching_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() =>
|
||||
{
|
||||
$self.[<handle_ $name _table_search_box_input>]()
|
||||
}
|
||||
_ if config.filtering_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.filtering_block
|
||||
.as_ref()
|
||||
.expect("filtering_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() =>
|
||||
{
|
||||
$self.[<handle_ $name _table_filter_box_input>]()
|
||||
}
|
||||
@@ -91,11 +84,11 @@ macro_rules! handle_table_events {
|
||||
true
|
||||
}
|
||||
_ if config.sorting_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.sorting_block
|
||||
.as_ref()
|
||||
.expect("sorting_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() =>
|
||||
{
|
||||
$table.sort.as_mut().unwrap().scroll_up();
|
||||
if let Some(ref mut sort) = $table.sort {
|
||||
sort.scroll_up();
|
||||
}
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
@@ -111,27 +104,12 @@ macro_rules! handle_table_events {
|
||||
true
|
||||
}
|
||||
_ if config.sorting_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.sorting_block
|
||||
.as_ref()
|
||||
.expect("sorting_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() =>
|
||||
{
|
||||
$table
|
||||
.sort
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.scroll_down();
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn [<handle_ $name _table_page_down>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||
use $crate::models::Paginated;
|
||||
|
||||
match $self.app.get_current_route() {
|
||||
_ if config.table_block == $self.app.get_current_route() => {
|
||||
$table.page_down();
|
||||
if let Some(ref mut sort) = $table.sort {
|
||||
sort
|
||||
.scroll_down();
|
||||
}
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
@@ -141,12 +119,22 @@ macro_rules! handle_table_events {
|
||||
fn [<handle_ $name _table_page_up>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||
use $crate::models::Paginated;
|
||||
|
||||
match $self.app.get_current_route() {
|
||||
_ if config.table_block == $self.app.get_current_route() => {
|
||||
$table.page_up();
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
if config.table_block == $self.app.get_current_route() {
|
||||
$table.page_up();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn [<handle_ $name _table_page_down>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||
use $crate::models::Paginated;
|
||||
|
||||
if config.table_block == $self.app.get_current_route() {
|
||||
$table.page_down();
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,39 +147,27 @@ macro_rules! handle_table_events {
|
||||
true
|
||||
}
|
||||
_ if config.sorting_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.sorting_block
|
||||
.as_ref()
|
||||
.expect("sorting_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() =>
|
||||
{
|
||||
$table
|
||||
.sort
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.scroll_to_top();
|
||||
if let Some(ref mut sort) = $table.sort {
|
||||
sort.scroll_to_top();
|
||||
}
|
||||
true
|
||||
}
|
||||
_ if config.searching_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.searching_block
|
||||
.as_ref()
|
||||
.expect("searching_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() =>
|
||||
{
|
||||
$table
|
||||
.search
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.scroll_home();
|
||||
if let Some(ref mut search) = $table.search {
|
||||
search.scroll_home();
|
||||
}
|
||||
true
|
||||
}
|
||||
_ if config.filtering_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.filtering_block
|
||||
.as_ref()
|
||||
.expect("filtering_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() =>
|
||||
{
|
||||
$table
|
||||
.filter
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.scroll_home();
|
||||
if let Some(ref mut filter) = $table.filter {
|
||||
filter.scroll_home();
|
||||
}
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
@@ -207,39 +183,27 @@ macro_rules! handle_table_events {
|
||||
true
|
||||
}
|
||||
_ if config.sorting_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.sorting_block
|
||||
.as_ref()
|
||||
.expect("sorting_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() =>
|
||||
{
|
||||
$table
|
||||
.sort
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.scroll_to_bottom();
|
||||
if let Some(ref mut sort) = $table.sort {
|
||||
sort.scroll_to_bottom();
|
||||
}
|
||||
true
|
||||
}
|
||||
_ if config.searching_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.searching_block
|
||||
.as_ref()
|
||||
.expect("searching_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() =>
|
||||
{
|
||||
$table
|
||||
.search
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.reset_offset();
|
||||
if let Some(ref mut search) = $table.search {
|
||||
search.reset_offset();
|
||||
}
|
||||
true
|
||||
}
|
||||
_ if config.filtering_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.filtering_block
|
||||
.as_ref()
|
||||
.expect("filtering_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() =>
|
||||
{
|
||||
$table
|
||||
.filter
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.reset_offset();
|
||||
if let Some(ref mut filter) = $table.filter {
|
||||
filter.reset_offset();
|
||||
}
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
@@ -249,53 +213,36 @@ macro_rules! handle_table_events {
|
||||
fn [<handle_ $name _table_left_right>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||
match $self.app.get_current_route() {
|
||||
_ if config.searching_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.searching_block
|
||||
.as_ref()
|
||||
.expect("searching_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() =>
|
||||
{
|
||||
$crate::handle_text_box_left_right_keys!(
|
||||
$self,
|
||||
$self.key,
|
||||
$table.search.as_mut().unwrap()
|
||||
);
|
||||
if let Some(ref mut search) = $table.search {
|
||||
$crate::handle_text_box_left_right_keys!($self, $self.key, search);
|
||||
}
|
||||
true
|
||||
}
|
||||
_ if config.filtering_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.filtering_block
|
||||
.as_ref()
|
||||
.expect("filtering_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() =>
|
||||
{
|
||||
$crate::handle_text_box_left_right_keys!(
|
||||
$self,
|
||||
$self.key,
|
||||
$table.filter.as_mut().unwrap()
|
||||
);
|
||||
if let Some(ref mut filter) = $table.filter {
|
||||
$crate::handle_text_box_left_right_keys!($self, $self.key, filter);
|
||||
}
|
||||
true
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn [<handle _$name _table_submit>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||
fn [<handle_ $name _table_submit>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||
match $self.app.get_current_route() {
|
||||
_ if config.sorting_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.sorting_block
|
||||
.as_ref()
|
||||
.expect("sorting_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() =>
|
||||
{
|
||||
if let Some(sort_by_fn) = config.sort_by_fn {
|
||||
$table.items.sort_by(sort_by_fn);
|
||||
}
|
||||
|
||||
$table.apply_sorting();
|
||||
$self.app.pop_navigation_stack();
|
||||
|
||||
true
|
||||
}
|
||||
_ if config.searching_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.searching_block
|
||||
.as_ref()
|
||||
.expect("searching_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap() =>
|
||||
{
|
||||
$self.app.pop_navigation_stack();
|
||||
$self.app.ignore_special_keys_for_textbox_input = false;
|
||||
@@ -318,9 +265,7 @@ macro_rules! handle_table_events {
|
||||
true
|
||||
}
|
||||
_ if config.filtering_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.filtering_block
|
||||
.as_ref()
|
||||
.expect("filtering_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap() =>
|
||||
{
|
||||
$self.app.pop_navigation_stack();
|
||||
$self.app.ignore_special_keys_for_textbox_input = false;
|
||||
@@ -349,21 +294,15 @@ macro_rules! handle_table_events {
|
||||
fn [<handle_ $name _table_esc>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||
match $self.app.get_current_route() {
|
||||
_ if config.sorting_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.sorting_block
|
||||
.as_ref()
|
||||
.expect("sorting_block must be configured for this table") =>
|
||||
&& $self.app.get_current_route() == *config.sorting_block.as_ref().unwrap() =>
|
||||
{
|
||||
$self.app.pop_navigation_stack();
|
||||
true
|
||||
}
|
||||
_ if (config.searching_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.searching_block
|
||||
.as_ref()
|
||||
.expect("searching_block must be configured for this table"))
|
||||
&& $self.app.get_current_route() == *config.searching_block.as_ref().unwrap())
|
||||
|| (config.search_error_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.search_error_block
|
||||
.as_ref()
|
||||
.expect("search_error_block must be configured for this table")) =>
|
||||
&& $self.app.get_current_route() == *config.search_error_block.as_ref().unwrap()) =>
|
||||
{
|
||||
$self.app.pop_navigation_stack();
|
||||
$table.reset_search();
|
||||
@@ -371,13 +310,9 @@ macro_rules! handle_table_events {
|
||||
true
|
||||
}
|
||||
_ if (config.filtering_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.filtering_block
|
||||
.as_ref()
|
||||
.expect("filtering_block must be configured for this table"))
|
||||
&& $self.app.get_current_route() == *config.filtering_block.as_ref().unwrap())
|
||||
|| (config.filter_error_block.is_some()
|
||||
&& $self.app.get_current_route() == *config.filter_error_block
|
||||
.as_ref()
|
||||
.expect("filter_error_block must be configured for this table")) =>
|
||||
&& $self.app.get_current_route() == *config.filter_error_block.as_ref().unwrap()) =>
|
||||
{
|
||||
$self.app.pop_navigation_stack();
|
||||
$table.reset_filter();
|
||||
@@ -394,68 +329,67 @@ macro_rules! handle_table_events {
|
||||
}
|
||||
}
|
||||
|
||||
fn [<handle_ $name _table_filter_key>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||
if matches!($self.app.get_current_route(), _ if config.table_block == $self.app.get_current_route()) {
|
||||
$self
|
||||
.app
|
||||
.push_navigation_stack(config.filtering_block.expect("Filtering block is undefined").into());
|
||||
$table.reset_filter();
|
||||
$table.filter = Some($crate::models::HorizontallyScrollableText::default());
|
||||
$self.app.ignore_special_keys_for_textbox_input = true;
|
||||
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn [<handle_ $name _table_search_key>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||
if matches!($self.app.get_current_route(), _ if config.table_block == $self.app.get_current_route()) {
|
||||
$self
|
||||
.app
|
||||
.push_navigation_stack(config.searching_block.expect("Searching block is undefined"));
|
||||
$table.search = Some($crate::models::HorizontallyScrollableText::default());
|
||||
$self.app.ignore_special_keys_for_textbox_input = true;
|
||||
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn [<handle_ $name _table_sort_key>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||
if matches!($self.app.get_current_route(), _ if config.table_block == $self.app.get_current_route()) {
|
||||
$table.sorting(
|
||||
config
|
||||
.sort_options
|
||||
.as_ref()
|
||||
.expect("Sort options are undefined")
|
||||
.clone(),
|
||||
);
|
||||
$self
|
||||
.app
|
||||
.push_navigation_stack(config.sorting_block.expect("Sorting block is undefined"));
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn [<handle_ $name _table_search_box_input>](&mut $self) -> bool {
|
||||
$crate::handle_text_box_keys!(
|
||||
$self,
|
||||
$self.key,
|
||||
$table.search.as_mut().unwrap()
|
||||
);
|
||||
let Some(ref mut search) = $table.search else {
|
||||
return false;
|
||||
};
|
||||
|
||||
$crate::handle_text_box_keys!($self, $self.key, search);
|
||||
true
|
||||
}
|
||||
|
||||
fn [<handle_ $name _table_filter_box_input>](&mut $self) -> bool {
|
||||
$crate::handle_text_box_keys!(
|
||||
$self,
|
||||
$self.key,
|
||||
$table.filter.as_mut().unwrap()
|
||||
);
|
||||
let Some(ref mut filter) = $table.filter else {
|
||||
return false;
|
||||
};
|
||||
|
||||
$crate::handle_text_box_keys!($self, $self.key, filter);
|
||||
true
|
||||
}
|
||||
|
||||
fn [<handle_ $name _table_filter_key>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||
if $self.app.get_current_route() != config.table_block {
|
||||
return false;
|
||||
}
|
||||
|
||||
let Some(ref filtering_block) = config.filtering_block else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let filter = $crate::models::HorizontallyScrollableText::default();
|
||||
$table.filter = Some(filter);
|
||||
$self.app.push_navigation_stack(*filtering_block);
|
||||
$self.app.ignore_special_keys_for_textbox_input = true;
|
||||
true
|
||||
}
|
||||
|
||||
fn [<handle_ $name _table_search_key>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||
if $self.app.get_current_route() != config.table_block {
|
||||
return false;
|
||||
}
|
||||
|
||||
let Some(ref searching_block) = config.searching_block else {
|
||||
return false;
|
||||
};
|
||||
|
||||
let search = $crate::models::HorizontallyScrollableText::default();
|
||||
$table.search = Some(search);
|
||||
$self.app.push_navigation_stack(*searching_block);
|
||||
$self.app.ignore_special_keys_for_textbox_input = true;
|
||||
true
|
||||
}
|
||||
|
||||
fn [<handle_ $name _table_sort_key>](&mut $self, config: $crate::handlers::table_handler::TableHandlingConfig<$row>) -> bool {
|
||||
if $self.app.get_current_route() != config.table_block {
|
||||
return false;
|
||||
}
|
||||
|
||||
let (Some(ref sorting_block), Some(sort_options)) = (config.sorting_block, config.sort_options.as_ref()) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
$table.sorting(sort_options.clone());
|
||||
$self.app.push_navigation_stack(*sorting_block);
|
||||
true
|
||||
}
|
||||
}
|
||||
@@ -467,17 +401,16 @@ where
|
||||
T: Clone + PartialEq + Eq + Debug + Default,
|
||||
{
|
||||
pub fn new(table_block: Route) -> Self {
|
||||
TableHandlingConfig {
|
||||
Self {
|
||||
table_block,
|
||||
sorting_block: None,
|
||||
sort_options: None,
|
||||
sort_by_fn: None,
|
||||
searching_block: None,
|
||||
search_error_block: None,
|
||||
search_field_fn: None,
|
||||
filtering_block: None,
|
||||
filter_error_block: None,
|
||||
filter_field_fn: None,
|
||||
table_block,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ mod tests {
|
||||
fn handle(&mut self) {
|
||||
let movie_table_handling_config = TableHandlingConfig::new(ActiveRadarrBlock::Movies.into())
|
||||
.sorting_block(ActiveRadarrBlock::MoviesSortPrompt.into())
|
||||
.sort_by_fn(|a: &Movie, b: &Movie| a.id.cmp(&b.id))
|
||||
.sort_options(sort_options())
|
||||
.searching_block(ActiveRadarrBlock::SearchMovie.into())
|
||||
.search_error_block(ActiveRadarrBlock::SearchMovieError.into())
|
||||
|
||||
+61
-210
@@ -50,151 +50,46 @@ where
|
||||
T: Clone + PartialEq + Eq + Debug,
|
||||
{
|
||||
fn scroll_down(&mut self) {
|
||||
if let Some(filtered_items) = self.filtered_items.as_ref() {
|
||||
if filtered_items.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
match self
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.selected()
|
||||
{
|
||||
Some(i) => {
|
||||
if i >= filtered_items.len() - 1 {
|
||||
self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.select_first();
|
||||
} else {
|
||||
self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.select_next();
|
||||
}
|
||||
}
|
||||
None => self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.select_first(),
|
||||
};
|
||||
|
||||
let items_len = self.active_items().len();
|
||||
if items_len == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.items.is_empty() {
|
||||
return;
|
||||
let state = self.active_state_mut();
|
||||
match state.selected() {
|
||||
Some(i) if i >= items_len - 1 => state.select_first(),
|
||||
Some(_) => state.select_next(),
|
||||
None => state.select_first(),
|
||||
}
|
||||
|
||||
match self.state.selected() {
|
||||
Some(i) => {
|
||||
if i >= self.items.len() - 1 {
|
||||
self.state.select_first();
|
||||
} else {
|
||||
self.state.select_next();
|
||||
}
|
||||
}
|
||||
None => self.state.select_first(),
|
||||
};
|
||||
}
|
||||
|
||||
fn scroll_up(&mut self) {
|
||||
if let Some(filtered_items) = self.filtered_items.as_ref() {
|
||||
if filtered_items.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
match self
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.selected()
|
||||
{
|
||||
Some(i) => {
|
||||
if i == 0 {
|
||||
self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.select(Some(filtered_items.len() - 1));
|
||||
} else {
|
||||
self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.select_previous();
|
||||
}
|
||||
}
|
||||
None => self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.select_first(),
|
||||
};
|
||||
|
||||
let items_len = self.active_items().len();
|
||||
if items_len == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.items.is_empty() {
|
||||
return;
|
||||
let state = self.active_state_mut();
|
||||
match state.selected() {
|
||||
Some(0) => state.select(Some(items_len - 1)),
|
||||
Some(_) => state.select_previous(),
|
||||
None => state.select_first(),
|
||||
}
|
||||
|
||||
match self.state.selected() {
|
||||
Some(i) => {
|
||||
if i == 0 {
|
||||
self.state.select(Some(self.items.len() - 1));
|
||||
} else {
|
||||
self.state.select_previous();
|
||||
}
|
||||
}
|
||||
None => self.state.select_first(),
|
||||
};
|
||||
}
|
||||
|
||||
fn scroll_to_top(&mut self) {
|
||||
if let Some(filtered_items) = self.filtered_items.as_ref() {
|
||||
if filtered_items.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.select_first();
|
||||
if self.active_items().is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.items.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.state.select_first();
|
||||
self.active_state_mut().select_first();
|
||||
}
|
||||
|
||||
fn scroll_to_bottom(&mut self) {
|
||||
if let Some(filtered_items) = self.filtered_items.as_ref() {
|
||||
if filtered_items.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.select(Some(filtered_items.len() - 1));
|
||||
let items_len = self.active_items().len();
|
||||
if items_len == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.items.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.state.select(Some(self.items.len() - 1));
|
||||
self.active_state_mut().select(Some(items_len - 1));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -203,89 +98,56 @@ where
|
||||
T: Clone + PartialEq + Eq + Debug,
|
||||
{
|
||||
fn page_down(&mut self) {
|
||||
if let Some(filtered_items) = self.filtered_items.as_ref() {
|
||||
if filtered_items.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
match self
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.selected()
|
||||
{
|
||||
Some(i) => {
|
||||
self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.select(Some(i.saturating_add(20) % (filtered_items.len() - 1)));
|
||||
}
|
||||
None => self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.select_first(),
|
||||
};
|
||||
|
||||
let items_len = self.active_items().len();
|
||||
if items_len == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.items.is_empty() {
|
||||
return;
|
||||
let state = self.active_state_mut();
|
||||
match state.selected() {
|
||||
Some(i) => state.select(Some(i.saturating_add(20) % (items_len - 1))),
|
||||
None => state.select_first(),
|
||||
}
|
||||
|
||||
match self.state.selected() {
|
||||
Some(i) => {
|
||||
self
|
||||
.state
|
||||
.select(Some(i.saturating_add(20) % (self.items.len() - 1)));
|
||||
}
|
||||
None => self.state.select_first(),
|
||||
};
|
||||
}
|
||||
|
||||
fn page_up(&mut self) {
|
||||
if let Some(filtered_items) = self.filtered_items.as_ref() {
|
||||
if filtered_items.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
match self
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.selected()
|
||||
{
|
||||
Some(i) => {
|
||||
let len = filtered_items.len() - 1;
|
||||
self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.select(Some((i + len - (20 % len)) % len));
|
||||
}
|
||||
None => self
|
||||
.filtered_state
|
||||
.as_mut()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.select_last(),
|
||||
};
|
||||
|
||||
let items_len = self.active_items().len();
|
||||
if items_len == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.items.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
match self.state.selected() {
|
||||
let state = self.active_state_mut();
|
||||
match state.selected() {
|
||||
Some(i) => {
|
||||
let len = self.items.len() - 1;
|
||||
self.state.select(Some((i + len - (20 % len)) % len));
|
||||
let len = items_len - 1;
|
||||
state.select(Some((i + len - (20 % len)) % len));
|
||||
}
|
||||
None => self.state.select_last(),
|
||||
};
|
||||
None => state.select_last(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> StatefulTable<T>
|
||||
where
|
||||
T: Clone + PartialEq + Eq + Debug,
|
||||
{
|
||||
fn active_items(&self) -> &[T] {
|
||||
self
|
||||
.filtered_items
|
||||
.as_ref()
|
||||
.map_or(&self.items[..], |items| &items[..])
|
||||
}
|
||||
|
||||
fn active_state_mut(&mut self) -> &mut TableState {
|
||||
if let Some(ref mut filtered_state) = self.filtered_state {
|
||||
filtered_state
|
||||
} else {
|
||||
&mut self.state
|
||||
}
|
||||
}
|
||||
|
||||
fn active_state(&self) -> &TableState {
|
||||
self.filtered_state.as_ref().unwrap_or(&self.state)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,24 +180,13 @@ where
|
||||
}
|
||||
|
||||
pub fn select_index(&mut self, index: Option<usize>) {
|
||||
if let Some(filtered_state) = &mut self.filtered_state {
|
||||
filtered_state.select(index);
|
||||
} else {
|
||||
self.state.select(index);
|
||||
}
|
||||
self.active_state_mut().select(index);
|
||||
}
|
||||
|
||||
pub fn current_selection(&self) -> &T {
|
||||
if let Some(filtered_items) = &self.filtered_items {
|
||||
&filtered_items[self
|
||||
.filtered_state
|
||||
.as_ref()
|
||||
.expect("filtered_state must exist when filtered_items exists")
|
||||
.selected()
|
||||
.unwrap_or(0)]
|
||||
} else {
|
||||
&self.items[self.state.selected().unwrap_or(0)]
|
||||
}
|
||||
let items = self.active_items();
|
||||
let index = self.active_state().selected().unwrap_or(0);
|
||||
&items[index]
|
||||
}
|
||||
|
||||
pub fn sorting(&mut self, sort_options: Vec<SortOption<T>>) {
|
||||
|
||||
+3
-3
@@ -6,10 +6,10 @@ use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use anyhow::Result;
|
||||
use anyhow::{anyhow, Context};
|
||||
use anyhow::{Context, anyhow};
|
||||
use colored::Colorize;
|
||||
use indicatif::{ProgressBar, ProgressStyle};
|
||||
use log::{error, LevelFilter};
|
||||
use log::{LevelFilter, error};
|
||||
use log4rs::append::file::FileAppender;
|
||||
use log4rs::config::{Appender, Root};
|
||||
use log4rs::encode::pattern::PatternEncoder;
|
||||
@@ -18,7 +18,7 @@ use reqwest::{Certificate, Client};
|
||||
use tokio::sync::Mutex;
|
||||
use tokio_util::sync::CancellationToken;
|
||||
|
||||
use crate::app::{log_and_print_error, App, AppConfig};
|
||||
use crate::app::{App, AppConfig, log_and_print_error};
|
||||
use crate::cli::{self, Command};
|
||||
use crate::network::Network;
|
||||
use crate::ui::theme::ThemeDefinitionsWrapper;
|
||||
|
||||
Reference in New Issue
Block a user