Move the login logic to a separate component
This commit is contained in:
parent
0755f2a0de
commit
206bb2ab83
|
@ -0,0 +1,124 @@
|
|||
use gtk::prelude::*;
|
||||
use relm4::prelude::*;
|
||||
|
||||
use crate::{
|
||||
api,
|
||||
settings::{self, get_current_account},
|
||||
};
|
||||
|
||||
pub struct LoginPage {}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LoginPageInput {
|
||||
Login(String, String, String),
|
||||
Cancel,
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
impl SimpleComponent for LoginPage {
|
||||
type Init = ();
|
||||
type Input = LoginPageInput;
|
||||
type Output = crate::AppMsg;
|
||||
|
||||
view! {
|
||||
gtk::Box {
|
||||
set_hexpand: true,
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
set_spacing: 12,
|
||||
set_margin_all: 20,
|
||||
set_valign: gtk::Align::Center,
|
||||
set_hexpand: true,
|
||||
|
||||
gtk::Label {
|
||||
set_text: "Login",
|
||||
add_css_class: "font-bold",
|
||||
},
|
||||
#[name(username)]
|
||||
gtk::Entry {
|
||||
set_placeholder_text: Some("Username or E-Mail"),
|
||||
},
|
||||
#[name(password)]
|
||||
gtk::PasswordEntry {
|
||||
set_placeholder_text: Some("Password"),
|
||||
set_show_peek_icon: true,
|
||||
},
|
||||
#[name(totp_token)]
|
||||
gtk::Entry {
|
||||
set_placeholder_text: Some("Totp token (Optional)"),
|
||||
},
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_halign: gtk::Align::End,
|
||||
gtk::Button {
|
||||
set_label: "Cancel",
|
||||
connect_clicked => LoginPageInput::Cancel,
|
||||
set_margin_end: 10,
|
||||
},
|
||||
gtk::Button {
|
||||
set_label: "Login",
|
||||
connect_clicked[sender, username, password, totp_token] => move |_| {
|
||||
let username_text = username.text().as_str().to_string();
|
||||
username.set_text("");
|
||||
let password_text = password.text().as_str().to_string();
|
||||
password.set_text("");
|
||||
let totp_token_text = totp_token.text().as_str().to_string();
|
||||
totp_token.set_text("");
|
||||
sender.input(LoginPageInput::Login(username_text, password_text, totp_token_text));
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn init(
|
||||
_init: Self::Init,
|
||||
root: &Self::Root,
|
||||
sender: ComponentSender<Self>,
|
||||
) -> ComponentParts<Self> {
|
||||
let model = Self {};
|
||||
let widgets = view_output!();
|
||||
ComponentParts { model, widgets }
|
||||
}
|
||||
|
||||
fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {
|
||||
match message {
|
||||
LoginPageInput::Login(username, password, totp_token) => {
|
||||
if get_current_account().instance_url.is_empty() {
|
||||
return;
|
||||
}
|
||||
let token = if totp_token.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(totp_token)
|
||||
};
|
||||
let _ = sender.output(crate::AppMsg::UpdateState(crate::AppState::Loading));
|
||||
|
||||
std::thread::spawn(move || {
|
||||
let message = match api::auth::login(username, password, token) {
|
||||
Ok(login) => {
|
||||
if let Some(token) = login.jwt {
|
||||
let mut account = settings::get_current_account();
|
||||
account.jwt = Some(token);
|
||||
settings::update_current_account(account.clone());
|
||||
if let Ok(site) = api::site::fetch_site() {
|
||||
let user = site.my_user.unwrap().local_user_view.person;
|
||||
account.name = user.name;
|
||||
account.id = user.id.0;
|
||||
settings::update_current_account(account);
|
||||
}
|
||||
crate::AppMsg::LoggedIn
|
||||
} else {
|
||||
crate::AppMsg::ShowMessage("Wrong credentials!".to_string())
|
||||
}
|
||||
}
|
||||
Err(err) => crate::AppMsg::ShowMessage(err.to_string()),
|
||||
};
|
||||
let _ = sender.output(message);
|
||||
});
|
||||
}
|
||||
LoginPageInput::Cancel => {
|
||||
let _ = sender.output(crate::AppMsg::StartFetchPosts(None, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ pub mod community_row;
|
|||
pub mod inbox_page;
|
||||
pub mod instance_row;
|
||||
pub mod instances_page;
|
||||
pub mod login_page;
|
||||
pub mod mention_row;
|
||||
pub mod post_page;
|
||||
pub mod post_row;
|
||||
|
|
104
src/main.rs
104
src/main.rs
|
@ -33,10 +33,11 @@ use relm4::{
|
|||
prelude::*,
|
||||
set_global_css,
|
||||
};
|
||||
use settings::get_current_account;
|
||||
|
||||
use crate::components::login_page::LoginPage;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
enum AppState {
|
||||
pub enum AppState {
|
||||
Loading,
|
||||
Posts,
|
||||
ChooseInstance,
|
||||
|
@ -60,6 +61,7 @@ struct App {
|
|||
communities_page: Controller<CommunitiesPage>,
|
||||
post_page: Controller<PostPage>,
|
||||
inbox_page: Controller<InboxPage>,
|
||||
login_page: Controller<LoginPage>,
|
||||
logged_in: bool,
|
||||
current_posts_type: Option<ListingType>,
|
||||
current_posts_page: i64,
|
||||
|
@ -70,7 +72,6 @@ struct App {
|
|||
pub enum AppMsg {
|
||||
ChooseInstance,
|
||||
ShowLogin,
|
||||
Login(String, String, String),
|
||||
LoggedIn,
|
||||
Logout,
|
||||
ShowMessage(String),
|
||||
|
@ -86,7 +87,7 @@ pub enum AppMsg {
|
|||
OpenInbox,
|
||||
OpenCommunities,
|
||||
PopBackStack,
|
||||
ShowAbout,
|
||||
UpdateState(AppState),
|
||||
}
|
||||
|
||||
#[relm4::component]
|
||||
|
@ -174,52 +175,8 @@ impl SimpleComponent for App {
|
|||
instances_page -> gtk::Box {}
|
||||
},
|
||||
AppState::Login => gtk::Box {
|
||||
set_hexpand: true,
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
set_spacing: 12,
|
||||
set_margin_all: 20,
|
||||
set_valign: gtk::Align::Center,
|
||||
set_hexpand: true,
|
||||
|
||||
gtk::Label {
|
||||
set_text: "Login",
|
||||
add_css_class: "font-bold",
|
||||
},
|
||||
#[name(username)]
|
||||
gtk::Entry {
|
||||
set_placeholder_text: Some("Username or E-Mail"),
|
||||
},
|
||||
#[name(password)]
|
||||
gtk::PasswordEntry {
|
||||
set_placeholder_text: Some("Password"),
|
||||
set_show_peek_icon: true,
|
||||
},
|
||||
#[name(totp_token)]
|
||||
gtk::Entry {
|
||||
set_placeholder_text: Some("Totp token (Optional)"),
|
||||
},
|
||||
gtk::Box {
|
||||
set_orientation: gtk::Orientation::Horizontal,
|
||||
set_halign: gtk::Align::End,
|
||||
|
||||
gtk::Button {
|
||||
set_label: "Cancel",
|
||||
connect_clicked => AppMsg::StartFetchPosts(None, true),
|
||||
set_margin_end: 10,
|
||||
},
|
||||
gtk::Button {
|
||||
set_label: "Login",
|
||||
connect_clicked[sender, username, password, totp_token] => move |_| {
|
||||
let username_text = username.text().as_str().to_string();
|
||||
username.set_text("");
|
||||
let password_text = password.text().as_str().to_string();
|
||||
password.set_text("");
|
||||
let totp_token_text = totp_token.text().as_str().to_string();
|
||||
totp_token.set_text("");
|
||||
sender.input(AppMsg::Login(username_text, password_text, totp_token_text));
|
||||
},
|
||||
},
|
||||
}
|
||||
#[local_ref]
|
||||
login_page -> gtk::Box {}
|
||||
},
|
||||
AppState::Communities => gtk::Box {
|
||||
#[local_ref]
|
||||
|
@ -316,6 +273,9 @@ impl SimpleComponent for App {
|
|||
let about_dialog = AboutDialog::builder()
|
||||
.launch(root.toplevel_window().unwrap())
|
||||
.detach();
|
||||
let login_page = LoginPage::builder()
|
||||
.launch(())
|
||||
.forward(sender.input_sender(), |msg| msg);
|
||||
|
||||
let model = App {
|
||||
state,
|
||||
|
@ -328,6 +288,7 @@ impl SimpleComponent for App {
|
|||
post_page,
|
||||
inbox_page,
|
||||
communities_page,
|
||||
login_page,
|
||||
message: None,
|
||||
current_posts_type: None,
|
||||
current_posts_page: 1,
|
||||
|
@ -347,6 +308,7 @@ impl SimpleComponent for App {
|
|||
let post_page = model.post_page.widget();
|
||||
let inbox_page = model.inbox_page.widget();
|
||||
let communities_page = model.communities_page.widget();
|
||||
let login_page = model.login_page.widget();
|
||||
|
||||
let widgets = view_output!();
|
||||
|
||||
|
@ -441,6 +403,10 @@ impl SimpleComponent for App {
|
|||
} else {
|
||||
self.current_posts_page + 1
|
||||
};
|
||||
// show the loading indicator if it's the first page
|
||||
if page == 1 {
|
||||
self.state = AppState::Loading;
|
||||
}
|
||||
self.current_posts_page = page;
|
||||
std::thread::spawn(move || {
|
||||
let message = match api::posts::list_posts(page, None, type_) {
|
||||
|
@ -521,39 +487,6 @@ impl SimpleComponent for App {
|
|||
AppMsg::ShowLogin => {
|
||||
self.state = AppState::Login;
|
||||
}
|
||||
AppMsg::Login(username, password, totp_token) => {
|
||||
if get_current_account().instance_url.is_empty() {
|
||||
return;
|
||||
}
|
||||
let token = if totp_token.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(totp_token)
|
||||
};
|
||||
self.state = AppState::Loading;
|
||||
std::thread::spawn(move || {
|
||||
let message = match api::auth::login(username, password, token) {
|
||||
Ok(login) => {
|
||||
if let Some(token) = login.jwt {
|
||||
let mut account = settings::get_current_account();
|
||||
account.jwt = Some(token);
|
||||
settings::update_current_account(account.clone());
|
||||
if let Ok(site) = api::site::fetch_site() {
|
||||
let user = site.my_user.unwrap().local_user_view.person;
|
||||
account.name = user.name;
|
||||
account.id = user.id.0;
|
||||
settings::update_current_account(account);
|
||||
}
|
||||
AppMsg::LoggedIn
|
||||
} else {
|
||||
AppMsg::ShowMessage("Wrong credentials!".to_string())
|
||||
}
|
||||
}
|
||||
Err(err) => AppMsg::ShowMessage(err.to_string()),
|
||||
};
|
||||
sender.input(message);
|
||||
});
|
||||
}
|
||||
AppMsg::Logout => {
|
||||
let mut account = settings::get_current_account();
|
||||
account.jwt = None;
|
||||
|
@ -570,6 +503,7 @@ impl SimpleComponent for App {
|
|||
}
|
||||
AppMsg::LoggedIn => {
|
||||
self.logged_in = true;
|
||||
self.back_queue.clear();
|
||||
sender.input(AppMsg::StartFetchPosts(None, true));
|
||||
}
|
||||
AppMsg::PopBackStack => {
|
||||
|
@ -581,7 +515,9 @@ impl SimpleComponent for App {
|
|||
self.back_queue.remove(self.back_queue.len() - 1);
|
||||
}
|
||||
}
|
||||
AppMsg::ShowAbout => {}
|
||||
AppMsg::UpdateState(state) => {
|
||||
self.state = state;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue