Skip to main content

gitv_tui/app/
mod.rs

1use anyhow::anyhow;
2use inquire::Password;
3
4use crate::app::cli::Cli;
5use crate::auth::AuthProvider;
6use crate::errors::AppError;
7use crate::github::GithubClient;
8use crate::logging::LoggingConfig;
9use crate::{logging, ui};
10use std::sync::OnceLock;
11
12pub struct App {
13    pub owner: String,
14    pub repo: String,
15}
16
17pub static GITHUB_CLIENT: OnceLock<GithubClient> = OnceLock::new();
18
19impl App {
20    pub async fn new(cli: Cli) -> Result<Self, AppError> {
21        logging::init(LoggingConfig::new(cli.args.log_level))?;
22        let auth = if cli.args.env {
23            Box::new(crate::auth::env::EnvAuth) as Box<dyn AuthProvider>
24        } else {
25            Box::new(crate::auth::keyring::KeyringAuth::new("gitv")?) as Box<dyn AuthProvider>
26        };
27        let token = match auth.get_token().ok() {
28            Some(token) => token,
29            None => Self::handle_no_token(&auth)?,
30        };
31        let github = GithubClient::new(Some(token))?;
32        let _ = GITHUB_CLIENT.set(github);
33        Ok(Self {
34            owner: cli.args.owner.unwrap_or_default(),
35            repo: cli.args.repo.unwrap_or_default(),
36        })
37    }
38
39    pub async fn run(&mut self) -> Result<(), AppError> {
40        use crate::ui::AppState;
41        let current_user = GITHUB_CLIENT
42            .get()
43            .ok_or_else(|| AppError::Other(anyhow!("github client is not initialized")))?
44            .inner()
45            .current()
46            .user()
47            .await?
48            .login;
49
50        let ap = AppState::new(self.repo.clone(), self.owner.clone(), current_user);
51        ui::run(ap).await
52    }
53
54    pub fn handle_no_token(auth: &impl AuthProvider) -> Result<String, AppError> {
55        let prompt = Password::new("No token found. Please enter your github token")
56            .with_display_toggle_enabled()
57            .without_confirmation()
58            .with_display_mode(inquire::PasswordDisplayMode::Masked);
59        let token = prompt.prompt()?;
60        auth.set_token(&token)?;
61        Ok(token)
62    }
63}
64
65pub mod cli;