From: Simon Tatham Date: Sun, 21 Jan 2024 11:27:49 +0000 (+0000) Subject: Prettify username and email in account registration. X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=476fab7eb82255f5cf90be4f2ad55338a22de00e;p=mastodonochrome.git Prettify username and email in account registration. The username is now shown with its domain suffix, but doesn't make you type that suffix. And the email is validated for basic syntax. --- diff --git a/Cargo.toml b/Cargo.toml index 38a73fe..6a8ec4d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ edition = "2021" chrono = { version = "0.4.31", features = ["serde"] } clap = { version = "4.4.12", features = ["derive"] } crossterm = "0.27.0" +email_address = "0.2.4" html2text = { version = "0.11.0", features = ["css"] } itertools = "0.12.0" lazy_static = "1.4.0" diff --git a/src/login.rs b/src/login.rs index cb12953..2a73ae2 100644 --- a/src/login.rs +++ b/src/login.rs @@ -1,6 +1,8 @@ +use email_address::EmailAddress; use reqwest::Url; use std::cell::RefCell; use std::rc::Rc; +use std::str::FromStr; use sys_locale::get_locale; use super::activity_stack::UtilityActivity; @@ -18,30 +20,75 @@ use super::tui::{ use super::types::{Account, Application, Instance}; use super::TopLevelError; -#[derive(Default)] -struct MandatoryString(String); +struct Username { + name: String, + domain: Rc>, +} -impl MandatoryString { +impl Username { fn ok(&self) -> bool { - !self.0.is_empty() + !self.name.is_empty() } } -impl EditableMenuLineData for MandatoryString { +impl EditableMenuLineData for Username { fn display(&self) -> ColouredString { - if self.0.is_empty() { + if self.name.is_empty() { ColouredString::uniform("none", 'r') } else { - ColouredString::plain(&self.0) + ColouredString::plain(&self.name) + + ColouredString::uniform( + &format!("@{}", self.domain.borrow()), + 'f', + ) } } fn to_text(&self) -> String { - self.0.clone() + self.name.clone() } fn update(&mut self, text: &str) { - *self = Self(text.to_owned()); + let text = text + .split_once('@') + .map_or(text, |(prefix, _)| prefix) + .trim(); + self.name = text.to_owned(); + } +} + +struct Email { + addr: String, +} + +impl Email { + fn ok(&self) -> bool { + EmailAddress::is_valid(&self.addr) + } +} + +impl EditableMenuLineData for Email { + fn display(&self) -> ColouredString { + if self.addr.is_empty() { + ColouredString::uniform("none", 'r') + } else if self.ok() { + ColouredString::plain(&self.addr) + + ColouredString::uniform(" valid", 'f') + } else { + ColouredString::plain(&self.addr) + + ColouredString::uniform(" invalid!", 'r') + } + } + + fn to_text(&self) -> String { + self.addr.clone() + } + + fn update(&mut self, text: &str) { + self.addr = match EmailAddress::from_str(text) { + Ok(addr) => addr.as_str().to_owned(), + Err(_) => text.to_owned(), + }; } } @@ -170,8 +217,8 @@ struct LoginMenu { para_login_url: Paragraph, el_logincode: EditableMenuLine, para_login_outcome: Paragraph, - el_username: EditableMenuLine, - el_email: EditableMenuLine, + el_username: EditableMenuLine, + el_email: EditableMenuLine, el_password: EditableMenuLine, el_password_confirm: EditableMenuLine, ml_rules: MenuKeypressLine, @@ -235,12 +282,17 @@ impl LoginMenu { let el_username = EditableMenuLine::new( Pr('N'), ColouredString::plain("Name of your new account: "), - MandatoryString::default(), + Username { + name: "".to_owned(), + domain: Rc::new(RefCell::new("".to_owned())), + }, ); let el_email = EditableMenuLine::new( Pr('E'), ColouredString::plain("Email address to associate with account: "), - MandatoryString::default(), + Email { + addr: "".to_owned(), + }, ); let password1 = Rc::new(RefCell::new("".to_owned())); let password2 = Rc::new(RefCell::new("".to_owned())); @@ -421,6 +473,8 @@ impl LoginMenu { ); self.para_server_id .push_text(ColouredString::uniform(".", 'H'), false); + *self.el_username.get_data().domain.borrow_mut() = + instance.domain.clone(); self.state = LoginState::ServerValid; LogicalAction::Nothing } @@ -593,8 +647,8 @@ impl LoginMenu { // Send the account registration request let token = client.register_account( - &self.el_username.get_data().0, - &self.el_email.get_data().0, + &self.el_username.get_data().name, + &self.el_email.get_data().addr, &self.el_password.get_data().this.borrow(), &language, )?; @@ -633,7 +687,10 @@ impl LoginMenu { false, ); self.para_login_outcome.push_text( - ColouredString::uniform(&self.el_email.get_data().0, 'K'), + ColouredString::uniform( + &self.el_email.get_data().addr, + 'K', + ), false, ); self.para_login_outcome.push_text(