added padding_pct
This commit is contained in:
parent
f8854de25c
commit
e2776996ef
File diff suppressed because it is too large
Load Diff
|
@ -17,11 +17,12 @@ pub enum Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Component {
|
impl Component {
|
||||||
fn debug(&self) -> String {
|
#[cfg(test)]
|
||||||
|
pub fn debug(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
Component::NextLine => "NextLine".to_string(),
|
Component::NextLine => "NextLine".to_string(),
|
||||||
Component::X(x) => format!("X({})", x),
|
Component::X(x) => format!("X({})", x),
|
||||||
Component::String(s) => format!("\"{}\"", s),
|
Component::String(s) => format!("\"{}\"({})", s, s.len()),
|
||||||
Component::Fg(c) => format!("FG({:#?})", c)
|
Component::Fg(c) => format!("FG({:#?})", c)
|
||||||
.replace('\n', "")
|
.replace('\n', "")
|
||||||
.replace(' ', ""),
|
.replace(' ', ""),
|
||||||
|
@ -564,7 +565,7 @@ mod tests {
|
||||||
"Scrollable widget: no scrolling",
|
"Scrollable widget: no scrolling",
|
||||||
Instruction::start()
|
Instruction::start()
|
||||||
.fixed(10, vec![scrolling_widget]),
|
.fixed(10, vec![scrolling_widget]),
|
||||||
(0..10)
|
(90..100)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|num| {
|
.map(|num| {
|
||||||
vec![
|
vec![
|
||||||
|
@ -587,7 +588,7 @@ mod tests {
|
||||||
(
|
(
|
||||||
"Scrollable widget: scrolled by 3",
|
"Scrollable widget: scrolled by 3",
|
||||||
Instruction::start().fixed(10, vec![scrolled_by_3]),
|
Instruction::start().fixed(10, vec![scrolled_by_3]),
|
||||||
(0..10)
|
(87..97)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|num| {
|
.map(|num| {
|
||||||
vec![
|
vec![
|
||||||
|
|
|
@ -166,10 +166,14 @@ impl PlanState {
|
||||||
action: Action,
|
action: Action,
|
||||||
scr: &mut Screen,
|
scr: &mut Screen,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
|
let term_size = termion::terminal_size()?;
|
||||||
let mut new = match action {
|
let mut new = match action {
|
||||||
Action::ReplaceAll(layers) => {
|
Action::ReplaceAll(layers) => Self::new(
|
||||||
Self::from_plans(layers, self.base_colorset)?
|
layers,
|
||||||
}
|
self.base_colorset,
|
||||||
|
term_size,
|
||||||
|
self.last_render,
|
||||||
|
),
|
||||||
Action::ReplaceLayer(layer, index) => {
|
Action::ReplaceLayer(layer, index) => {
|
||||||
if index >= self.plans.len() {
|
if index >= self.plans.len() {
|
||||||
return Err(anyhow::anyhow!(
|
return Err(anyhow::anyhow!(
|
||||||
|
@ -184,12 +188,22 @@ impl PlanState {
|
||||||
Action::PushLayer(layer) => {
|
Action::PushLayer(layer) => {
|
||||||
let mut layers = self.plans;
|
let mut layers = self.plans;
|
||||||
layers.push(layer);
|
layers.push(layer);
|
||||||
Self::from_plans(layers, self.base_colorset)?
|
Self::new(
|
||||||
|
layers,
|
||||||
|
self.base_colorset,
|
||||||
|
term_size,
|
||||||
|
self.last_render,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Action::PopLayer => {
|
Action::PopLayer => {
|
||||||
let mut layers = self.plans;
|
let mut layers = self.plans;
|
||||||
layers.pop();
|
layers.pop();
|
||||||
Self::from_plans(layers, self.base_colorset)?
|
Self::new(
|
||||||
|
layers,
|
||||||
|
self.base_colorset,
|
||||||
|
term_size,
|
||||||
|
self.last_render,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Action::Nothing => return Ok(self),
|
Action::Nothing => return Ok(self),
|
||||||
};
|
};
|
||||||
|
@ -215,6 +229,9 @@ where
|
||||||
let mut plans =
|
let mut plans =
|
||||||
PlanState::from_plans(view.init()?, base_colorset)?;
|
PlanState::from_plans(view.init()?, base_colorset)?;
|
||||||
plans.render(&mut screen)?;
|
plans.render(&mut screen)?;
|
||||||
|
// FIXME: current loop means that pasting a string with len >1
|
||||||
|
// results in only the first character being rendered, until
|
||||||
|
// something else triggers a render
|
||||||
loop {
|
loop {
|
||||||
if let Some(msg) = view.query() {
|
if let Some(msg) = view.query() {
|
||||||
plans = plans.act_on(
|
plans = plans.act_on(
|
||||||
|
|
|
@ -5,6 +5,7 @@ pub enum Token {
|
||||||
Centered(Box<Token>),
|
Centered(Box<Token>),
|
||||||
Limited(Box<Token>, usize),
|
Limited(Box<Token>, usize),
|
||||||
CharPad(Box<Token>, char, usize),
|
CharPad(Box<Token>, char, usize),
|
||||||
|
PadPercent(Box<Token>, u8),
|
||||||
Fg(Box<Token>, Color),
|
Fg(Box<Token>, Color),
|
||||||
Bg(Box<Token>, Color),
|
Bg(Box<Token>, Color),
|
||||||
Link(Box<Token>, String),
|
Link(Box<Token>, String),
|
||||||
|
@ -51,18 +52,41 @@ impl Token {
|
||||||
Self::CharPad(Box::new(self), ' ', pad_to)
|
Self::CharPad(Box::new(self), ' ', pad_to)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn str_len(&self) -> usize {
|
pub fn pad_percent(self, pct: u8) -> Self {
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
if pct > 100 {
|
||||||
|
panic!("pad_percent with >100% width: {}", pct);
|
||||||
|
}
|
||||||
|
Self::PadPercent(Box::new(self), 100.min(pct))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns (str_count, str_len_total)
|
||||||
|
pub fn str_len(&self, total_width: usize) -> (usize, usize) {
|
||||||
match self {
|
match self {
|
||||||
Token::String(t, s) => s.len() + t.str_len(),
|
Token::String(t, s) => {
|
||||||
Token::Fg(t, _) => t.str_len(),
|
let (count, len) = t.str_len(total_width);
|
||||||
Token::Bg(t, _) => t.str_len(),
|
(count + 1, len + s.len())
|
||||||
Token::Link(t, _) => t.str_len(),
|
}
|
||||||
Token::Centered(t) => t.str_len(),
|
Token::Fg(t, _) => t.str_len(total_width),
|
||||||
Token::Limited(t, lim) => (*lim).min(t.str_len()),
|
Token::Bg(t, _) => t.str_len(total_width),
|
||||||
Token::CharPad(t, _, pad_to) => {
|
Token::Link(t, _) => t.str_len(total_width),
|
||||||
(*pad_to).max(t.str_len())
|
Token::Centered(t) => t.str_len(total_width),
|
||||||
|
Token::Limited(t, lim) => {
|
||||||
|
let (count, len) = t.str_len(total_width);
|
||||||
|
(count, (*lim).min(len))
|
||||||
|
}
|
||||||
|
Token::CharPad(t, _, pad_to) => {
|
||||||
|
let (count, len) = t.str_len(total_width);
|
||||||
|
(count, (*pad_to).max(len))
|
||||||
|
}
|
||||||
|
Token::End => (0, 0),
|
||||||
|
Token::PadPercent(t, pct) => {
|
||||||
|
let (count, len) = t.str_len(total_width);
|
||||||
|
(
|
||||||
|
count,
|
||||||
|
((*pct as usize * total_width) / 100).max(len),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Token::End => 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,6 +102,7 @@ impl Token {
|
||||||
Token::Link(next, _) => next.has_centered(),
|
Token::Link(next, _) => next.has_centered(),
|
||||||
Token::String(next, _) => next.has_centered(),
|
Token::String(next, _) => next.has_centered(),
|
||||||
Token::End => false,
|
Token::End => false,
|
||||||
|
Token::PadPercent(next, _) => next.has_centered(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,13 +138,13 @@ impl Token {
|
||||||
.chain(t.with_width(width))
|
.chain(t.with_width(width))
|
||||||
.collect(),
|
.collect(),
|
||||||
Token::Link(t, name) => {
|
Token::Link(t, name) => {
|
||||||
vec![Component::Link(name, t.str_len())]
|
vec![Component::Link(name, t.str_len(width).1)]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(t.with_width(width))
|
.chain(t.with_width(width))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
Token::Centered(cnt) => {
|
Token::Centered(cnt) => {
|
||||||
let mut str_len = cnt.str_len();
|
let mut str_len = cnt.str_len(width).1;
|
||||||
let components = if str_len > width {
|
let components = if str_len > width {
|
||||||
str_len = width;
|
str_len = width;
|
||||||
cnt.limited(width).with_width(width)
|
cnt.limited(width).with_width(width)
|
||||||
|
@ -170,6 +195,43 @@ impl Token {
|
||||||
.chain(t.with_width(width))
|
.chain(t.with_width(width))
|
||||||
.collect(),
|
.collect(),
|
||||||
Token::End => vec![],
|
Token::End => vec![],
|
||||||
|
Token::PadPercent(next, pct) => {
|
||||||
|
// FIXME: I feel like this'll be a problem
|
||||||
|
// at some point but I cba to deal with it rn
|
||||||
|
let (str_cnt, str_len) = next.str_len(width);
|
||||||
|
let actual_pad = (pct as usize * width) / 100;
|
||||||
|
let mut str_idx = 0;
|
||||||
|
next.with_width(width)
|
||||||
|
.into_iter()
|
||||||
|
.map(|comp| {
|
||||||
|
if let Component::String(s) = comp {
|
||||||
|
str_idx += 1;
|
||||||
|
if str_idx != str_cnt {
|
||||||
|
// Continue as this isn't the end
|
||||||
|
Component::String(s)
|
||||||
|
} else if str_len >= actual_pad {
|
||||||
|
// FIXME: this is probably THE BAD
|
||||||
|
Component::String({
|
||||||
|
let mut s = s;
|
||||||
|
s.truncate(
|
||||||
|
actual_pad
|
||||||
|
- (str_len - s.len()),
|
||||||
|
);
|
||||||
|
s
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Component::String(format!(
|
||||||
|
"{}{}",
|
||||||
|
s,
|
||||||
|
" ".repeat(actual_pad - str_len)
|
||||||
|
))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
comp
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,7 +242,7 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_token_gen() {
|
fn test_token_gen() {
|
||||||
const WIDTH: usize = 20;
|
const WIDTH: usize = 100;
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
"string -> string",
|
"string -> string",
|
||||||
|
@ -281,6 +343,48 @@ mod tests {
|
||||||
Component::String("learn more".into()),
|
Component::String("learn more".into()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
(
|
||||||
|
"padding percentage",
|
||||||
|
Token::text("this gets longer").pad_percent(100),
|
||||||
|
vec![Component::String(
|
||||||
|
"this gets longer".to_string()
|
||||||
|
+ &" "
|
||||||
|
.repeat(WIDTH - "this gets longer".len()),
|
||||||
|
)],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"pad percent with centering",
|
||||||
|
Token::text("all to the middle")
|
||||||
|
.pad_percent(60)
|
||||||
|
.centered(),
|
||||||
|
vec![
|
||||||
|
Component::X((WIDTH - (WIDTH * 60) / 100) / 2),
|
||||||
|
Component::String(
|
||||||
|
"all to the middle".to_string()
|
||||||
|
+ &" ".repeat(
|
||||||
|
((WIDTH * 60) / 100)
|
||||||
|
- "all to the middle".len(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"two strings, padded pct",
|
||||||
|
Token::text("two")
|
||||||
|
.bg(Color::BLUE)
|
||||||
|
.string("one")
|
||||||
|
.pad_percent(80)
|
||||||
|
.centered(),
|
||||||
|
vec![
|
||||||
|
Component::X((WIDTH - ((WIDTH * 80) / 100)) / 2),
|
||||||
|
Component::String("one".into()),
|
||||||
|
Component::Bg(Color::BLUE),
|
||||||
|
Component::String(
|
||||||
|
"two".to_string()
|
||||||
|
+ &" ".repeat(((WIDTH * 80) / 100) - 6),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
]
|
]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.for_each(|(name, token, expected)| {
|
.for_each(|(name, token, expected)| {
|
||||||
|
@ -298,12 +402,12 @@ mod tests {
|
||||||
assert!(
|
assert!(
|
||||||
exp == *act,
|
exp == *act,
|
||||||
"<{}>: component at index {} mismatch.
|
"<{}>: component at index {} mismatch.
|
||||||
expected:\n{:#?}
|
expected:\n{}
|
||||||
actual:\n{:#?}",
|
actual:\n{}",
|
||||||
&name,
|
&name,
|
||||||
i,
|
i,
|
||||||
exp,
|
exp.debug(),
|
||||||
act,
|
act.debug(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -21,7 +21,11 @@ impl From<termion::event::Key> for Key {
|
||||||
termion::event::Key::Delete => Self::Delete,
|
termion::event::Key::Delete => Self::Delete,
|
||||||
termion::event::Key::Insert => Self::Insert,
|
termion::event::Key::Insert => Self::Insert,
|
||||||
termion::event::Key::F(f) => Self::F(f),
|
termion::event::Key::F(f) => Self::F(f),
|
||||||
termion::event::Key::Char(c) => Self::Char(c),
|
termion::event::Key::Char(c) => match c {
|
||||||
|
'\n' => Self::Return,
|
||||||
|
'\t' => Self::Tab,
|
||||||
|
_ => Self::Char(c),
|
||||||
|
},
|
||||||
termion::event::Key::Alt(c) => Self::Alt(c),
|
termion::event::Key::Alt(c) => Self::Alt(c),
|
||||||
termion::event::Key::Ctrl(c) => Self::Ctrl(c),
|
termion::event::Key::Ctrl(c) => Self::Ctrl(c),
|
||||||
termion::event::Key::Null => Self::Null,
|
termion::event::Key::Null => Self::Null,
|
||||||
|
@ -51,4 +55,6 @@ pub enum Key {
|
||||||
Ctrl(char),
|
Ctrl(char),
|
||||||
Null,
|
Null,
|
||||||
Esc,
|
Esc,
|
||||||
|
Return,
|
||||||
|
Tab,
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,11 +8,13 @@ edition = "2021"
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.68"
|
anyhow = "1.0.68"
|
||||||
kkdisp = { version = "0.1.0", path = "../kkdisp" }
|
kkdisp = { version = "0.1.0", path = "../kkdisp" }
|
||||||
|
futures = "0.3.25"
|
||||||
|
|
||||||
[dependencies.tokio]
|
[dependencies.tokio]
|
||||||
version = "1.24.2"
|
version = "1.24.2"
|
||||||
features = ["full"]
|
features = ["full"]
|
||||||
|
|
||||||
[dependencies.misskey]
|
[dependencies.misskey]
|
||||||
version = "*"
|
git = "https://github.com/coord-e/misskey-rs"
|
||||||
|
branch = "develop"
|
||||||
features = ["websocket-client"]
|
features = ["websocket-client"]
|
||||||
|
|
107
kkx/src/login.rs
107
kkx/src/login.rs
|
@ -1,3 +1,4 @@
|
||||||
|
use futures::stream::TryStreamExt;
|
||||||
use kkdisp::{
|
use kkdisp::{
|
||||||
component::{Plan, Widget},
|
component::{Plan, Widget},
|
||||||
theme::Color,
|
theme::Color,
|
||||||
|
@ -5,6 +6,8 @@ use kkdisp::{
|
||||||
view::{Event, Key},
|
view::{Event, Key},
|
||||||
Action,
|
Action,
|
||||||
};
|
};
|
||||||
|
use misskey::{StreamingClientExt, WebSocketClient};
|
||||||
|
use tokio::sync::mpsc::{self, Receiver, Sender};
|
||||||
|
|
||||||
use crate::Message;
|
use crate::Message;
|
||||||
pub enum LoginFocus {
|
pub enum LoginFocus {
|
||||||
|
@ -27,15 +30,7 @@ pub struct LoginPrompt {
|
||||||
token: String,
|
token: String,
|
||||||
error: Option<String>,
|
error: Option<String>,
|
||||||
focus: LoginFocus,
|
focus: LoginFocus,
|
||||||
}
|
client: Option<WebSocketClient>,
|
||||||
|
|
||||||
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 {
|
impl LoginPrompt {
|
||||||
|
@ -45,9 +40,17 @@ impl LoginPrompt {
|
||||||
token: String::new(),
|
token: String::new(),
|
||||||
error: None,
|
error: None,
|
||||||
focus: LoginFocus::Hostname,
|
focus: LoginFocus::Hostname,
|
||||||
|
client: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn plan(&self) -> Plan {
|
||||||
|
Plan::start()
|
||||||
|
.fill(vec![])
|
||||||
|
.fixed(8, vec![Widget::new(100, self.tokens())])
|
||||||
|
.fill(vec![])
|
||||||
|
}
|
||||||
|
|
||||||
fn backspace(&mut self) {
|
fn backspace(&mut self) {
|
||||||
match self.focus {
|
match self.focus {
|
||||||
LoginFocus::Hostname => {
|
LoginFocus::Hostname => {
|
||||||
|
@ -59,11 +62,26 @@ impl LoginPrompt {
|
||||||
LoginFocus::OK => {}
|
LoginFocus::OK => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn query(&mut self) -> Option<()> {
|
||||||
pub fn attempt(&self) -> Result<(), anyhow::Error> {
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn attempt(&mut self) {
|
||||||
|
let hostname = self.hostname.clone();
|
||||||
|
if hostname.len() == 0 {
|
||||||
|
self.error = Some("empty hostname".into());
|
||||||
|
self.focus = LoginFocus::Hostname;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let token = self.token.clone();
|
||||||
|
if token.len() == 0 {
|
||||||
|
self.error = Some("empty token".into());
|
||||||
|
self.focus = LoginFocus::Token;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn update(
|
pub fn update(
|
||||||
&mut self,
|
&mut self,
|
||||||
event: Event<Message>,
|
event: Event<Message>,
|
||||||
|
@ -71,13 +89,29 @@ impl LoginPrompt {
|
||||||
match event {
|
match event {
|
||||||
Event::Link(lnk) => {
|
Event::Link(lnk) => {
|
||||||
if lnk == "ok" {
|
if lnk == "ok" {
|
||||||
todo!()
|
self.attempt();
|
||||||
|
Ok(Action::ReplaceAll(vec![self.plan()]))
|
||||||
|
} else if lnk == "token" {
|
||||||
|
self.focus = LoginFocus::Token;
|
||||||
|
Ok(Action::ReplaceAll(vec![self.plan()]))
|
||||||
|
} else if lnk == "hostname" {
|
||||||
|
self.focus = LoginFocus::Hostname;
|
||||||
|
Ok(Action::ReplaceAll(vec![self.plan()]))
|
||||||
} else {
|
} else {
|
||||||
Ok(Action::Nothing)
|
Ok(Action::Nothing)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Event::Input(input) => {
|
Event::Input(input) => {
|
||||||
match input {
|
match input {
|
||||||
|
Key::Return => match self.focus {
|
||||||
|
LoginFocus::Hostname => {
|
||||||
|
self.focus = LoginFocus::Token;
|
||||||
|
}
|
||||||
|
LoginFocus::Token => {
|
||||||
|
self.focus = LoginFocus::OK;
|
||||||
|
}
|
||||||
|
LoginFocus::OK => self.attempt(),
|
||||||
|
},
|
||||||
Key::Backspace => self.backspace(),
|
Key::Backspace => self.backspace(),
|
||||||
Key::Up => {
|
Key::Up => {
|
||||||
self.focus = match self.focus {
|
self.focus = match self.focus {
|
||||||
|
@ -93,24 +127,11 @@ impl LoginPrompt {
|
||||||
LoginFocus::OK => LoginFocus::Hostname,
|
LoginFocus::OK => LoginFocus::Hostname,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Key::Char(c) => {
|
Key::Char(c) => match self.focus {
|
||||||
if c == '\n' {
|
LoginFocus::Hostname => self.hostname.push(c),
|
||||||
if self.focus.ok() {
|
LoginFocus::Token => self.token.push(c),
|
||||||
self.attempt()?;
|
LoginFocus::OK => {}
|
||||||
}
|
},
|
||||||
} 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) => {
|
Key::Ctrl(c) => {
|
||||||
if c == 'u' || c == 'U' {
|
if c == 'u' || c == 'U' {
|
||||||
match self.focus {
|
match self.focus {
|
||||||
|
@ -131,16 +152,17 @@ impl LoginPrompt {
|
||||||
return Ok(Action::Nothing);
|
return Ok(Action::Nothing);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(Action::ReplaceAll(vec![(&*self).into()]))
|
Ok(Action::ReplaceAll(vec![self.plan()]))
|
||||||
}
|
}
|
||||||
Event::Message(_) => todo!(),
|
Event::Message(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tokens(&self) -> Vec<Token> {
|
fn tokens(&self) -> Vec<Token> {
|
||||||
let mut hostname =
|
const HOSTNAME_PROMPT: &str = "hostname: ";
|
||||||
Token::text(self.hostname.clone()).padded(10);
|
const TOKEN_PROMPT: &str = "token: ";
|
||||||
let mut token = Token::text(self.token.clone()).padded(10);
|
let mut hostname = Token::text(self.hostname.clone());
|
||||||
|
let mut token = Token::text(self.token.clone());
|
||||||
let mut ok = Token::text("[ok]");
|
let mut ok = Token::text("[ok]");
|
||||||
match self.focus {
|
match self.focus {
|
||||||
LoginFocus::Hostname => {
|
LoginFocus::Hostname => {
|
||||||
|
@ -156,11 +178,22 @@ impl LoginPrompt {
|
||||||
.centered(),
|
.centered(),
|
||||||
Token::End,
|
Token::End,
|
||||||
match &self.error {
|
match &self.error {
|
||||||
Some(e) => Token::text(e).fg(Color::RED),
|
Some(e) => Token::text(e)
|
||||||
|
.fg(Color::RED)
|
||||||
|
.pad_percent(80)
|
||||||
|
.centered(),
|
||||||
None => Token::End,
|
None => Token::End,
|
||||||
},
|
},
|
||||||
hostname.string("hostname: ").centered(),
|
hostname
|
||||||
token.string("token: ").centered(),
|
.string(HOSTNAME_PROMPT)
|
||||||
|
.link("hostname")
|
||||||
|
.pad_percent(80)
|
||||||
|
.centered(),
|
||||||
|
token
|
||||||
|
.string(TOKEN_PROMPT)
|
||||||
|
.link("token")
|
||||||
|
.pad_percent(80)
|
||||||
|
.centered(),
|
||||||
ok.link("ok").centered(),
|
ok.link("ok").centered(),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ pub enum Page {
|
||||||
impl Page {
|
impl Page {
|
||||||
fn init(&self) -> Result<PlanLayers, anyhow::Error> {
|
fn init(&self) -> Result<PlanLayers, anyhow::Error> {
|
||||||
match self {
|
match self {
|
||||||
Page::Login(log) => Ok(vec![log.into()]),
|
Page::Login(log) => Ok(vec![log.plan()]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue