From 5824275f062c737181062cb38cba6f7926f30acf Mon Sep 17 00:00:00 2001 From: Emmanuel Gil Peyrot Date: Tue, 4 Jun 2024 18:00:38 +0200 Subject: [PATCH] Implement a login page That way we connect only after the UI is created. --- src/main.rs | 67 +++++++++------- src/window/imp.rs | 23 +++++- src/window/mod.rs | 24 ++++++ src/window/window.ui | 178 +++++++++++++++++++++++++++++-------------- src/xmpp_client.rs | 7 +- 5 files changed, 213 insertions(+), 86 deletions(-) diff --git a/src/main.rs b/src/main.rs index 428047d..52bb18b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,38 +40,44 @@ fn xep_0392(input: &str) -> String { format!("#{:02x}{:02x}{:02x}", r, g, b) } +fn on_login_pressed(win: &window::MainWindow) { + let jid = win.jid().text(); + let password = win.password().text(); + println!("jid={jid:?} password={password:?}"); + + if !jid.is_empty() && !password.is_empty() { + win.stack().set_visible_child(win.spinner()); + + let (xmpp_receiver, cmd_sender) = xmpp_client::client(&jid, &password); + let win2 = win.clone(); + glib::spawn_future_local(async move { + while let Ok(event) = xmpp_receiver.recv().await { + match event { + xmpp::Event::Online => { + win2.stack().set_visible_child(win2.split_view()); + } + xmpp::Event::ContactAdded(jid) => { + let tab = Tab::new(jid.jid.as_str(), jid.jid.as_str()); + win2.tabs_store().append(&tab); + } + xmpp::Event::ChatMessage(_id, _from, _body, _time) => { + // TODO: Insert message into tab history + continue; + } + _ => continue, + } + } + }); + } +} + fn main() { env_logger::init(); - let mut args = std::env::args(); - let _ = args.next().unwrap(); - let username = args.next().expect("Please give username argument 1"); - let password = args.next().expect("Please give password argument 2"); - let app = adw::Application::builder() .application_id("fr.linkmauve.XmppClient") .build(); - let tabs_store = gio::ListStore::new::(); - - let (xmpp_receiver, cmd_sender) = xmpp_client::client(&username, &password); - let tabs_store_copy = tabs_store.clone(); - glib::spawn_future_local(async move { - while let Ok(event) = xmpp_receiver.recv().await { - match event { - xmpp::Event::ContactAdded(jid) => { - let tab = Tab::new(jid.jid.as_str(), jid.jid.as_str()); - tabs_store_copy.append(&tab); - } - xmpp::Event::ChatMessage(_id, _from, _body, _time) => { - // TODO: Insert message into tab history - continue; - } - _ => continue, - } - } - }); - app.connect_activate(move |app| { let win = window::MainWindow::new(app); @@ -83,6 +89,11 @@ fn main() { win.add_action_entries([action_close]); app.set_accels_for_action("win.close", &["Q"]); + let win2 = win.clone(); + win.login().connect_clicked(move |_| { + on_login_pressed(&win2); + }); + assert!(Tab::static_type().is_valid()); assert!(Message::static_type().is_valid()); @@ -135,7 +146,7 @@ fn main() { }); win.tabs().set_factory(Some(&tabs_factory)); - win.tabs_selection().set_model(Some(&tabs_store)); + win.tabs_selection().set_model(Some(win.tabs_store())); let win2 = win.clone(); win.tabs_selection() @@ -156,7 +167,7 @@ fn main() { }); let win2 = win.clone(); - let cmd_sender2 = cmd_sender.clone(); + //let cmd_sender2 = cmd_sender.clone(); win.entry().connect_activate(move |entry| { let text = entry.text(); entry.set_text(""); @@ -166,12 +177,14 @@ fn main() { .selected_item() .and_downcast() .unwrap(); + /* cmd_sender2 .send_blocking(xmpp_client::XMPPCommand::SendPM( xmpp::BareJid::new(¤t_tab.jid()).unwrap(), text.as_str().to_string(), )) .unwrap(); + */ let message = Message::now(&get_own_nick(), &text); let selection = win2.selection(); let store = selection diff --git a/src/window/imp.rs b/src/window/imp.rs index da86ecc..fb4a2ba 100644 --- a/src/window/imp.rs +++ b/src/window/imp.rs @@ -15,12 +15,33 @@ // along with this program. If not, see . use adw::subclass::prelude::*; -use gtk::glib; +use gtk::{gio, glib}; /// The private struct, which can hold widgets and other data. #[derive(Debug, Default, gtk::CompositeTemplate)] #[template(file = "window.ui")] pub struct MainWindow { + #[template_child] + pub stack: TemplateChild, + + // For the login page + + #[template_child] + pub jid: TemplateChild, + #[template_child] + pub password: TemplateChild, + #[template_child] + pub login: TemplateChild, + + // For the spinner + + #[template_child] + pub spinner: TemplateChild, + + // For the chats page + + #[template_child] + pub tabs_store: TemplateChild, #[template_child] pub split_view: TemplateChild, #[template_child] diff --git a/src/window/mod.rs b/src/window/mod.rs index c4e9465..7ac96cb 100644 --- a/src/window/mod.rs +++ b/src/window/mod.rs @@ -30,6 +30,30 @@ impl MainWindow { glib::Object::builder().property("application", app).build() } + pub fn stack(&self) -> >k::Stack { + &self.imp().stack + } + + pub fn jid(&self) -> &adw::EntryRow { + &self.imp().jid + } + + pub fn password(&self) -> &adw::PasswordEntryRow { + &self.imp().password + } + + pub fn login(&self) -> >k::Button { + &self.imp().login + } + + pub fn spinner(&self) -> >k::Box { + &self.imp().spinner + } + + pub fn tabs_store(&self) -> &gio::ListStore { + &self.imp().tabs_store + } + pub fn split_view(&self) -> &adw::NavigationSplitView { &self.imp().split_view } diff --git a/src/window/window.ui b/src/window/window.ui index 0cbbbdc..7751e16 100644 --- a/src/window/window.ui +++ b/src/window/window.ui @@ -13,81 +13,147 @@ - - - - Open Chats - - - - - - - - yes - - - tabs_selection - - - - - - - - - - - Messages - chat - - - - - - + + + + vertical + + + + + + vertical - - yes + + Enter your XMPP credentials - - selection + + JID + email + + + + + Password + password - - 10 - 10 - 10 - 10 - - - yes - Send a message - - - + + Login + suggested-action + 8 + + + + + + + + vertical + + + + + + Connecting… + + + + + yes + no + + + + + + + + + Open Chats + + + + + + + + yes + + + tabs_selection + + + + + + + + + + + Messages + chat + + + + + + + + vertical + + + yes + + + selection + + + + + + + 10 + 10 + 10 + 10 + + + yes + Send a message + free-form + + + + + + + + - + + diff --git a/src/xmpp_client.rs b/src/xmpp_client.rs index 7fe350c..720df16 100644 --- a/src/xmpp_client.rs +++ b/src/xmpp_client.rs @@ -32,6 +32,9 @@ pub(crate) fn client(jid: &str, password: &str) -> (Receiver, Sende Some(events) = client.wait_for_events() => { for event in events { match event { + Event::Online => { + event_sender.send(event).await.expect("BOOOOOOHOOOO"); + } Event::ContactAdded(_) => { event_sender.send(event).await.expect("BOOOOOOHOOOO"); } @@ -45,8 +48,8 @@ pub(crate) fn client(jid: &str, password: &str) -> (Receiver, Sende } } - command = cmd_receiver.recv() => { - match command.unwrap() { + Ok(command) = cmd_receiver.recv() => { + match command { XMPPCommand::SendPM(jid, content) => { client.send_message(jid.into(), xmpp::parsers::message::MessageType::Chat, "en", &content).await; },