kkx/kkx/src/login.rs

168 lines
4.9 KiB
Rust

use kkdisp::{
component::{Plan, Widget},
theme::Color,
token::Token,
view::{Event, Key},
Action,
};
use crate::Message;
pub enum LoginFocus {
Hostname,
Token,
OK,
}
impl LoginFocus {
fn ok(&self) -> bool {
match self {
LoginFocus::OK => true,
_ => false,
}
}
}
pub struct LoginPrompt {
hostname: String,
token: String,
error: Option<String>,
focus: LoginFocus,
}
impl From<&LoginPrompt> for Plan {
fn from(value: &LoginPrompt) -> Self {
Plan::start()
.fill(vec![])
.fixed(8, vec![Widget::new(100, value.tokens())])
.fill(vec![])
}
}
impl LoginPrompt {
pub fn new() -> Self {
Self {
hostname: String::new(),
token: String::new(),
error: None,
focus: LoginFocus::Hostname,
}
}
fn backspace(&mut self) {
match self.focus {
LoginFocus::Hostname => {
self.hostname.pop();
}
LoginFocus::Token => {
self.token.pop();
}
LoginFocus::OK => {}
}
}
pub fn attempt(&self) -> Result<(), anyhow::Error> {
todo!()
}
pub fn update(
&mut self,
event: Event<Message>,
) -> Result<Action, anyhow::Error> {
match event {
Event::Link(lnk) => {
if lnk == "ok" {
todo!()
} else {
Ok(Action::Nothing)
}
}
Event::Input(input) => {
match input {
Key::Backspace => self.backspace(),
Key::Up => {
self.focus = match self.focus {
LoginFocus::Hostname => LoginFocus::OK,
LoginFocus::Token => LoginFocus::Hostname,
LoginFocus::OK => LoginFocus::Token,
};
}
Key::Down => {
self.focus = match self.focus {
LoginFocus::Hostname => LoginFocus::Token,
LoginFocus::Token => LoginFocus::OK,
LoginFocus::OK => LoginFocus::Hostname,
};
}
Key::Char(c) => {
if c == '\n' {
if self.focus.ok() {
self.attempt()?;
}
} else if c == '\t' {
} else {
match self.focus {
LoginFocus::Hostname => {
self.hostname.push(c)
}
LoginFocus::Token => {
self.token.push(c)
}
LoginFocus::OK => {}
}
}
}
Key::Ctrl(c) => {
if c == 'u' || c == 'U' {
match self.focus {
LoginFocus::Hostname => {
self.hostname = String::new();
}
LoginFocus::Token => {
self.token = String::new()
}
LoginFocus::OK => {}
}
}
}
Key::Esc => {
self.focus = LoginFocus::OK;
}
_ => {
return Ok(Action::Nothing);
}
};
Ok(Action::ReplaceAll(vec![(&*self).into()]))
}
Event::Message(_) => todo!(),
}
}
fn tokens(&self) -> Vec<Token> {
let mut hostname =
Token::text(self.hostname.clone()).padded(10);
let mut token = Token::text(self.token.clone()).padded(10);
let mut ok = Token::text("[ok]");
match self.focus {
LoginFocus::Hostname => {
hostname = hostname.bg(Color::BLUE)
}
LoginFocus::Token => token = token.bg(Color::BLUE),
LoginFocus::OK => ok = ok.bg(Color::BLUE),
};
vec![
Token::text("kkx cfg")
.bg(Color::BLUE)
.fg(Color::WHITE)
.centered(),
Token::End,
match &self.error {
Some(e) => Token::text(e).fg(Color::RED),
None => Token::End,
},
hostname.string("hostname: ").centered(),
token.string("token: ").centered(),
ok.link("ok").centered(),
]
}
}