First commit in rust
This commit is contained in:
98
backchannel-client/src/tui/views/login.rs
Normal file
98
backchannel-client/src/tui/views/login.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
use ratatui::{
|
||||
layout::{Alignment, Constraint, Direction, Layout},
|
||||
style::{Color, Modifier, Style},
|
||||
text::{Line, Span},
|
||||
widgets::{Block, Borders, Paragraph},
|
||||
Frame,
|
||||
};
|
||||
|
||||
use crate::tui::app::{App, LoginField};
|
||||
|
||||
pub fn draw(frame: &mut Frame, app: &App) {
|
||||
let area = frame.size();
|
||||
|
||||
// Centre a 50×12 box on screen.
|
||||
let v = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([
|
||||
Constraint::Percentage(30),
|
||||
Constraint::Length(14),
|
||||
Constraint::Min(0),
|
||||
])
|
||||
.split(area);
|
||||
|
||||
let h = Layout::default()
|
||||
.direction(Direction::Horizontal)
|
||||
.constraints([
|
||||
Constraint::Percentage(25),
|
||||
Constraint::Percentage(50),
|
||||
Constraint::Percentage(25),
|
||||
])
|
||||
.split(v[1]);
|
||||
|
||||
let box_area = h[1];
|
||||
|
||||
let mode_label = if app.login_register { "Register" } else { "Login" };
|
||||
|
||||
let outer = Block::default()
|
||||
.title(format!(" BackChannel — {} ", mode_label))
|
||||
.borders(Borders::ALL)
|
||||
.style(Style::default().fg(Color::Cyan));
|
||||
|
||||
frame.render_widget(outer, box_area);
|
||||
|
||||
let inner = Layout::default()
|
||||
.direction(Direction::Vertical)
|
||||
.constraints([
|
||||
Constraint::Length(1), // padding
|
||||
Constraint::Length(3), // username
|
||||
Constraint::Length(3), // password
|
||||
Constraint::Length(1), // padding
|
||||
Constraint::Length(1), // hint
|
||||
Constraint::Length(1), // status
|
||||
])
|
||||
.margin(1)
|
||||
.split(box_area);
|
||||
|
||||
// Username field
|
||||
let username_style = if app.login_field == LoginField::Username {
|
||||
Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD)
|
||||
} else {
|
||||
Style::default()
|
||||
};
|
||||
let username_widget = Paragraph::new(app.login_username.as_str())
|
||||
.block(Block::default().borders(Borders::ALL).title(" Username "))
|
||||
.style(username_style);
|
||||
frame.render_widget(username_widget, inner[1]);
|
||||
|
||||
// Password field (mask with asterisks)
|
||||
let password_style = if app.login_field == LoginField::Password {
|
||||
Style::default().fg(Color::Yellow).add_modifier(Modifier::BOLD)
|
||||
} else {
|
||||
Style::default()
|
||||
};
|
||||
let masked: String = "*".repeat(app.login_password.len());
|
||||
let password_widget = Paragraph::new(masked.as_str())
|
||||
.block(Block::default().borders(Borders::ALL).title(" Password "))
|
||||
.style(password_style);
|
||||
frame.render_widget(password_widget, inner[2]);
|
||||
|
||||
// Hints
|
||||
let hint = Paragraph::new(Line::from(vec![
|
||||
Span::raw("Tab: switch field | Enter: submit | "),
|
||||
Span::styled(
|
||||
if app.login_register { "T: switch to Login" } else { "T: switch to Register" },
|
||||
Style::default().fg(Color::DarkGray),
|
||||
),
|
||||
]))
|
||||
.alignment(Alignment::Center);
|
||||
frame.render_widget(hint, inner[4]);
|
||||
|
||||
// Status / error message
|
||||
if let Some(msg) = &app.status_msg {
|
||||
let status = Paragraph::new(msg.as_str())
|
||||
.style(Style::default().fg(Color::Red))
|
||||
.alignment(Alignment::Center);
|
||||
frame.render_widget(status, inner[5]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user