First commit in rust

This commit is contained in:
2026-02-19 13:51:07 +08:00
commit c37ca9ba52
73 changed files with 9737 additions and 0 deletions

View 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]);
}
}