retrix/src/ui/login.rs

145 lines
3.6 KiB
Rust

//! The login prompt
use iced::{
widget::{button::State as ButtonState, text_input::State as InputState},
Button, Column, Command, Container, Element, Length, Space, Text, TextInput, Toggler,
};
use self::Message::{InputHomeserver, InputPassword, InputUser, LoginFailed, TogglePassword};
/// Data for the login prompt
#[derive(Debug, Default)]
pub struct Login {
/// The username
user: String,
/// The password
password: String,
/// Whether the password should be visible.
show_password: bool,
/// The homeserver URL.
homeserver: String,
/// Whether we're waiting for a response to a login attempt
waiting: bool,
/// Widget state
state: State,
}
/// Login prompt widget state
#[derive(Debug, Default)]
pub struct State {
/// State for the login input
user: InputState,
/// State from the password input
password: InputState,
/// State for the homeserver input
homeserver: InputState,
/// State for the login button
login: ButtonState,
}
/// Notification to change the state for the login view.
#[derive(Debug, Clone)]
pub enum Message {
/// The login input changed.
InputUser(String),
/// The password input changed.
InputPassword(String),
/// The homerserver input changed.
InputHomeserver(String),
/// The "show password" toggle has been switched.
TogglePassword(bool),
/// Triggers login
Login,
/// A login attempt failed
LoginFailed(String),
}
impl Login {
/// Update state
pub fn update(&mut self, message: Message) -> Command<super::Message> {
match message {
InputUser(input) => self.user = input,
InputPassword(input) => self.password = input,
InputHomeserver(input) => self.homeserver = input,
TogglePassword(toggle) => self.show_password = toggle,
Message::Login => {
self.waiting = true;
let command = async {
std::thread::sleep_ms(1000);
super::Message::from(LoginFailed(String::from("Not implemented :(")))
};
return command.into();
}
LoginFailed(error) => {
self.waiting = false;
}
};
Command::none()
}
/// Generate widgets for this view
pub fn view(&mut self) -> Element<super::Message> {
let user_input =
TextInput::new(&mut self.state.user, "alice", &self.user, |i| InputUser(i).into())
.padding(5);
let mut password_input =
TextInput::new(&mut self.state.password, "verysecret", &self.password, |i| {
InputPassword(i).into()
})
.padding(5);
if !self.show_password {
password_input = password_input.password();
}
let password_toggle =
Toggler::new(self.show_password, String::from("show password"), |b| {
TogglePassword(b).into()
})
.text_size(15);
let homeserver_input = TextInput::new(
&mut self.state.homeserver,
"https://matrix.org",
&self.homeserver,
|i| InputHomeserver(i).into(),
)
.padding(5);
let login_button = Button::new(
&mut self.state.login,
Text::new("Log in")
.horizontal_alignment(iced::HorizontalAlignment::Center)
.width(Length::Fill),
)
.on_press(Message::Login.into())
.width(Length::Fill);
let mut column = Column::new()
.width(500.into())
.push(Text::new("User name"))
.push(user_input)
.push(Space::with_height(10.into()))
.push(Text::new("Password"))
.push(password_input)
.push(password_toggle)
.push(Space::with_height(5.into()))
.push(Text::new("Homeserver address"))
.push(homeserver_input)
.push(login_button);
if self.waiting {
column = column.push(Text::new("Loggin in"));
}
Container::new(column).center_x().center_y().width(Length::Fill).height(Length::Fill).into()
}
}
impl From<Message> for super::Message {
fn from(message: Message) -> Self {
super::Message::Login(message)
}
}