From 281dddb19f88543bef2edeeeedbcfb7b7c62d346 Mon Sep 17 00:00:00 2001 From: Candifloss Date: Tue, 20 Jan 2026 22:04:21 +0530 Subject: [PATCH] Loop TUI until successful auth --- src/main.rs | 13 ++----------- src/tui.rs | 24 ++++++++++++++++++++---- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/main.rs b/src/main.rs index e3da23a..4b802ee 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,16 +4,7 @@ mod tui; use std::io; fn main() -> io::Result<()> { - let (username, password) = tui::run()?; - - match auth::authenticate(&username, &password) { - Ok(()) => { - println!("authentication successful"); - } - Err(_) => { - println!("authentication failed"); - } - } - + let username = tui::run(|u, p| auth::authenticate(u, p).is_ok())?; + println!("authenticated as {username}"); Ok(()) } diff --git a/src/tui.rs b/src/tui.rs index 32ea302..9a88965 100644 --- a/src/tui.rs +++ b/src/tui.rs @@ -14,7 +14,10 @@ use std::io; /// Runs the TUI and returns the entered username and password. /// This module owns all terminal state. -pub fn run() -> io::Result<(String, String)> { +pub fn run(auth_fn: F) -> io::Result +where + F: Fn(&str, &str) -> bool, +{ enable_raw_mode()?; let mut stdout = io::stdout(); execute!(stdout, EnterAlternateScreen)?; @@ -22,6 +25,8 @@ pub fn run() -> io::Result<(String, String)> { let backend = CrosstermBackend::new(stdout); let mut terminal = Terminal::new(backend)?; + let mut error_msg: Option<&str> = None; + let mut username = String::new(); let mut password = String::new(); let mut focus = 0; @@ -30,7 +35,11 @@ pub fn run() -> io::Result<(String, String)> { terminal.draw(|f| { let chunks = Layout::default() .direction(Direction::Vertical) - .constraints([Constraint::Length(3), Constraint::Length(3)]) + .constraints([ + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(2), + ]) .split(f.area()); let user = Paragraph::new(username.as_str()) @@ -51,8 +60,11 @@ pub fn run() -> io::Result<(String, String)> { Style::default() }); + let error = Paragraph::new(error_msg.unwrap_or("")).style(Style::new().fg(Color::Red)); + f.render_widget(user, chunks[0]); f.render_widget(pass, chunks[1]); + f.render_widget(error, chunks[2]); })?; if let Event::Key(key) = event::read()? { @@ -61,7 +73,11 @@ pub fn run() -> io::Result<(String, String)> { KeyCode::Tab => focus = (focus + 1) % 2, KeyCode::Enter => { if !username.is_empty() && !password.is_empty() { - break; + if auth_fn(&username, &password) { + break; + } + password.clear(); + error_msg = Some("Authentication failed"); } } @@ -87,5 +103,5 @@ pub fn run() -> io::Result<(String, String)> { disable_raw_mode()?; execute!(terminal.backend_mut(), LeaveAlternateScreen)?; - Ok((username, password)) + Ok(username) }