feat(cli): Added a spinner to the CLI for long running commands like fetching releases
This commit is contained in:
+20
-79
@@ -1,20 +1,13 @@
|
||||
#![warn(rust_2018_idioms)]
|
||||
|
||||
use std::fs::{self, File};
|
||||
use std::io::BufReader;
|
||||
use anyhow::Result;
|
||||
use std::panic::PanicHookInfo;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use std::{io, panic, process};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use anyhow::Result;
|
||||
use app::{log_and_print_error, AppConfig};
|
||||
use clap::{
|
||||
command, crate_authors, crate_description, crate_name, crate_version, CommandFactory, Parser,
|
||||
};
|
||||
use clap::{crate_authors, crate_description, crate_name, crate_version, CommandFactory, Parser};
|
||||
use clap_complete::generate;
|
||||
use colored::Colorize;
|
||||
use crossterm::execute;
|
||||
@@ -25,14 +18,17 @@ use log::{error, warn};
|
||||
use network::NetworkTrait;
|
||||
use ratatui::backend::CrosstermBackend;
|
||||
use ratatui::Terminal;
|
||||
use reqwest::{Certificate, Client};
|
||||
use reqwest::Client;
|
||||
use tokio::select;
|
||||
use tokio::sync::mpsc::Receiver;
|
||||
use tokio::sync::{mpsc, Mutex};
|
||||
use tokio_util::sync::CancellationToken;
|
||||
use utils::tail_logs;
|
||||
use utils::{
|
||||
build_network_client, load_config, render_spinner, start_cli_no_spinner, start_cli_with_spinner,
|
||||
tail_logs,
|
||||
};
|
||||
|
||||
use crate::app::App;
|
||||
use crate::app::{App, AppConfig};
|
||||
use crate::cli::Command;
|
||||
use crate::event::input_event::{Events, InputEvent};
|
||||
use crate::event::Key;
|
||||
@@ -67,6 +63,13 @@ mod utils;
|
||||
struct Cli {
|
||||
#[command(subcommand)]
|
||||
command: Option<Command>,
|
||||
#[arg(
|
||||
long,
|
||||
global = true,
|
||||
env = "MANAGARR_DISABLE_SPINNER",
|
||||
help = "Disable the spinner (can sometimes make parsing output challenging)"
|
||||
)]
|
||||
disable_spinner: bool,
|
||||
#[arg(
|
||||
long,
|
||||
global = true,
|
||||
@@ -91,6 +94,7 @@ async fn main() -> Result<()> {
|
||||
} else {
|
||||
confy::load("managarr", "config")?
|
||||
};
|
||||
let spinner_disabled = args.disable_spinner;
|
||||
config.validate();
|
||||
let reqwest_client = build_network_client(&config);
|
||||
let (sync_network_tx, sync_network_rx) = mpsc::channel(500);
|
||||
@@ -113,14 +117,10 @@ async fn main() -> Result<()> {
|
||||
match args.command {
|
||||
Some(command) => match command {
|
||||
Command::Radarr(_) | Command::Sonarr(_) => {
|
||||
config.verify_config_present_for_cli(&command);
|
||||
app.lock().await.cli_mode = true;
|
||||
let app_nw = Arc::clone(&app);
|
||||
let mut network = Network::new(&app_nw, cancellation_token, reqwest_client);
|
||||
|
||||
if let Err(e) = cli::handle_command(&app, command, &mut network).await {
|
||||
eprintln!("error: {}", e.to_string().red());
|
||||
process::exit(1);
|
||||
if spinner_disabled {
|
||||
start_cli_no_spinner(config, reqwest_client, cancellation_token, app, command).await;
|
||||
} else {
|
||||
start_cli_with_spinner(config, reqwest_client, cancellation_token, app, command).await;
|
||||
}
|
||||
}
|
||||
Command::Completions { shell } => {
|
||||
@@ -237,65 +237,6 @@ fn panic_hook(info: &PanicHookInfo<'_>) {
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn load_config(path: &str) -> Result<AppConfig> {
|
||||
let file = File::open(path).map_err(|e| anyhow!(e))?;
|
||||
let reader = BufReader::new(file);
|
||||
let config = serde_yaml::from_reader(reader)?;
|
||||
Ok(config)
|
||||
}
|
||||
|
||||
fn build_network_client(config: &AppConfig) -> Client {
|
||||
let mut client_builder = Client::builder()
|
||||
.pool_max_idle_per_host(10)
|
||||
.http2_keep_alive_interval(Duration::from_secs(5))
|
||||
.tcp_keepalive(Duration::from_secs(5));
|
||||
|
||||
if let Some(radarr_config) = &config.radarr {
|
||||
if let Some(ref cert_path) = &radarr_config.ssl_cert_path {
|
||||
let cert = create_cert(cert_path, "Radarr");
|
||||
client_builder = client_builder.add_root_certificate(cert);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(sonarr_config) = &config.sonarr {
|
||||
if let Some(ref cert_path) = &sonarr_config.ssl_cert_path {
|
||||
let cert = create_cert(cert_path, "Sonarr");
|
||||
client_builder = client_builder.add_root_certificate(cert);
|
||||
}
|
||||
}
|
||||
|
||||
match client_builder.build() {
|
||||
Ok(client) => client,
|
||||
Err(e) => {
|
||||
error!("Unable to create reqwest client: {}", e);
|
||||
eprintln!("error: {}", e.to_string().red());
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn create_cert(cert_path: &String, servarr_name: &str) -> Certificate {
|
||||
match fs::read(cert_path) {
|
||||
Ok(cert) => match Certificate::from_pem(&cert) {
|
||||
Ok(certificate) => certificate,
|
||||
Err(_) => {
|
||||
log_and_print_error(format!(
|
||||
"Unable to read the specified {} SSL certificate",
|
||||
servarr_name
|
||||
));
|
||||
process::exit(1);
|
||||
}
|
||||
},
|
||||
Err(_) => {
|
||||
log_and_print_error(format!(
|
||||
"Unable to open specified {} SSL certificate",
|
||||
servarr_name
|
||||
));
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(debug_assertions))]
|
||||
fn panic_hook(info: &PanicHookInfo<'_>) {
|
||||
use human_panic::{handle_dump, metadata, print_msg};
|
||||
|
||||
Reference in New Issue
Block a user