From 4cad9e1755540152870b3d11253fb0acee925b32 Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Thu, 25 Jun 2026 12:35:51 -0600 Subject: [PATCH 1/9] docs: Improved the README to demonstrate what a truly minimal configuration looks like for each service and explain the "reasonable defaults" [#61] --- README.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2211557..73067db 100644 --- a/README.md +++ b/README.md @@ -338,7 +338,38 @@ $ managarr radarr list movies | jq '.[] | select(.title == "Ad Astra") | .id' # Configuration Managarr assumes reasonable defaults to connect to each service (i.e. Radarr is on localhost:7878), -but all servers will require you to input the API token. +but all servers will require you to input the API token. This means that for each Servarr you configure, +if you define only the `api_token`, Managarr will assume the Servarr is running on `localhost` and on the +default port for that respective service. That is: + +| Servarr | Default Host | Default Port | +|---------|--------------|--------------| +| Radarr | `localhost` | 7878 | +| Sonarr | `localhost` | 8989 | +| Lidarr | `localhost` | 8686 | + +> [!TIP] +> In general, all Servarrs store their API tokens under Settings -> General -> Security -> API Key in their web UIs. + +## Minimum Configuration Requirements +The following configuration file will connect to each Servarr running on localhost with their default ports. The only +requirement for each is the specification of an API token. + +```yaml +radarr: + # Connect to Radarr running on localhost:7878 + - api_token: + +sonarr: + # Connect to sonarr running on localhost:8989 + - api_token: + +lidarr: + # Connect to lidarr running on localhost:8686 + - api_token: +``` + +## Configuration File Location The configuration file is located somewhere different for each OS, so run the following command to print out the default location of the `managarr` configuration file for your system: From 03d134bec923a93b1b4d708d8fe3144cfe13fc56 Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Thu, 25 Jun 2026 13:18:43 -0600 Subject: [PATCH 2/9] refactor: Refactored several usages of sort_by_key and match guards to utilize newer Rust version APIs --- src/handlers/handlers_tests.rs | 8 ++--- .../indexers/edit_indexer_handler.rs | 17 +++++----- .../indexers/edit_indexer_settings_handler.rs | 8 ++--- .../library/add_artist_handler.rs | 15 ++++----- .../library/artist_details_handler.rs | 18 +++++----- .../library/edit_artist_handler.rs | 17 +++++----- .../root_folders/add_root_folder_handler.rs | 19 +++++------ src/handlers/mod.rs | 4 +-- .../collections/edit_collection_handler.rs | 19 +++++------ .../indexers/edit_indexer_handler.rs | 17 +++++----- .../indexers/edit_indexer_settings_handler.rs | 27 ++++++++------- .../library/add_movie_handler.rs | 15 ++++----- .../library/edit_movie_handler.rs | 17 +++++----- .../indexers/edit_indexer_handler.rs | 17 +++++----- .../indexers/edit_indexer_settings_handler.rs | 8 ++--- .../library/add_series_handler.rs | 15 ++++----- .../library/edit_series_handler.rs | 17 +++++----- src/handlers/table_handler_tests.rs | 2 +- src/network/lidarr_network/blocklist/mod.rs | 2 +- src/network/lidarr_network/history/mod.rs | 2 +- .../lidarr_network/library/albums/mod.rs | 4 +-- .../lidarr_network/library/artists/mod.rs | 4 +-- .../lidarr_network/library/tracks/mod.rs | 4 +-- src/network/lidarr_network/system/mod.rs | 7 ++-- src/network/radarr_network/blocklist/mod.rs | 2 +- src/network/radarr_network/collections/mod.rs | 2 +- src/network/radarr_network/history/mod.rs | 2 +- src/network/radarr_network/library/mod.rs | 2 +- src/network/radarr_network/system/mod.rs | 7 ++-- src/network/sonarr_network/blocklist/mod.rs | 2 +- src/network/sonarr_network/history/mod.rs | 2 +- .../sonarr_network/library/episodes/mod.rs | 4 +-- .../sonarr_network/library/seasons/mod.rs | 2 +- .../sonarr_network/library/series/mod.rs | 4 +-- src/network/sonarr_network/system/mod.rs | 7 ++-- src/ui/lidarr_ui/indexers/mod.rs | 33 +++++++------------ src/ui/lidarr_ui/system/mod.rs | 9 +++-- src/ui/radarr_ui/indexers/mod.rs | 33 +++++++------------ src/ui/radarr_ui/system/mod.rs | 5 ++- src/ui/sonarr_ui/indexers/mod.rs | 33 +++++++------------ src/ui/sonarr_ui/system/mod.rs | 9 +++-- src/ui/widgets/managarr_table.rs | 16 ++++----- 42 files changed, 202 insertions(+), 255 deletions(-) diff --git a/src/handlers/handlers_tests.rs b/src/handlers/handlers_tests.rs index c436db9..9ce9708 100644 --- a/src/handlers/handlers_tests.rs +++ b/src/handlers/handlers_tests.rs @@ -231,8 +231,8 @@ mod tests { let expected_keybinding_items = Vec::from(SERVARR_CONTEXT_CLUES) .iter() .map(|(key, desc)| { - let (key, alt_key) = if key.alt.is_some() { - (key.key.to_string(), key.alt.as_ref().unwrap().to_string()) + let (key, alt_key) = if let Some(key1) = key.alt { + (key.key.to_string(), key1.to_string()) } else { (key.key.to_string(), String::new()) }; @@ -338,8 +338,8 @@ mod tests { } fn context_clue_to_keybinding_item(key: &KeyBinding, desc: &&str) -> KeybindingItem { - let (key, alt_key) = if key.alt.is_some() { - (key.key.to_string(), key.alt.as_ref().unwrap().to_string()) + let (key, alt_key) = if let Some(key1) = key.alt { + (key.key.to_string(), key1.to_string()) } else { (key.key.to_string(), String::new()) }; diff --git a/src/handlers/lidarr_handlers/indexers/edit_indexer_handler.rs b/src/handlers/lidarr_handlers/indexers/edit_indexer_handler.rs index a1aea6e..39cbfc6 100644 --- a/src/handlers/lidarr_handlers/indexers/edit_indexer_handler.rs +++ b/src/handlers/lidarr_handlers/indexers/edit_indexer_handler.rs @@ -506,18 +506,17 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for EditIndexerHandler<' .tags ); } - ActiveLidarrBlock::EditIndexerPrompt => { + ActiveLidarrBlock::EditIndexerPrompt if self.app.data.lidarr_data.selected_block.get_active_block() == ActiveLidarrBlock::EditIndexerConfirmPrompt - && matches_key!(confirm, self.key) - { - self.app.data.lidarr_data.prompt_confirm = true; - self.app.data.lidarr_data.prompt_confirm_action = - Some(LidarrEvent::EditIndexer(self.build_edit_indexer_params())); - self.app.should_refresh = true; + && matches_key!(confirm, self.key) => + { + self.app.data.lidarr_data.prompt_confirm = true; + self.app.data.lidarr_data.prompt_confirm_action = + Some(LidarrEvent::EditIndexer(self.build_edit_indexer_params())); + self.app.should_refresh = true; - self.app.pop_navigation_stack(); - } + self.app.pop_navigation_stack(); } _ => (), } diff --git a/src/handlers/lidarr_handlers/indexers/edit_indexer_settings_handler.rs b/src/handlers/lidarr_handlers/indexers/edit_indexer_settings_handler.rs index 0de6cc1..d149133 100644 --- a/src/handlers/lidarr_handlers/indexers/edit_indexer_settings_handler.rs +++ b/src/handlers/lidarr_handlers/indexers/edit_indexer_settings_handler.rs @@ -106,10 +106,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for IndexerSettingsHandl indexer_settings.maximum_size -= 1; } } - ActiveLidarrBlock::IndexerSettingsRssSyncIntervalInput => { - if indexer_settings.rss_sync_interval > 0 { - indexer_settings.rss_sync_interval -= 1; - } + ActiveLidarrBlock::IndexerSettingsRssSyncIntervalInput + if indexer_settings.rss_sync_interval > 0 => + { + indexer_settings.rss_sync_interval -= 1; } _ => (), } diff --git a/src/handlers/lidarr_handlers/library/add_artist_handler.rs b/src/handlers/lidarr_handlers/library/add_artist_handler.rs index 7f4e63b..6c1a84e 100644 --- a/src/handlers/lidarr_handlers/library/add_artist_handler.rs +++ b/src/handlers/lidarr_handlers/library/add_artist_handler.rs @@ -591,16 +591,15 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for AddArtistHandler<'a, .tags ) } - ActiveLidarrBlock::AddArtistPrompt => { + ActiveLidarrBlock::AddArtistPrompt if self.app.data.lidarr_data.selected_block.get_active_block() == ActiveLidarrBlock::AddArtistConfirmPrompt - && matches_key!(confirm, key) - { - self.app.data.lidarr_data.prompt_confirm = true; - self.app.data.lidarr_data.prompt_confirm_action = - Some(LidarrEvent::AddArtist(self.build_add_artist_body())); - self.app.pop_navigation_stack(); - } + && matches_key!(confirm, key) => + { + self.app.data.lidarr_data.prompt_confirm = true; + self.app.data.lidarr_data.prompt_confirm_action = + Some(LidarrEvent::AddArtist(self.build_add_artist_body())); + self.app.pop_navigation_stack(); } _ => (), } diff --git a/src/handlers/lidarr_handlers/library/artist_details_handler.rs b/src/handlers/lidarr_handlers/library/artist_details_handler.rs index 6911ff8..fa5fd77 100644 --- a/src/handlers/lidarr_handlers/library/artist_details_handler.rs +++ b/src/handlers/lidarr_handlers/library/artist_details_handler.rs @@ -293,16 +293,16 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for ArtistDetailsHandler self.app.data.lidarr_data.selected_block = BlockSelectionState::new(EDIT_ARTIST_SELECTION_BLOCKS); } - _ if matches_key!(toggle_monitoring, key) => { - if !self.app.data.lidarr_data.albums.is_empty() { - self.app.data.lidarr_data.prompt_confirm = true; - self.app.data.lidarr_data.prompt_confirm_action = - Some(LidarrEvent::ToggleAlbumMonitoring(self.extract_album_id())); + _ if matches_key!(toggle_monitoring, key) + && !self.app.data.lidarr_data.albums.is_empty() => + { + self.app.data.lidarr_data.prompt_confirm = true; + self.app.data.lidarr_data.prompt_confirm_action = + Some(LidarrEvent::ToggleAlbumMonitoring(self.extract_album_id())); - self - .app - .pop_and_push_navigation_stack(self.active_lidarr_block.into()); - } + self + .app + .pop_and_push_navigation_stack(self.active_lidarr_block.into()); } _ => (), }, diff --git a/src/handlers/lidarr_handlers/library/edit_artist_handler.rs b/src/handlers/lidarr_handlers/library/edit_artist_handler.rs index 194a5e0..1d40941 100644 --- a/src/handlers/lidarr_handlers/library/edit_artist_handler.rs +++ b/src/handlers/lidarr_handlers/library/edit_artist_handler.rs @@ -428,18 +428,17 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for EditArtistHandler<'a .tags ) } - ActiveLidarrBlock::EditArtistPrompt => { + ActiveLidarrBlock::EditArtistPrompt if self.app.data.lidarr_data.selected_block.get_active_block() == ActiveLidarrBlock::EditArtistConfirmPrompt - && matches_key!(confirm, key) - { - self.app.data.lidarr_data.prompt_confirm = true; - self.app.data.lidarr_data.prompt_confirm_action = - Some(LidarrEvent::EditArtist(self.build_edit_artist_params())); - self.app.should_refresh = true; + && matches_key!(confirm, key) => + { + self.app.data.lidarr_data.prompt_confirm = true; + self.app.data.lidarr_data.prompt_confirm_action = + Some(LidarrEvent::EditArtist(self.build_edit_artist_params())); + self.app.should_refresh = true; - self.app.pop_navigation_stack(); - } + self.app.pop_navigation_stack(); } _ => (), } diff --git a/src/handlers/lidarr_handlers/root_folders/add_root_folder_handler.rs b/src/handlers/lidarr_handlers/root_folders/add_root_folder_handler.rs index b6d1bf7..ea8f250 100644 --- a/src/handlers/lidarr_handlers/root_folders/add_root_folder_handler.rs +++ b/src/handlers/lidarr_handlers/root_folders/add_root_folder_handler.rs @@ -505,19 +505,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveLidarrBlock> for AddRootFolderHandler .tags ) } - ActiveLidarrBlock::AddRootFolderPrompt => { + ActiveLidarrBlock::AddRootFolderPrompt if self.app.data.lidarr_data.selected_block.get_active_block() == ActiveLidarrBlock::AddRootFolderConfirmPrompt - && matches_key!(confirm, key) - { - self.app.data.lidarr_data.prompt_confirm = true; - self.app.data.lidarr_data.prompt_confirm_action = Some(LidarrEvent::AddRootFolder( - self.build_add_root_folder_body(), - )); - self.app.should_refresh = true; + && matches_key!(confirm, key) => + { + self.app.data.lidarr_data.prompt_confirm = true; + self.app.data.lidarr_data.prompt_confirm_action = Some(LidarrEvent::AddRootFolder( + self.build_add_root_folder_body(), + )); + self.app.should_refresh = true; - self.app.pop_navigation_stack(); - } + self.app.pop_navigation_stack(); } _ => (), } diff --git a/src/handlers/mod.rs b/src/handlers/mod.rs index 375959c..bf72eb0 100644 --- a/src/handlers/mod.rs +++ b/src/handlers/mod.rs @@ -139,8 +139,8 @@ pub fn handle_events(key: Key, app: &mut App<'_>) { pub fn populate_keymapping_table(app: &mut App<'_>) { let context_clue_to_keybinding_item = |key: &KeyBinding, desc: &&str| { - let (key, alt_key) = if key.alt.is_some() { - (key.key.to_string(), key.alt.as_ref().unwrap().to_string()) + let (key, alt_key) = if let Some(key1) = key.alt { + (key.key.to_string(), key1.to_string()) } else { (key.key.to_string(), String::new()) }; diff --git a/src/handlers/radarr_handlers/collections/edit_collection_handler.rs b/src/handlers/radarr_handlers/collections/edit_collection_handler.rs index fe34986..a2d28c6 100644 --- a/src/handlers/radarr_handlers/collections/edit_collection_handler.rs +++ b/src/handlers/radarr_handlers/collections/edit_collection_handler.rs @@ -354,19 +354,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditCollectionHandle .path ) } - ActiveRadarrBlock::EditCollectionPrompt => { + ActiveRadarrBlock::EditCollectionPrompt if self.app.data.radarr_data.selected_block.get_active_block() == ActiveRadarrBlock::EditCollectionConfirmPrompt - && matches_key!(confirm, key) - { - self.app.data.radarr_data.prompt_confirm = true; - self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditCollection( - self.build_edit_collection_params(), - )); - self.app.should_refresh = true; + && matches_key!(confirm, key) => + { + self.app.data.radarr_data.prompt_confirm = true; + self.app.data.radarr_data.prompt_confirm_action = Some(RadarrEvent::EditCollection( + self.build_edit_collection_params(), + )); + self.app.should_refresh = true; - self.app.pop_navigation_stack(); - } + self.app.pop_navigation_stack(); } _ => (), } diff --git a/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs b/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs index d83ab1b..2862a74 100644 --- a/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs +++ b/src/handlers/radarr_handlers/indexers/edit_indexer_handler.rs @@ -507,18 +507,17 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditIndexerHandler<' .tags ); } - ActiveRadarrBlock::EditIndexerPrompt => { + ActiveRadarrBlock::EditIndexerPrompt if self.app.data.radarr_data.selected_block.get_active_block() == ActiveRadarrBlock::EditIndexerConfirmPrompt - && matches_key!(confirm, self.key) - { - self.app.data.radarr_data.prompt_confirm = true; - self.app.data.radarr_data.prompt_confirm_action = - Some(RadarrEvent::EditIndexer(self.build_edit_indexer_params())); - self.app.should_refresh = true; + && matches_key!(confirm, self.key) => + { + self.app.data.radarr_data.prompt_confirm = true; + self.app.data.radarr_data.prompt_confirm_action = + Some(RadarrEvent::EditIndexer(self.build_edit_indexer_params())); + self.app.should_refresh = true; - self.app.pop_navigation_stack(); - } + self.app.pop_navigation_stack(); } _ => (), } diff --git a/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs b/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs index 9145529..439bb2c 100644 --- a/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs +++ b/src/handlers/radarr_handlers/indexers/edit_indexer_settings_handler.rs @@ -114,10 +114,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl ActiveRadarrBlock::IndexerSettingsAvailabilityDelayInput => { indexer_settings.availability_delay -= 1; } - ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput => { - if indexer_settings.rss_sync_interval > 0 { - indexer_settings.rss_sync_interval -= 1; - } + ActiveRadarrBlock::IndexerSettingsRssSyncIntervalInput + if indexer_settings.rss_sync_interval > 0 => + { + indexer_settings.rss_sync_interval -= 1; } _ => (), } @@ -272,19 +272,18 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for IndexerSettingsHandl .whitelisted_hardcoded_subs ) } - ActiveRadarrBlock::AllIndexerSettingsPrompt => { + ActiveRadarrBlock::AllIndexerSettingsPrompt if self.app.data.radarr_data.selected_block.get_active_block() == ActiveRadarrBlock::IndexerSettingsConfirmPrompt - && matches_key!(confirm, self.key) - { - self.app.data.radarr_data.prompt_confirm = true; - self.app.data.radarr_data.prompt_confirm_action = Some( - RadarrEvent::EditAllIndexerSettings(self.build_edit_indexer_settings_body()), - ); - self.app.should_refresh = true; + && matches_key!(confirm, self.key) => + { + self.app.data.radarr_data.prompt_confirm = true; + self.app.data.radarr_data.prompt_confirm_action = Some( + RadarrEvent::EditAllIndexerSettings(self.build_edit_indexer_settings_body()), + ); + self.app.should_refresh = true; - self.app.pop_navigation_stack(); - } + self.app.pop_navigation_stack(); } _ => (), } diff --git a/src/handlers/radarr_handlers/library/add_movie_handler.rs b/src/handlers/radarr_handlers/library/add_movie_handler.rs index 28609a7..895bc14 100644 --- a/src/handlers/radarr_handlers/library/add_movie_handler.rs +++ b/src/handlers/radarr_handlers/library/add_movie_handler.rs @@ -539,16 +539,15 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for AddMovieHandler<'a, .tags ) } - ActiveRadarrBlock::AddMoviePrompt => { + ActiveRadarrBlock::AddMoviePrompt if self.app.data.radarr_data.selected_block.get_active_block() == ActiveRadarrBlock::AddMovieConfirmPrompt - && matches_key!(confirm, key) - { - self.app.data.radarr_data.prompt_confirm = true; - self.app.data.radarr_data.prompt_confirm_action = - Some(RadarrEvent::AddMovie(self.build_add_movie_body())); - self.app.pop_navigation_stack(); - } + && matches_key!(confirm, key) => + { + self.app.data.radarr_data.prompt_confirm = true; + self.app.data.radarr_data.prompt_confirm_action = + Some(RadarrEvent::AddMovie(self.build_add_movie_body())); + self.app.pop_navigation_stack(); } _ => (), } diff --git a/src/handlers/radarr_handlers/library/edit_movie_handler.rs b/src/handlers/radarr_handlers/library/edit_movie_handler.rs index 593f08d..cd34fb4 100644 --- a/src/handlers/radarr_handlers/library/edit_movie_handler.rs +++ b/src/handlers/radarr_handlers/library/edit_movie_handler.rs @@ -376,18 +376,17 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveRadarrBlock> for EditMovieHandler<'a, .tags ) } - ActiveRadarrBlock::EditMoviePrompt => { + ActiveRadarrBlock::EditMoviePrompt if self.app.data.radarr_data.selected_block.get_active_block() == ActiveRadarrBlock::EditMovieConfirmPrompt - && matches_key!(confirm, key) - { - self.app.data.radarr_data.prompt_confirm = true; - self.app.data.radarr_data.prompt_confirm_action = - Some(RadarrEvent::EditMovie(self.build_edit_movie_params())); - self.app.should_refresh = true; + && matches_key!(confirm, key) => + { + self.app.data.radarr_data.prompt_confirm = true; + self.app.data.radarr_data.prompt_confirm_action = + Some(RadarrEvent::EditMovie(self.build_edit_movie_params())); + self.app.should_refresh = true; - self.app.pop_navigation_stack(); - } + self.app.pop_navigation_stack(); } _ => (), } diff --git a/src/handlers/sonarr_handlers/indexers/edit_indexer_handler.rs b/src/handlers/sonarr_handlers/indexers/edit_indexer_handler.rs index 8d1394f..552b09a 100644 --- a/src/handlers/sonarr_handlers/indexers/edit_indexer_handler.rs +++ b/src/handlers/sonarr_handlers/indexers/edit_indexer_handler.rs @@ -506,18 +506,17 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditIndexerHandler<' .tags ); } - ActiveSonarrBlock::EditIndexerPrompt => { + ActiveSonarrBlock::EditIndexerPrompt if self.app.data.sonarr_data.selected_block.get_active_block() == ActiveSonarrBlock::EditIndexerConfirmPrompt - && matches_key!(confirm, self.key) - { - self.app.data.sonarr_data.prompt_confirm = true; - self.app.data.sonarr_data.prompt_confirm_action = - Some(SonarrEvent::EditIndexer(self.build_edit_indexer_params())); - self.app.should_refresh = true; + && matches_key!(confirm, self.key) => + { + self.app.data.sonarr_data.prompt_confirm = true; + self.app.data.sonarr_data.prompt_confirm_action = + Some(SonarrEvent::EditIndexer(self.build_edit_indexer_params())); + self.app.should_refresh = true; - self.app.pop_navigation_stack(); - } + self.app.pop_navigation_stack(); } _ => (), } diff --git a/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler.rs b/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler.rs index a6e3bb0..a2f2611 100644 --- a/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler.rs +++ b/src/handlers/sonarr_handlers/indexers/edit_indexer_settings_handler.rs @@ -106,10 +106,10 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for IndexerSettingsHandl indexer_settings.maximum_size -= 1; } } - ActiveSonarrBlock::IndexerSettingsRssSyncIntervalInput => { - if indexer_settings.rss_sync_interval > 0 { - indexer_settings.rss_sync_interval -= 1; - } + ActiveSonarrBlock::IndexerSettingsRssSyncIntervalInput + if indexer_settings.rss_sync_interval > 0 => + { + indexer_settings.rss_sync_interval -= 1; } _ => (), } diff --git a/src/handlers/sonarr_handlers/library/add_series_handler.rs b/src/handlers/sonarr_handlers/library/add_series_handler.rs index 12af178..a13333e 100644 --- a/src/handlers/sonarr_handlers/library/add_series_handler.rs +++ b/src/handlers/sonarr_handlers/library/add_series_handler.rs @@ -606,16 +606,15 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for AddSeriesHandler<'a, .tags ) } - ActiveSonarrBlock::AddSeriesPrompt => { + ActiveSonarrBlock::AddSeriesPrompt if self.app.data.sonarr_data.selected_block.get_active_block() == ActiveSonarrBlock::AddSeriesConfirmPrompt - && matches_key!(confirm, key) - { - self.app.data.sonarr_data.prompt_confirm = true; - self.app.data.sonarr_data.prompt_confirm_action = - Some(SonarrEvent::AddSeries(self.build_add_series_body())); - self.app.pop_navigation_stack(); - } + && matches_key!(confirm, key) => + { + self.app.data.sonarr_data.prompt_confirm = true; + self.app.data.sonarr_data.prompt_confirm_action = + Some(SonarrEvent::AddSeries(self.build_add_series_body())); + self.app.pop_navigation_stack(); } _ => (), } diff --git a/src/handlers/sonarr_handlers/library/edit_series_handler.rs b/src/handlers/sonarr_handlers/library/edit_series_handler.rs index 4bd4d79..1b4dfbd 100644 --- a/src/handlers/sonarr_handlers/library/edit_series_handler.rs +++ b/src/handlers/sonarr_handlers/library/edit_series_handler.rs @@ -450,18 +450,17 @@ impl<'a, 'b> KeyEventHandler<'a, 'b, ActiveSonarrBlock> for EditSeriesHandler<'a .tags ) } - ActiveSonarrBlock::EditSeriesPrompt => { + ActiveSonarrBlock::EditSeriesPrompt if self.app.data.sonarr_data.selected_block.get_active_block() == ActiveSonarrBlock::EditSeriesConfirmPrompt - && matches_key!(confirm, key) - { - self.app.data.sonarr_data.prompt_confirm = true; - self.app.data.sonarr_data.prompt_confirm_action = - Some(SonarrEvent::EditSeries(self.build_edit_series_params())); - self.app.should_refresh = true; + && matches_key!(confirm, key) => + { + self.app.data.sonarr_data.prompt_confirm = true; + self.app.data.sonarr_data.prompt_confirm_action = + Some(SonarrEvent::EditSeries(self.build_edit_series_params())); + self.app.should_refresh = true; - self.app.pop_navigation_stack(); - } + self.app.pop_navigation_stack(); } _ => (), } diff --git a/src/handlers/table_handler_tests.rs b/src/handlers/table_handler_tests.rs index 0e3ff10..45dc7b4 100644 --- a/src/handlers/table_handler_tests.rs +++ b/src/handlers/table_handler_tests.rs @@ -893,7 +893,7 @@ mod tests { app.push_navigation_stack(ActiveRadarrBlock::MoviesSortPrompt.into()); let mut expected_vec = movies_vec(); - expected_vec.sort_by(|a, b| a.id.cmp(&b.id)); + expected_vec.sort_by_key(|a| a.id); expected_vec.reverse(); TableHandlerUnit::new( diff --git a/src/network/lidarr_network/blocklist/mod.rs b/src/network/lidarr_network/blocklist/mod.rs index 6f542e2..b38406e 100644 --- a/src/network/lidarr_network/blocklist/mod.rs +++ b/src/network/lidarr_network/blocklist/mod.rs @@ -82,7 +82,7 @@ impl Network<'_, '_> { Route::Lidarr(ActiveLidarrBlock::BlocklistSortPrompt, _) ) { let mut blocklist_vec: Vec = blocklist_resp.records; - blocklist_vec.sort_by(|a, b| a.id.cmp(&b.id)); + blocklist_vec.sort_by_key(|a| a.id); app.data.lidarr_data.blocklist.set_items(blocklist_vec); app.data.lidarr_data.blocklist.apply_sorting_toggle(false); } diff --git a/src/network/lidarr_network/history/mod.rs b/src/network/lidarr_network/history/mod.rs index de6a069..f37d876 100644 --- a/src/network/lidarr_network/history/mod.rs +++ b/src/network/lidarr_network/history/mod.rs @@ -31,7 +31,7 @@ impl Network<'_, '_> { Route::Lidarr(ActiveLidarrBlock::HistorySortPrompt, _) ) { let mut history_vec = history_response.records; - history_vec.sort_by(|a, b| a.id.cmp(&b.id)); + history_vec.sort_by_key(|a| a.id); app.data.lidarr_data.history.set_items(history_vec); app.data.lidarr_data.history.apply_sorting_toggle(false); } diff --git a/src/network/lidarr_network/library/albums/mod.rs b/src/network/lidarr_network/library/albums/mod.rs index d99f1c5..5204b0a 100644 --- a/src/network/lidarr_network/library/albums/mod.rs +++ b/src/network/lidarr_network/library/albums/mod.rs @@ -33,7 +33,7 @@ impl Network<'_, '_> { self .handle_request::<(), Vec>(request_props, |mut albums_vec, mut app| { - albums_vec.sort_by(|a, b| a.id.cmp(&b.id)); + albums_vec.sort_by_key(|a| a.id); app.data.lidarr_data.albums.set_items(albums_vec); }) .await @@ -89,7 +89,7 @@ impl Network<'_, '_> { .get_or_insert_default(); let mut history_vec = history_items; - history_vec.sort_by(|a, b| a.id.cmp(&b.id)); + history_vec.sort_by_key(|a| a.id); album_details_modal.album_history.set_items(history_vec); album_details_modal .album_history diff --git a/src/network/lidarr_network/library/artists/mod.rs b/src/network/lidarr_network/library/artists/mod.rs index 484fa66..948456a 100644 --- a/src/network/lidarr_network/library/artists/mod.rs +++ b/src/network/lidarr_network/library/artists/mod.rs @@ -64,7 +64,7 @@ impl Network<'_, '_> { app.get_current_route(), Route::Lidarr(ActiveLidarrBlock::ArtistsSortPrompt, _) ) { - artists_vec.sort_by(|a, b| a.id.cmp(&b.id)); + artists_vec.sort_by_key(|a| a.id); app.data.lidarr_data.artists.set_items(artists_vec); app.data.lidarr_data.artists.apply_sorting_toggle(false); } @@ -309,7 +309,7 @@ impl Network<'_, '_> { let artist_history = &mut app.data.lidarr_data.artist_history; if !is_sorting { - history_vec.sort_by(|a, b| a.id.cmp(&b.id)); + history_vec.sort_by_key(|a| a.id); artist_history.set_items(history_vec); artist_history.apply_sorting_toggle(false); } diff --git a/src/network/lidarr_network/library/tracks/mod.rs b/src/network/lidarr_network/library/tracks/mod.rs index d24ddb5..1206f41 100644 --- a/src/network/lidarr_network/library/tracks/mod.rs +++ b/src/network/lidarr_network/library/tracks/mod.rs @@ -55,7 +55,7 @@ impl Network<'_, '_> { self .handle_request::<(), Vec>(request_props, |mut track_vec, mut app| { - track_vec.sort_by(|a, b| a.id.cmp(&b.id)); + track_vec.sort_by_key(|a| a.id); let album_details_modal = app .data .lidarr_data @@ -238,7 +238,7 @@ impl Network<'_, '_> { .into_iter() .filter(|it| it.track_id == track_id) .collect(); - history_vec.sort_by(|a, b| a.id.cmp(&b.id)); + history_vec.sort_by_key(|a| a.id); track_details_modal.track_history.set_items(history_vec); track_details_modal .track_history diff --git a/src/network/lidarr_network/system/mod.rs b/src/network/lidarr_network/system/mod.rs index fb1b1cf..8f50f31 100644 --- a/src/network/lidarr_network/system/mod.rs +++ b/src/network/lidarr_network/system/mod.rs @@ -50,7 +50,7 @@ impl Network<'_, '_> { let log_lines = logs .into_iter() .map(|log| { - if log.exception.is_some() { + if let Some(exception) = log.exception { HorizontallyScrollableText::from(format!( "{}|{}|{}|{}|{}", log.time, @@ -63,10 +63,7 @@ impl Network<'_, '_> { .exception_type .as_ref() .expect("exception_type must exist when exception is present"), - log - .exception - .as_ref() - .expect("exception must exist in this branch") + exception )) } else { HorizontallyScrollableText::from(format!( diff --git a/src/network/radarr_network/blocklist/mod.rs b/src/network/radarr_network/blocklist/mod.rs index 333b05a..dc6b632 100644 --- a/src/network/radarr_network/blocklist/mod.rs +++ b/src/network/radarr_network/blocklist/mod.rs @@ -83,7 +83,7 @@ impl Network<'_, '_> { Route::Radarr(ActiveRadarrBlock::BlocklistSortPrompt, _) ) { let mut blocklist_vec = blocklist_resp.records; - blocklist_vec.sort_by(|a, b| a.id.cmp(&b.id)); + blocklist_vec.sort_by_key(|a| a.id); app.data.radarr_data.blocklist.set_items(blocklist_vec); app.data.radarr_data.blocklist.apply_sorting_toggle(false); } diff --git a/src/network/radarr_network/collections/mod.rs b/src/network/radarr_network/collections/mod.rs index 7c04146..f8c1af1 100644 --- a/src/network/radarr_network/collections/mod.rs +++ b/src/network/radarr_network/collections/mod.rs @@ -128,7 +128,7 @@ impl Network<'_, '_> { app.get_current_route(), Route::Radarr(ActiveRadarrBlock::CollectionsSortPrompt, _) ) { - collections_vec.sort_by(|a, b| a.id.cmp(&b.id)); + collections_vec.sort_by_key(|a| a.id); app.data.radarr_data.collections.set_items(collections_vec); app.data.radarr_data.collections.apply_sorting_toggle(false); } diff --git a/src/network/radarr_network/history/mod.rs b/src/network/radarr_network/history/mod.rs index 429b7dd..138ad76 100644 --- a/src/network/radarr_network/history/mod.rs +++ b/src/network/radarr_network/history/mod.rs @@ -31,7 +31,7 @@ impl Network<'_, '_> { Route::Radarr(ActiveRadarrBlock::HistorySortPrompt, _) ) { let mut history_vec = history_response.records; - history_vec.sort_by(|a, b| a.id.cmp(&b.id)); + history_vec.sort_by_key(|a| a.id); app.data.radarr_data.history.set_items(history_vec); app.data.radarr_data.history.apply_sorting_toggle(false); } diff --git a/src/network/radarr_network/library/mod.rs b/src/network/radarr_network/library/mod.rs index 42b2d67..e373c58 100644 --- a/src/network/radarr_network/library/mod.rs +++ b/src/network/radarr_network/library/mod.rs @@ -270,7 +270,7 @@ impl Network<'_, '_> { app.get_current_route(), Route::Radarr(ActiveRadarrBlock::MoviesSortPrompt, _) ) { - movie_vec.sort_by(|a, b| a.id.cmp(&b.id)); + movie_vec.sort_by_key(|a| a.id); app.data.radarr_data.movies.set_items(movie_vec); app.data.radarr_data.movies.apply_sorting_toggle(false); } diff --git a/src/network/radarr_network/system/mod.rs b/src/network/radarr_network/system/mod.rs index 6091a55..40428cd 100644 --- a/src/network/radarr_network/system/mod.rs +++ b/src/network/radarr_network/system/mod.rs @@ -67,7 +67,7 @@ impl Network<'_, '_> { let log_lines = logs .into_iter() .map(|log| { - if log.exception.is_some() { + if let Some(exception) = log.exception { HorizontallyScrollableText::from(format!( "{}|{}|{}|{}|{}", log.time, @@ -80,10 +80,7 @@ impl Network<'_, '_> { .exception_type .as_ref() .expect("exception_type must exist when exception is present"), - log - .exception - .as_ref() - .expect("exception must exist in this branch") + exception )) } else { HorizontallyScrollableText::from(format!( diff --git a/src/network/sonarr_network/blocklist/mod.rs b/src/network/sonarr_network/blocklist/mod.rs index d43f46e..b1cfb6c 100644 --- a/src/network/sonarr_network/blocklist/mod.rs +++ b/src/network/sonarr_network/blocklist/mod.rs @@ -102,7 +102,7 @@ impl Network<'_, '_> { } }) .collect(); - blocklist_vec.sort_by(|a, b| a.id.cmp(&b.id)); + blocklist_vec.sort_by_key(|a| a.id); app.data.sonarr_data.blocklist.set_items(blocklist_vec); app.data.sonarr_data.blocklist.apply_sorting_toggle(false); } diff --git a/src/network/sonarr_network/history/mod.rs b/src/network/sonarr_network/history/mod.rs index 0fddf3c..72bbd7c 100644 --- a/src/network/sonarr_network/history/mod.rs +++ b/src/network/sonarr_network/history/mod.rs @@ -31,7 +31,7 @@ impl Network<'_, '_> { Route::Sonarr(ActiveSonarrBlock::HistorySortPrompt, _) ) { let mut history_vec = history_response.records; - history_vec.sort_by(|a, b| a.id.cmp(&b.id)); + history_vec.sort_by_key(|a| a.id); app.data.sonarr_data.history.set_items(history_vec); app.data.sonarr_data.history.apply_sorting_toggle(false); } diff --git a/src/network/sonarr_network/library/episodes/mod.rs b/src/network/sonarr_network/library/episodes/mod.rs index 518c872..0eec86d 100644 --- a/src/network/sonarr_network/library/episodes/mod.rs +++ b/src/network/sonarr_network/library/episodes/mod.rs @@ -60,7 +60,7 @@ impl Network<'_, '_> { self .handle_request::<(), Vec>(request_props, |mut episode_vec, mut app| { - episode_vec.sort_by(|a, b| a.id.cmp(&b.id)); + episode_vec.sort_by_key(|a| a.id); if !matches!( app.get_current_route(), Route::Sonarr(ActiveSonarrBlock::EpisodesSortPrompt, _) @@ -151,7 +151,7 @@ impl Network<'_, '_> { .get_or_insert_default(); let mut history_vec = history_response.records; - history_vec.sort_by(|a, b| a.id.cmp(&b.id)); + history_vec.sort_by_key(|a| a.id); episode_details_modal.episode_history.set_items(history_vec); episode_details_modal .episode_history diff --git a/src/network/sonarr_network/library/seasons/mod.rs b/src/network/sonarr_network/library/seasons/mod.rs index d165dff..c587965 100644 --- a/src/network/sonarr_network/library/seasons/mod.rs +++ b/src/network/sonarr_network/library/seasons/mod.rs @@ -158,7 +158,7 @@ impl Network<'_, '_> { if !is_sorting { let mut history_vec = history_items; - history_vec.sort_by(|a, b| a.id.cmp(&b.id)); + history_vec.sort_by_key(|a| a.id); season_details_modal.season_history.set_items(history_vec); season_details_modal .season_history diff --git a/src/network/sonarr_network/library/series/mod.rs b/src/network/sonarr_network/library/series/mod.rs index 151cbe6..1247528 100644 --- a/src/network/sonarr_network/library/series/mod.rs +++ b/src/network/sonarr_network/library/series/mod.rs @@ -315,7 +315,7 @@ impl Network<'_, '_> { let series_history = app.data.sonarr_data.series_history.get_or_insert_default(); if !is_sorting { - history_vec.sort_by(|a, b| a.id.cmp(&b.id)); + history_vec.sort_by_key(|a| a.id); series_history.set_items(history_vec); series_history.apply_sorting_toggle(false); } @@ -337,7 +337,7 @@ impl Network<'_, '_> { app.get_current_route(), Route::Sonarr(ActiveSonarrBlock::SeriesSortPrompt, _) ) { - series_vec.sort_by(|a, b| a.id.cmp(&b.id)); + series_vec.sort_by_key(|a| a.id); app.data.sonarr_data.series.set_items(series_vec); app.data.sonarr_data.series.apply_sorting_toggle(false); } diff --git a/src/network/sonarr_network/system/mod.rs b/src/network/sonarr_network/system/mod.rs index d2c1ed6..c32b75b 100644 --- a/src/network/sonarr_network/system/mod.rs +++ b/src/network/sonarr_network/system/mod.rs @@ -50,7 +50,7 @@ impl Network<'_, '_> { let log_lines = logs .into_iter() .map(|log| { - if log.exception.is_some() { + if let Some(exception) = log.exception { HorizontallyScrollableText::from(format!( "{}|{}|{}|{}|{}", log.time, @@ -63,10 +63,7 @@ impl Network<'_, '_> { .exception_type .as_ref() .expect("exception_type must exist when exception is present"), - log - .exception - .as_ref() - .expect("exception must exist in this branch") + exception )) } else { HorizontallyScrollableText::from(format!( diff --git a/src/ui/lidarr_ui/indexers/mod.rs b/src/ui/lidarr_ui/indexers/mod.rs index 2968537..dc1d9af 100644 --- a/src/ui/lidarr_ui/indexers/mod.rs +++ b/src/ui/lidarr_ui/indexers/mod.rs @@ -52,33 +52,24 @@ impl DrawUi for IndexersUi { _ if TestAllIndexersUi::accepts(route) => TestAllIndexersUi::draw(f, app, area), Route::Lidarr(active_lidarr_block, _) => match active_lidarr_block { ActiveLidarrBlock::TestIndexer => { - if app.is_loading || app.data.lidarr_data.indexer_test_errors.is_none() { + if let Some(result) = app.data.lidarr_data.indexer_test_errors.as_ref().filter(|_| !app.is_loading) { + let popup = if !result.is_empty() { + Popup::new(Message::new(result.clone())).size(Size::LargeMessage) + } else { + let message = Message::new("Indexer test succeeded!") + .title("Success") + .style(success_style().bold()); + Popup::new(message).size(Size::Message) + }; + + f.render_widget(popup, f.area()); + } else { let loading_popup = Popup::new(LoadingBlock::new( app.is_loading || app.data.lidarr_data.indexer_test_errors.is_none(), title_block("Testing Indexer"), )) .size(Size::LargeMessage); f.render_widget(loading_popup, f.area()); - } else { - let popup = { - let result = app - .data - .lidarr_data - .indexer_test_errors - .as_ref() - .expect("Test result is unpopulated"); - - if !result.is_empty() { - Popup::new(Message::new(result.clone())).size(Size::LargeMessage) - } else { - let message = Message::new("Indexer test succeeded!") - .title("Success") - .style(success_style().bold()); - Popup::new(message).size(Size::Message) - } - }; - - f.render_widget(popup, f.area()); } } ActiveLidarrBlock::DeleteIndexerPrompt => { diff --git a/src/ui/lidarr_ui/system/mod.rs b/src/ui/lidarr_ui/system/mod.rs index 70e89f1..e34362d 100644 --- a/src/ui/lidarr_ui/system/mod.rs +++ b/src/ui/lidarr_ui/system/mod.rs @@ -107,9 +107,8 @@ pub(super) fn draw_queued_events(f: &mut Frame<'_>, app: &mut App<'_>, area: Rec } else { queued }; - let started_string = if event.started.is_some() { - let started = - convert_to_minutes_hours_days(Utc::now().sub(event.started.unwrap()).num_minutes()); + let started_string = if let Some(date_time) = event.started { + let started = convert_to_minutes_hours_days(Utc::now().sub(date_time).num_minutes()); if started != "now" { format!("{started} ago") @@ -120,8 +119,8 @@ pub(super) fn draw_queued_events(f: &mut Frame<'_>, app: &mut App<'_>, area: Rec String::new() }; - let duration = if event.duration.is_some() { - &event.duration.as_ref().unwrap()[..8] + let duration = if let Some(dur) = &event.duration { + &dur[..8] } else { "" }; diff --git a/src/ui/radarr_ui/indexers/mod.rs b/src/ui/radarr_ui/indexers/mod.rs index 3f9cee1..884ae9d 100644 --- a/src/ui/radarr_ui/indexers/mod.rs +++ b/src/ui/radarr_ui/indexers/mod.rs @@ -52,33 +52,24 @@ impl DrawUi for IndexersUi { _ if TestAllIndexersUi::accepts(route) => TestAllIndexersUi::draw(f, app, area), Route::Radarr(active_radarr_block, _) => match active_radarr_block { ActiveRadarrBlock::TestIndexer => { - if app.is_loading || app.data.radarr_data.indexer_test_errors.is_none() { + if let Some(result) = app.data.radarr_data.indexer_test_errors.as_ref().filter(|_| !app.is_loading) { + let popup = if !result.is_empty() { + Popup::new(Message::new(result.clone())).size(Size::LargeMessage) + } else { + let message = Message::new("Indexer test succeeded!") + .title("Success") + .style(success_style().bold()); + Popup::new(message).size(Size::Message) + }; + + f.render_widget(popup, f.area()); + } else { let loading_popup = Popup::new(LoadingBlock::new( app.is_loading || app.data.radarr_data.indexer_test_errors.is_none(), title_block("Testing Indexer"), )) .size(Size::LargeMessage); f.render_widget(loading_popup, f.area()); - } else { - let popup = { - let result = app - .data - .radarr_data - .indexer_test_errors - .as_ref() - .expect("Test result is unpopulated"); - - if !result.is_empty() { - Popup::new(Message::new(result.clone())).size(Size::LargeMessage) - } else { - let message = Message::new("Indexer test succeeded!") - .title("Success") - .style(success_style().bold()); - Popup::new(message).size(Size::Message) - } - }; - - f.render_widget(popup, f.area()); } } ActiveRadarrBlock::DeleteIndexerPrompt => { diff --git a/src/ui/radarr_ui/system/mod.rs b/src/ui/radarr_ui/system/mod.rs index 79cf00c..8bec01e 100644 --- a/src/ui/radarr_ui/system/mod.rs +++ b/src/ui/radarr_ui/system/mod.rs @@ -114,9 +114,8 @@ pub(super) fn draw_queued_events(f: &mut Frame<'_>, app: &mut App<'_>, area: Rec } else { queued }; - let started_string = if event.started.is_some() { - let started = - convert_to_minutes_hours_days(Utc::now().sub(event.started.unwrap()).num_minutes()); + let started_string = if let Some(date_time) = event.started { + let started = convert_to_minutes_hours_days(Utc::now().sub(date_time).num_minutes()); if started != "now" { format!("{started} ago") diff --git a/src/ui/sonarr_ui/indexers/mod.rs b/src/ui/sonarr_ui/indexers/mod.rs index 6dcda09..5d5c5ba 100644 --- a/src/ui/sonarr_ui/indexers/mod.rs +++ b/src/ui/sonarr_ui/indexers/mod.rs @@ -52,33 +52,24 @@ impl DrawUi for IndexersUi { _ if TestAllIndexersUi::accepts(route) => TestAllIndexersUi::draw(f, app, area), Route::Sonarr(active_sonarr_block, _) => match active_sonarr_block { ActiveSonarrBlock::TestIndexer => { - if app.is_loading || app.data.sonarr_data.indexer_test_errors.is_none() { + if let Some(result) = app.data.sonarr_data.indexer_test_errors.as_ref().filter(|_| !app.is_loading) { + let popup = if !result.is_empty() { + Popup::new(Message::new(result.clone())).size(Size::LargeMessage) + } else { + let message = Message::new("Indexer test succeeded!") + .title("Success") + .style(success_style().bold()); + Popup::new(message).size(Size::Message) + }; + + f.render_widget(popup, f.area()); + } else { let loading_popup = Popup::new(LoadingBlock::new( app.is_loading || app.data.sonarr_data.indexer_test_errors.is_none(), title_block("Testing Indexer"), )) .size(Size::LargeMessage); f.render_widget(loading_popup, f.area()); - } else { - let popup = { - let result = app - .data - .sonarr_data - .indexer_test_errors - .as_ref() - .expect("Test result is unpopulated"); - - if !result.is_empty() { - Popup::new(Message::new(result.clone())).size(Size::LargeMessage) - } else { - let message = Message::new("Indexer test succeeded!") - .title("Success") - .style(success_style().bold()); - Popup::new(message).size(Size::Message) - } - }; - - f.render_widget(popup, f.area()); } } ActiveSonarrBlock::DeleteIndexerPrompt => { diff --git a/src/ui/sonarr_ui/system/mod.rs b/src/ui/sonarr_ui/system/mod.rs index e983762..233acd7 100644 --- a/src/ui/sonarr_ui/system/mod.rs +++ b/src/ui/sonarr_ui/system/mod.rs @@ -107,9 +107,8 @@ pub(super) fn draw_queued_events(f: &mut Frame<'_>, app: &mut App<'_>, area: Rec } else { queued }; - let started_string = if event.started.is_some() { - let started = - convert_to_minutes_hours_days(Utc::now().sub(event.started.unwrap()).num_minutes()); + let started_string = if let Some(date_time) = event.started { + let started = convert_to_minutes_hours_days(Utc::now().sub(date_time).num_minutes()); if started != "now" { format!("{started} ago") @@ -120,8 +119,8 @@ pub(super) fn draw_queued_events(f: &mut Frame<'_>, app: &mut App<'_>, area: Rec String::new() }; - let duration = if event.duration.is_some() { - &event.duration.as_ref().unwrap()[..8] + let duration = if let Some(dur) = &event.duration { + &dur[..8] } else { "" }; diff --git a/src/ui/widgets/managarr_table.rs b/src/ui/widgets/managarr_table.rs index a463e6e..9b9cb35 100644 --- a/src/ui/widgets/managarr_table.rs +++ b/src/ui/widgets/managarr_table.rs @@ -125,11 +125,8 @@ where if let Some(content) = self.content && !self.is_loading { - let (table_contents, table_state) = if content.filtered_items.is_some() { - ( - content.filtered_items.as_ref().unwrap(), - content.filtered_state.as_mut().unwrap(), - ) + let (table_contents, table_state) = if let Some(items) = &content.filtered_items { + (items, content.filtered_state.as_mut().unwrap()) } else { (&content.items, &mut content.state) }; @@ -153,10 +150,11 @@ where StatefulWidget::render(table, table_area, buf, table_state); - if content.sort.is_some() && self.is_sorting { - let selectable_list = SelectableList::new(content.sort.as_mut().unwrap(), |item| { - ListItem::new(Text::from(item.name)) - }); + if let Some(sort) = &mut content.sort + && self.is_sorting + { + let selectable_list = + SelectableList::new(sort, |item| ListItem::new(Text::from(item.name))); Popup::new(selectable_list) .dimensions(20, 50) .render(table_area, buf); From a4d93692a9459c3083edb91042f293c0b65491bb Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Thu, 25 Jun 2026 13:19:27 -0600 Subject: [PATCH 3/9] build: Upgraded to Rust v1.95.0 --- .github/workflows/check.yml | 8 +- Cargo.lock | 885 +++++++++++++++--------------------- Cargo.toml | 2 +- 3 files changed, 366 insertions(+), 529 deletions(-) diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index 3e504e6..e7848f8 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -76,15 +76,15 @@ jobs: RUSTDOCFLAGS: --cfg docsrs msrv: # check that we can build using the minimal rust version that is specified by this crate - name: 1.89.0 / check + name: 1.95.0 / check runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - name: Install 1.89.0 + - name: Install 1.95.0 uses: dtolnay/rust-toolchain@master with: - toolchain: 1.89.0 + toolchain: 1.95.0 - - name: cargo +1.89.0 check + - name: cargo +1.95.0 check run: cargo check diff --git a/Cargo.lock b/Cargo.lock index 332d24b..e34a7cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,6 +97,15 @@ version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +[[package]] +name = "approx" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" +dependencies = [ + "num-traits", +] + [[package]] name = "arc-swap" version = "1.9.1" @@ -118,9 +127,9 @@ dependencies = [ [[package]] name = "assert_cmd" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39bae1d3fa576f7c6519514180a72559268dd7d1fe104070956cb687bc6673bd" +checksum = "2aa3a22042e45de04255c7bf3626e239f450200fd0493c1e382263544b20aea6" dependencies = [ "anstyle", "bstr", @@ -149,7 +158,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -169,15 +178,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "aws-lc-rs" -version = "1.16.3" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f" +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" dependencies = [ "aws-lc-sys", "zeroize", @@ -185,9 +194,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.40.0" +version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7" +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" dependencies = [ "cc", "cmake", @@ -263,9 +272,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.11.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" [[package]] name = "block-buffer" @@ -287,20 +296,26 @@ dependencies = [ [[package]] name = "bstr" -version = "1.12.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +checksum = "5cee35f73844aa3014bb606320a6c1f010249dbdf43342fe54b5a4f6a8ed4b79" dependencies = [ "memchr", "regex-automata", - "serde", + "serde_core", ] [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" + +[[package]] +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" [[package]] name = "bytemuck" @@ -310,9 +325,9 @@ checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" [[package]] name = "bytes" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +checksum = "8ae3f5d315924270530207e2a68396c3cc547f6dca3fbdca317cfb1a51edb593" [[package]] name = "cargo-husky" @@ -331,9 +346,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.60" +version = "1.2.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20" +checksum = "e228eec9be7c17ccb640b59b36a5cd805ea2a564a4c5e162c2f659fea30d3b96" dependencies = [ "find-msvc-tools", "jobserver", @@ -341,12 +356,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - [[package]] name = "cfg-if" version = "1.0.4" @@ -361,9 +370,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.44" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ "iana-time-zone", "js-sys", @@ -398,9 +407,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.6.2" +version = "4.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff7a1dccbdd8b078c2bdebff47e404615151534d5043da397ec50286816f9cb" +checksum = "e0a7a9bfdb35811f9e59832f0f05975114d2251b415fb534108e6f34060fd772" dependencies = [ "clap", ] @@ -414,7 +423,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -459,9 +468,9 @@ dependencies = [ [[package]] name = "compact_str" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" +checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab" dependencies = [ "castaway", "cfg-if", @@ -552,13 +561,19 @@ dependencies = [ "libc", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + [[package]] name = "crossterm" version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "crossterm_winapi", "mio", "parking_lot", @@ -574,7 +589,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "crossterm_winapi", "derive_more", "document-features", @@ -622,7 +637,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ "dispatch2", - "nix 0.31.2", + "nix 0.31.3", "windows-sys 0.61.2", ] @@ -667,7 +682,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -681,7 +696,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -694,7 +709,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -705,7 +720,7 @@ checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core 0.20.11", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -716,7 +731,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core 0.21.3", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -727,7 +742,7 @@ checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ "darling_core 0.23.0", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -741,9 +756,6 @@ name = "deranged" version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" -dependencies = [ - "powerfmt", -] [[package]] name = "derivative" @@ -775,7 +787,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn 2.0.117", + "syn 2.0.118", "unicode-xid", ] @@ -788,7 +800,7 @@ dependencies = [ "darling 0.21.3", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -852,7 +864,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "block2", "libc", "objc2", @@ -860,13 +872,13 @@ dependencies = [ [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -892,9 +904,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "encode_unicode" @@ -919,7 +931,7 @@ checksum = "583f1f514d2754010ff71ed6853068cacbe43cc142cc076aa1b871d9754efc48" dependencies = [ "darling 0.20.11", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -928,7 +940,7 @@ version = "0.6.1" dependencies = [ "darling 0.20.11", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -977,6 +989,12 @@ dependencies = [ "regex", ] +[[package]] +name = "fast-srgb8" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" + [[package]] name = "fastrand" version = "2.4.1" @@ -1018,12 +1036,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - [[package]] name = "foldhash" version = "0.2.0" @@ -1103,7 +1115,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1120,9 +1132,9 @@ checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-timer" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" +checksum = "af43fadb8a98512d547e37b4e92e0ced13e205c061b87b4623eff01d918d6968" [[package]] name = "futures-util" @@ -1176,15 +1188,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "libc", "r-efi 6.0.0", - "wasip2", - "wasip3", ] [[package]] @@ -1201,9 +1211,9 @@ checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "h2" -version = "0.4.13" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +checksum = "6cb093c84e8bd9b188d4c4a8cb6579fc016968d14c99882163cd3ff402a4f155" dependencies = [ "atomic-waker", "bytes", @@ -1218,15 +1228,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash 0.1.5", -] - [[package]] name = "hashbrown" version = "0.16.1" @@ -1235,14 +1236,19 @@ checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", - "foldhash 0.2.0", + "foldhash", ] [[package]] name = "hashbrown" -version = "0.17.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] [[package]] name = "heck" @@ -1267,9 +1273,9 @@ dependencies = [ [[package]] name = "http" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" dependencies = [ "bytes", "itoa", @@ -1334,9 +1340,9 @@ checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "hyper" -version = "1.9.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" dependencies = [ "atomic-waker", "bytes", @@ -1500,12 +1506,6 @@ dependencies = [ "zerovec", ] -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "ident_case" version = "1.0.1" @@ -1525,9 +1525,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -1540,9 +1540,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.17.0", - "serde", - "serde_core", + "hashbrown 0.17.1", ] [[package]] @@ -1569,9 +1567,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.47.2" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4a6248eb93a4401ed2f37dfe8ea592d3cf05b7cf4f8efa867b6895af7e094e" +checksum = "86f0f8fee8c926415c58d6ae43a08523a26faccb2323f5e6b644fe7dd4ef6b82" dependencies = [ "console 0.16.3", "once_cell", @@ -1589,7 +1587,7 @@ dependencies = [ "indoc", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1598,16 +1596,6 @@ version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" -[[package]] -name = "iri-string" -version = "0.7.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -1631,27 +1619,32 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jni" -version = "0.21.1" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" dependencies = [ - "cesu8", "cfg-if", "combine", - "jni-sys 0.3.1", + "jni-macros", + "jni-sys", "log", - "thiserror 1.0.69", + "simd_cesu8", + "thiserror 2.0.18", "walkdir", - "windows-sys 0.45.0", + "windows-link", ] [[package]] -name = "jni-sys" -version = "0.3.1" +name = "jni-macros" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" dependencies = [ - "jni-sys 0.4.1", + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.118", ] [[package]] @@ -1670,7 +1663,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -1685,13 +1678,12 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.95" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" dependencies = [ "cfg-if", "futures-util", - "once_cell", "wasm-bindgen", ] @@ -1719,22 +1711,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] -name = "leb128fmt" -version = "0.1.0" +name = "libc" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] -name = "libc" -version = "0.2.185" +name = "libm" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ff2c0fe9bc6cb6b14a0592c2ff4fa9ceb83eea9db979b0487cd054946a2b8f" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c" +checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" dependencies = [ "libc", ] @@ -1745,7 +1737,7 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f50e8f47623268b5407192d26876c4d7f89d686ca130fdc53bced4814cd29f8" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -1783,9 +1775,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.29" +version = "0.4.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" dependencies = [ "serde_core", ] @@ -1827,11 +1819,11 @@ dependencies = [ [[package]] name = "lru" -version = "0.16.4" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" +checksum = "8a860605968fce16869fd239cf4237a82f3ac470723415db603b0e8b6c8d4fb9" dependencies = [ - "hashbrown 0.16.1", + "hashbrown 0.17.1", ] [[package]] @@ -1915,9 +1907,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "memmem" @@ -1957,9 +1949,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ "libc", "log", @@ -1969,9 +1961,9 @@ dependencies = [ [[package]] name = "mock_instant" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce6dd36094cac388f119d2e9dc82dc730ef91c32a6222170d630e5414b956e6" +checksum = "9bb517913cfcfb9eeda59f36020269075a152701a01606c612f547e4890be399" [[package]] name = "mockall" @@ -1996,7 +1988,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2030,7 +2022,7 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg-if", "cfg_aliases", "libc", @@ -2039,11 +2031,11 @@ dependencies = [ [[package]] name = "nix" -version = "0.31.2" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d0705320c1e6ba1d912b5e37cf18071b6c2e9b7fa8215a1e8a7651966f5d3" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg-if", "cfg_aliases", "libc", @@ -2070,9 +2062,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-derive" @@ -2082,7 +2074,7 @@ checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2124,7 +2116,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -2166,15 +2158,14 @@ checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "openssl" -version = "0.10.78" +version = "0.10.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38c4372413cdaaf3cc79dd92d29d7d9f5ab09b51b10dded508fb90bb70b9222" +checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "cfg-if", "foreign-types", "libc", - "once_cell", "openssl-macros", "openssl-sys", ] @@ -2187,7 +2178,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2198,18 +2189,18 @@ checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-src" -version = "300.6.0+3.6.2" +version = "300.6.1+3.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8e8cbfd3a4a8c8f089147fd7aaa33cf8c7450c4d09f8f80698a0cf093abeff4" +checksum = "46eb8fb9fb3b61ce1c0f8a026c4c1a0714d3a9e138e7fbde78753ce2babc3846" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.114" +version = "0.9.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13ce1245cd07fcc4cfdb438f7507b0c7e4f3849a69fd84d52374c66d83741bb6" +checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695" dependencies = [ "cc", "libc", @@ -2236,6 +2227,30 @@ dependencies = [ "num-traits", ] +[[package]] +name = "palette" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" +dependencies = [ + "approx", + "fast-srgb8", + "libm", + "palette_derive", +] + +[[package]] +name = "palette_derive" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" +dependencies = [ + "by_address", + "proc-macro2", + "quote", + "syn 2.0.118", +] + [[package]] name = "parking_lot" version = "0.12.5" @@ -2295,7 +2310,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2348,7 +2363,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -2439,16 +2454,6 @@ dependencies = [ "yansi", ] -[[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn 2.0.117", -] - [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -2475,7 +2480,7 @@ checksum = "4b45fcc2344c680f5025fe57779faef368840d0bd1f42f216291f0dc4ace4744" dependencies = [ "bit-set 0.8.0", "bit-vec 0.8.0", - "bitflags 2.11.1", + "bitflags 2.13.0", "num-traits", "rand 0.9.4", "rand_chacha", @@ -2494,9 +2499,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quinn" -version = "0.11.9" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +checksum = "0c1a41e437b6bbd489372cd4971de128e85c855f56c57f283d20ff016cf7c0a8" dependencies = [ "bytes", "cfg_aliases", @@ -2514,9 +2519,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.14" +version = "0.11.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" +checksum = "4fcb935c5bec503c2f0e306bdd3e58bb9029dcb14fa8d9ac76e3a5256ac0763e" dependencies = [ "aws-lc-rs", "bytes", @@ -2550,9 +2555,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.45" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] @@ -2624,32 +2629,36 @@ dependencies = [ [[package]] name = "ratatui" -version = "0.30.0" +version = "0.30.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1ce67fb8ba4446454d1c8dbaeda0557ff5e94d39d5e5ed7f10a65eb4c8266bc" +checksum = "3274ba0a2c5e1bcad2a2005d20f4dc59dad26b2eb0940fb094500dba4099d57d" dependencies = [ "instability", "ratatui-core", "ratatui-crossterm", "ratatui-macros", + "ratatui-termina", "ratatui-termwiz", "ratatui-widgets", + "serde", ] [[package]] name = "ratatui-core" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293" +checksum = "cbb175c433c8e28a809d1f5773a2ae96e68c0ce40db865cbab1020bf33ae479c" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "compact_str", - "hashbrown 0.16.1", - "indoc", + "critical-section", + "hashbrown 0.17.1", "itertools", "kasuari", "lru", - "strum 0.27.2", + "palette", + "serde", + "strum 0.28.0", "thiserror 2.0.18", "unicode-segmentation", "unicode-truncate", @@ -2658,9 +2667,9 @@ dependencies = [ [[package]] name = "ratatui-crossterm" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "577c9b9f652b4c121fb25c6a391dd06406d3b092ba68827e6d2f09550edc54b3" +checksum = "567584a3b0e6a8203c23de40b4861497266725eb5363dbfd18a1edd603cca9f0" dependencies = [ "cfg-if", "crossterm 0.29.0", @@ -2670,19 +2679,30 @@ dependencies = [ [[package]] name = "ratatui-macros" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f1342a13e83e4bb9d0b793d0ea762be633f9582048c892ae9041ef39c936f4" +checksum = "ed7dc68daa7498a43e4d68e0eb078427e10c38fbcfbb1e42d955f1fa2140d814" dependencies = [ "ratatui-core", "ratatui-widgets", ] [[package]] -name = "ratatui-termwiz" +name = "ratatui-termina" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f76fe0bd0ed4295f0321b1676732e2454024c15a35d01904ddb315afd3d545c" +checksum = "c0bf912d9e66f057a759d92e386a280ea886b352ab757d6ac4d653c7ed2c43c2" +dependencies = [ + "instability", + "ratatui-core", + "termina", +] + +[[package]] +name = "ratatui-termwiz" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf03e0380b7744054d6cb74224fe3adf062a029754933f575ca1e3b4c2ce977" dependencies = [ "ratatui-core", "termwiz", @@ -2690,18 +2710,19 @@ dependencies = [ [[package]] name = "ratatui-widgets" -version = "0.3.0" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7dbfa023cd4e604c2553483820c5fe8aa9d71a42eea5aa77c6e7f35756612db" +checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1" dependencies = [ - "bitflags 2.11.1", - "hashbrown 0.16.1", + "bitflags 2.13.0", + "hashbrown 0.17.1", "indoc", "instability", "itertools", "line-clipping", "ratatui-core", - "strum 0.27.2", + "serde", + "strum 0.28.0", "time", "unicode-segmentation", "unicode-width", @@ -2713,7 +2734,7 @@ version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", ] [[package]] @@ -2729,9 +2750,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.3" +version = "1.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" dependencies = [ "aho-corasick", "memchr", @@ -2752,9 +2773,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "relative-path" @@ -2764,9 +2785,9 @@ checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "reqwest" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" dependencies = [ "base64", "bytes", @@ -2842,7 +2863,7 @@ dependencies = [ "regex", "relative-path", "rustc_version", - "syn 2.0.117", + "syn 2.0.118", "unicode-ident", ] @@ -2873,7 +2894,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -2886,7 +2907,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "errno", "libc", "linux-raw-sys 0.12.1", @@ -2895,9 +2916,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.38" +version = "0.23.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f9466fb2c14ea04357e91413efb882e2a6d4a406e625449bc0a5d360d53a21" +checksum = "6b92b125634d9b795e7beca796cc790df15a7fb38323bf3196fda83292d06b1f" dependencies = [ "aws-lc-rs", "once_cell", @@ -2909,9 +2930,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -2921,9 +2942,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ "web-time", "zeroize", @@ -2931,9 +2952,9 @@ dependencies = [ [[package]] name = "rustls-platform-verifier" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", @@ -2958,9 +2979,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" [[package]] name = "rustls-webpki" -version = "0.103.12" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ "aws-lc-rs", "ring", @@ -3001,15 +3022,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "scc" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc" -dependencies = [ - "sdd", -] - [[package]] name = "schannel" version = "0.1.29" @@ -3025,19 +3037,13 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sdd" -version = "3.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" - [[package]] name = "security-framework" version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -3097,14 +3103,14 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ "itoa", "memchr", @@ -3149,28 +3155,27 @@ dependencies = [ [[package]] name = "serial_test" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "911bd979bf1070a3f3aa7b691a3b3e9968f339ceeec89e08c280a8a22207a32f" +checksum = "699f4197115b8a7e7ff19c9a315a4bd6fffec26cc4626ef45ecaea389e081c6d" dependencies = [ "futures-executor", "futures-util", "log", "once_cell", "parking_lot", - "scc", "serial_test_derive", ] [[package]] name = "serial_test_derive" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a7d91949b85b0d2fb687445e448b40d322b6b3e4af6b44a29b21d9a5f33e6d9" +checksum = "94e153fc76e1c6a068703d6d29c508a0b15c061c4b7e43da59cc097bc342673c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3186,9 +3191,9 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "signal-hook" @@ -3221,6 +3226,22 @@ dependencies = [ "libc", ] +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "similar" version = "2.7.0" @@ -3229,9 +3250,9 @@ checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" [[package]] name = "siphasher" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "slab" @@ -3241,15 +3262,15 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.1" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "socket2" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", "windows-sys 0.61.2", @@ -3284,11 +3305,11 @@ dependencies = [ [[package]] name = "strum" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" dependencies = [ - "strum_macros 0.27.2", + "strum_macros 0.28.0", ] [[package]] @@ -3301,19 +3322,19 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "strum_macros" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3335,9 +3356,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.117" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -3361,7 +3382,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3384,7 +3405,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -3406,12 +3427,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.2", + "getrandom 0.4.3", "once_cell", "rustix 1.1.4", "windows-sys 0.61.2", ] +[[package]] +name = "termina" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9048a889effe34a5cddee0af7f53285198b16dca3be510858d38dfdb3e62a04e" +dependencies = [ + "bitflags 2.13.0", + "parking_lot", + "rustix 1.1.4", + "signal-hook", + "windows-sys 0.61.2", +] + [[package]] name = "terminal_size" version = "0.4.4" @@ -3457,7 +3491,7 @@ checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" dependencies = [ "anyhow", "base64", - "bitflags 2.11.1", + "bitflags 2.13.0", "fancy-regex", "filedescriptor", "finl_unicode", @@ -3517,7 +3551,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3528,7 +3562,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3543,9 +3577,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.47" +version = "0.3.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +checksum = "85c17d80feb7334b40c484e45ed1a5273dfd8bfda537c3be2e74a06a6686f327" dependencies = [ "deranged", "libc", @@ -3558,9 +3592,9 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" +checksum = "9e1c906769ad99c88eaa54e728060edef082f8e358ff32030cb7c7d315e81109" [[package]] name = "tinystr" @@ -3589,9 +3623,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.52.1" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", @@ -3612,7 +3646,7 @@ checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3661,9 +3695,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.25.11+spec-1.1.0" +version = "0.25.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" dependencies = [ "indexmap", "toml_datetime", @@ -3703,20 +3737,20 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.8" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags 2.11.1", + "bitflags 2.13.0", "bytes", "futures-util", "http", "http-body", - "iri-string", "pin-project-lite", "tower", "tower-layer", "tower-service", + "url", ] [[package]] @@ -3767,9 +3801,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.20.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "ucd-trie" @@ -3791,9 +3825,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-segmentation" -version = "1.13.2" +version = "1.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" +checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8" [[package]] name = "unicode-truncate" @@ -3871,12 +3905,12 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.1" +version = "1.23.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76" +checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" dependencies = [ "atomic", - "getrandom 0.4.2", + "getrandom 0.4.3", "js-sys", "wasm-bindgen", ] @@ -3888,7 +3922,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40630259c022600210096da9538abcb992b801e30b464cb9d19f19ef0e0d09b9" dependencies = [ "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3897,7 +3931,7 @@ version = "0.6.1" dependencies = [ "log", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3924,7 +3958,7 @@ checksum = "5b2d5567b6fbd34e8f0488d56b648e67c0d999535f4af2060d14f9074b43e833" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -3978,27 +4012,18 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] name = "wasip2" -version = "1.0.3+wasi-0.2.9" +version = "1.0.4+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" +checksum = "b67efb37e106e55ce722a510d6b5f9c17f083e5fc79afc2badeb12cc313d9487" dependencies = [ - "wit-bindgen 0.57.1", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen 0.51.0", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.118" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" dependencies = [ "cfg-if", "once_cell", @@ -4009,9 +4034,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.68" +version = "0.4.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" +checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" dependencies = [ "js-sys", "wasm-bindgen", @@ -4019,9 +4044,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.118" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4029,65 +4054,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.118" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.118" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser", -] - -[[package]] -name = "wasmparser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags 2.11.1", - "hashbrown 0.15.5", - "indexmap", - "semver", -] - [[package]] name = "web-sys" -version = "0.3.95" +version = "0.3.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" +checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" dependencies = [ "js-sys", "wasm-bindgen", @@ -4105,9 +4096,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" +checksum = "0d46a5a140e6f7afeccd8eae97eff335163939eac8b929834875168b29b3d267" dependencies = [ "rustls-pki-types", ] @@ -4268,7 +4259,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4279,7 +4270,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] @@ -4327,15 +4318,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.52.0" @@ -4372,21 +4354,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-targets" version = "0.52.6" @@ -4429,12 +4396,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -4447,12 +4408,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -4465,12 +4420,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -4495,12 +4444,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -4513,12 +4456,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -4531,12 +4468,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -4549,12 +4480,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -4569,107 +4494,19 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" dependencies = [ "memchr", ] -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn 2.0.117", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn 2.0.117", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags 2.11.1", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser", -] - [[package]] name = "writeable" version = "0.6.3" @@ -4684,9 +4521,9 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yoke" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" +checksum = "709fe23a0424b6a435d82152b1bd3fdfb0833487d5fa90d05d42762a9891fef5" dependencies = [ "stable_deref_trait", "yoke-derive", @@ -4701,35 +4538,35 @@ checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.48" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.48" +version = "0.8.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] name = "zerofrom" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] @@ -4742,15 +4579,15 @@ checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.2" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" [[package]] name = "zerotrie" @@ -4782,7 +4619,7 @@ checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.117", + "syn 2.0.118", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 60b3917..cf9c5ba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,7 +10,7 @@ homepage = "https://github.com/Dark-Alex-17/managarr" readme = "README.md" edition = "2024" license = "MIT" -rust-version = "1.89.0" +rust-version = "1.95.0" exclude = [".github", "CONTRIBUTING.md", "*.log", "tags"] [workspace] From 10e18af1bf87b01121667d34126f917cef950c1f Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Thu, 25 Jun 2026 13:20:14 -0600 Subject: [PATCH 4/9] build: upgraded to openssl 0.10.79 to fix security vulnerabilities --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index cf9c5ba..babd875 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,7 +63,7 @@ managarr-tree-widget = "0.25.0" indicatif = "0.17.11" derive_setters = "0.1.9" deunicode = "1.6.2" -openssl = { version = "0.10.75", features = ["vendored"] } +openssl = { version = "0.10.79", features = ["vendored"] } veil = "0.2.0" validate_theme_derive = "0.1.0" enum_display_style_derive = "0.1.0" From dd93fe117dd28e6fa8b015c1a27fc7a1d0ab0539 Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Thu, 25 Jun 2026 13:29:56 -0600 Subject: [PATCH 5/9] feat: Implemented log rolling so the log file doesn't just grow exponentially [#60] --- Cargo.toml | 2 +- src/utils.rs | 21 ++++++++++++++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index babd875..a7f63b8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ derivative = "2.2.0" human-panic = "2.0.6" indoc = "2.0.7" log = "0.4.29" -log4rs = { version = "1.4.0", features = ["file_appender"] } +log4rs = { version = "1.4.0", features = ["rolling_file_appender", "compound_policy", "size_trigger", "fixed_window_roller"] } regex = "1.12.2" reqwest = { version = "0.13.2", features = ["json"] } serde_yaml = "0.9.34" diff --git a/src/utils.rs b/src/utils.rs index 7dd2e5a..904ae20 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -10,7 +10,10 @@ use anyhow::{Context, anyhow}; use colored::Colorize; use indicatif::{ProgressBar, ProgressStyle}; use log::{LevelFilter, error}; -use log4rs::append::file::FileAppender; +use log4rs::append::rolling_file::policy::compound::roll::fixed_window::FixedWindowRoller; +use log4rs::append::rolling_file::policy::compound::trigger::size::SizeTrigger; +use log4rs::append::rolling_file::policy::compound::CompoundPolicy; +use log4rs::append::rolling_file::RollingFileAppender; use log4rs::config::{Appender, Root}; use log4rs::encode::pattern::PatternEncoder; use regex::Regex; @@ -47,11 +50,23 @@ pub fn get_log_path() -> PathBuf { } pub fn init_logging_config() -> log4rs::Config { - let logfile = FileAppender::builder() + let log_path = get_log_path(); + let archive_pattern = log_path + .with_file_name("managarr.{}.log") + .to_string_lossy() + .into_owned(); + + let trigger = SizeTrigger::new(10 * 1024 * 1024); + let roller = FixedWindowRoller::builder() + .build(&archive_pattern, 3) + .unwrap(); + let policy = CompoundPolicy::new(Box::new(trigger), Box::new(roller)); + + let logfile = RollingFileAppender::builder() .encoder(Box::new(PatternEncoder::new( "{d(%Y-%m-%d %H:%M:%S%.3f)(utc)} <{i}> [{l}] {f}:{L} - {m}{n}", ))) - .build(get_log_path()) + .build(log_path, Box::new(policy)) .unwrap(); log4rs::Config::builder() From 366809d8c6defc1a5266c8580464e99022a705d3 Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Thu, 25 Jun 2026 13:32:31 -0600 Subject: [PATCH 6/9] fmt: applied formatting --- src/ui/lidarr_ui/indexers/mod.rs | 8 +++++++- src/ui/radarr_ui/indexers/mod.rs | 8 +++++++- src/ui/sonarr_ui/indexers/mod.rs | 8 +++++++- src/utils.rs | 4 ++-- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/ui/lidarr_ui/indexers/mod.rs b/src/ui/lidarr_ui/indexers/mod.rs index dc1d9af..2da5b45 100644 --- a/src/ui/lidarr_ui/indexers/mod.rs +++ b/src/ui/lidarr_ui/indexers/mod.rs @@ -52,7 +52,13 @@ impl DrawUi for IndexersUi { _ if TestAllIndexersUi::accepts(route) => TestAllIndexersUi::draw(f, app, area), Route::Lidarr(active_lidarr_block, _) => match active_lidarr_block { ActiveLidarrBlock::TestIndexer => { - if let Some(result) = app.data.lidarr_data.indexer_test_errors.as_ref().filter(|_| !app.is_loading) { + if let Some(result) = app + .data + .lidarr_data + .indexer_test_errors + .as_ref() + .filter(|_| !app.is_loading) + { let popup = if !result.is_empty() { Popup::new(Message::new(result.clone())).size(Size::LargeMessage) } else { diff --git a/src/ui/radarr_ui/indexers/mod.rs b/src/ui/radarr_ui/indexers/mod.rs index 884ae9d..10d270d 100644 --- a/src/ui/radarr_ui/indexers/mod.rs +++ b/src/ui/radarr_ui/indexers/mod.rs @@ -52,7 +52,13 @@ impl DrawUi for IndexersUi { _ if TestAllIndexersUi::accepts(route) => TestAllIndexersUi::draw(f, app, area), Route::Radarr(active_radarr_block, _) => match active_radarr_block { ActiveRadarrBlock::TestIndexer => { - if let Some(result) = app.data.radarr_data.indexer_test_errors.as_ref().filter(|_| !app.is_loading) { + if let Some(result) = app + .data + .radarr_data + .indexer_test_errors + .as_ref() + .filter(|_| !app.is_loading) + { let popup = if !result.is_empty() { Popup::new(Message::new(result.clone())).size(Size::LargeMessage) } else { diff --git a/src/ui/sonarr_ui/indexers/mod.rs b/src/ui/sonarr_ui/indexers/mod.rs index 5d5c5ba..74260dc 100644 --- a/src/ui/sonarr_ui/indexers/mod.rs +++ b/src/ui/sonarr_ui/indexers/mod.rs @@ -52,7 +52,13 @@ impl DrawUi for IndexersUi { _ if TestAllIndexersUi::accepts(route) => TestAllIndexersUi::draw(f, app, area), Route::Sonarr(active_sonarr_block, _) => match active_sonarr_block { ActiveSonarrBlock::TestIndexer => { - if let Some(result) = app.data.sonarr_data.indexer_test_errors.as_ref().filter(|_| !app.is_loading) { + if let Some(result) = app + .data + .sonarr_data + .indexer_test_errors + .as_ref() + .filter(|_| !app.is_loading) + { let popup = if !result.is_empty() { Popup::new(Message::new(result.clone())).size(Size::LargeMessage) } else { diff --git a/src/utils.rs b/src/utils.rs index 904ae20..0588169 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -10,10 +10,10 @@ use anyhow::{Context, anyhow}; use colored::Colorize; use indicatif::{ProgressBar, ProgressStyle}; use log::{LevelFilter, error}; +use log4rs::append::rolling_file::RollingFileAppender; +use log4rs::append::rolling_file::policy::compound::CompoundPolicy; use log4rs::append::rolling_file::policy::compound::roll::fixed_window::FixedWindowRoller; use log4rs::append::rolling_file::policy::compound::trigger::size::SizeTrigger; -use log4rs::append::rolling_file::policy::compound::CompoundPolicy; -use log4rs::append::rolling_file::RollingFileAppender; use log4rs::config::{Appender, Root}; use log4rs::encode::pattern::PatternEncoder; use regex::Regex; From 92187c5f164e64d82313269955b0f9c8ae9919dc Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Thu, 25 Jun 2026 13:51:32 -0600 Subject: [PATCH 7/9] fix: tail-logs subcommand follows log rollovers and sleeps to minimize idle CPU loops --- src/utils.rs | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 0588169..5f2f0c8 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -104,23 +104,50 @@ pub async fn tail_logs(no_color: bool) -> Result<()> { .seek(SeekFrom::End(0)) .with_context(|| "Unable to tail log file")?; - let mut lines = reader.lines(); - tokio::spawn(async move { loop { - if let Some(Ok(line)) = lines.next() { - if no_color { - println!("{line}"); - } else { - let colored_line = colorize_log_line(&line, &re); - println!("{colored_line}"); + let mut line_buf = String::new(); + match reader.read_line(&mut line_buf) { + Ok(0) => { + if was_log_rotated(&file_path, &mut reader) { + continue; + } + + tokio::time::sleep(Duration::from_millis(100)).await; + } + Ok(_) => { + let line = line_buf.trim_end(); + if no_color { + println!("{line}"); + } else { + let colored_line = colorize_log_line(line, &re); + println!("{colored_line}"); + } + } + Err(_) => { + tokio::time::sleep(Duration::from_millis(100)).await; } } + line_buf.clear(); } }) .await? } +fn was_log_rotated(file_path: &PathBuf, reader: &mut BufReader) -> bool { + let current_pos = reader.stream_position().unwrap_or(0); + let file_len = fs::metadata(file_path).map(|m| m.len()).unwrap_or(0); + + if file_len < current_pos + && let Ok(new_file) = File::open(file_path) + { + *reader = BufReader::new(new_file); + return true; + } + + false +} + fn colorize_log_line(line: &str, re: &Regex) -> String { if let Some(caps) = re.captures(line) { let level = &caps["level"]; From cbca6bd91689e043d9e2a952d420efe724da050a Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Thu, 25 Jun 2026 14:11:18 -0600 Subject: [PATCH 8/9] fix: addressed code review comments --- src/utils.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 5f2f0c8..5b7f5bb 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -59,7 +59,7 @@ pub fn init_logging_config() -> log4rs::Config { let trigger = SizeTrigger::new(10 * 1024 * 1024); let roller = FixedWindowRoller::builder() .build(&archive_pattern, 3) - .unwrap(); + .expect("Failed to build log roller"); let policy = CompoundPolicy::new(Box::new(trigger), Box::new(roller)); let logfile = RollingFileAppender::builder() @@ -67,7 +67,7 @@ pub fn init_logging_config() -> log4rs::Config { "{d(%Y-%m-%d %H:%M:%S%.3f)(utc)} <{i}> [{l}] {f}:{L} - {m}{n}", ))) .build(log_path, Box::new(policy)) - .unwrap(); + .expect("Failed to build rolling file appender"); log4rs::Config::builder() .appender(Appender::builder().build("logfile", Box::new(logfile))) @@ -105,8 +105,9 @@ pub async fn tail_logs(no_color: bool) -> Result<()> { .with_context(|| "Unable to tail log file")?; tokio::spawn(async move { + let mut line_buf = String::new(); loop { - let mut line_buf = String::new(); + line_buf.clear(); match reader.read_line(&mut line_buf) { Ok(0) => { if was_log_rotated(&file_path, &mut reader) { @@ -128,7 +129,6 @@ pub async fn tail_logs(no_color: bool) -> Result<()> { tokio::time::sleep(Duration::from_millis(100)).await; } } - line_buf.clear(); } }) .await? From 6df68b8a66b4f4e4c65489dbd21465717c143380 Mon Sep 17 00:00:00 2001 From: Alex Clarke Date: Thu, 25 Jun 2026 14:21:57 -0600 Subject: [PATCH 9/9] tests: Addressed additional CR comments and added tests for tail-logs --- src/utils.rs | 8 +++---- src/utils_tests.rs | 56 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 5b7f5bb..788a6a7 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -104,7 +104,7 @@ pub async fn tail_logs(no_color: bool) -> Result<()> { .seek(SeekFrom::End(0)) .with_context(|| "Unable to tail log file")?; - tokio::spawn(async move { + tokio::task::spawn_blocking(move || { let mut line_buf = String::new(); loop { line_buf.clear(); @@ -114,7 +114,7 @@ pub async fn tail_logs(no_color: bool) -> Result<()> { continue; } - tokio::time::sleep(Duration::from_millis(100)).await; + std::thread::sleep(Duration::from_millis(100)); } Ok(_) => { let line = line_buf.trim_end(); @@ -126,7 +126,7 @@ pub async fn tail_logs(no_color: bool) -> Result<()> { } } Err(_) => { - tokio::time::sleep(Duration::from_millis(100)).await; + std::thread::sleep(Duration::from_millis(100)); } } } @@ -134,7 +134,7 @@ pub async fn tail_logs(no_color: bool) -> Result<()> { .await? } -fn was_log_rotated(file_path: &PathBuf, reader: &mut BufReader) -> bool { +pub(crate) fn was_log_rotated(file_path: &PathBuf, reader: &mut BufReader) -> bool { let current_pos = reader.stream_position().unwrap_or(0); let file_len = fs::metadata(file_path).map(|m| m.len()).unwrap_or(0); diff --git a/src/utils_tests.rs b/src/utils_tests.rs index 7e9a533..9434f80 100644 --- a/src/utils_tests.rs +++ b/src/utils_tests.rs @@ -1,8 +1,11 @@ #[cfg(test)] mod tests { + use std::fs::{self, File}; + use std::io::{BufRead, BufReader, Seek, SeekFrom, Write}; + use pretty_assertions::assert_eq; - use crate::utils::{convert_f64_to_gb, convert_runtime, convert_to_gb}; + use crate::utils::{convert_f64_to_gb, convert_runtime, convert_to_gb, was_log_rotated}; #[test] fn test_convert_to_gb() { @@ -23,4 +26,55 @@ mod tests { assert_eq!(hours, 2); assert_eq!(minutes, 34); } + + #[test] + fn test_was_log_rotated_returns_false_when_file_has_not_rotated() { + let path = std::env::temp_dir().join("managarr_test_no_rotation.log"); + fs::write(&path, "line one\nline two\n").unwrap(); + + let file = File::open(&path).unwrap(); + let mut reader = BufReader::new(file); + reader.seek(SeekFrom::End(0)).unwrap(); + + assert!(!was_log_rotated(&path, &mut reader)); + + fs::remove_file(&path).unwrap(); + } + + #[test] + fn test_was_log_rotated_returns_true_and_reopens_reader_after_rotation() { + let path = std::env::temp_dir().join("managarr_test_rotation.log"); + fs::write(&path, "original content that is long enough\n").unwrap(); + + let file = File::open(&path).unwrap(); + let mut reader = BufReader::new(file); + reader.seek(SeekFrom::End(0)).unwrap(); + + fs::write(&path, "new\n").unwrap(); + + assert!(was_log_rotated(&path, &mut reader)); + + let mut line = String::new(); + reader.read_line(&mut line).unwrap(); + assert_eq!(line, "new\n"); + + fs::remove_file(&path).unwrap(); + } + + #[test] + fn test_was_log_rotated_returns_false_when_file_grows() { + let path = std::env::temp_dir().join("managarr_test_growing.log"); + fs::write(&path, "initial\n").unwrap(); + + let file = File::open(&path).unwrap(); + let mut reader = BufReader::new(file); + reader.seek(SeekFrom::End(0)).unwrap(); + + let mut appender = fs::OpenOptions::new().append(true).open(&path).unwrap(); + appender.write_all(b"more data\n").unwrap(); + + assert!(!was_log_rotated(&path, &mut reader)); + + fs::remove_file(&path).unwrap(); + } }