171 lines
4.3 KiB
Rust
171 lines
4.3 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::*;
|
|
use crate::{matrix, style};
|
|
|
|
/// 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,
|
|
/// The text of an error message
|
|
error: Option<String>,
|
|
|
|
/// 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),
|
|
/// Login completed.
|
|
LoggedIn(matrix_sdk::Client),
|
|
/// Hide the error message.
|
|
ResetError,
|
|
}
|
|
|
|
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,
|
|
Login => {
|
|
self.waiting = true;
|
|
let homeserver = self.homeserver.clone();
|
|
let user = self.user.clone();
|
|
let password = self.password.clone();
|
|
let command = async move {
|
|
let client = match matrix::login(&homeserver, &user, &password).await {
|
|
Ok(client) => client,
|
|
Err(e) => return LoginFailed(e.to_string()),
|
|
};
|
|
LoggedIn(client)
|
|
};
|
|
return Command::perform(command, super::Message::from);
|
|
}
|
|
LoginFailed(error) => {
|
|
self.waiting = false;
|
|
self.error = Some(error);
|
|
}
|
|
LoggedIn(_) => (),
|
|
ResetError => self.error = None,
|
|
};
|
|
Command::none()
|
|
}
|
|
|
|
/// Generate widgets for this view
|
|
pub fn view(&mut self) -> Element<super::Message> {
|
|
let error_message: iced::Element<_> = match self.error {
|
|
Some(ref error) => Container::new(Text::new(error.clone()))
|
|
.center_x()
|
|
.width(Length::Fill)
|
|
.padding(5)
|
|
.style(style::container::Error)
|
|
.into(),
|
|
None => Space::new(0.into(), 0.into()).into(),
|
|
};
|
|
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::alignment::Horizontal::Center)
|
|
.width(Length::Fill),
|
|
)
|
|
.on_press(Message::Login.into())
|
|
.width(Length::Fill);
|
|
|
|
let mut column = Column::new()
|
|
.width(500.into())
|
|
.push(error_message)
|
|
.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("Logging 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)
|
|
}
|
|
}
|