send + receive message

This commit is contained in:
xmppftw xmppftw 2024-06-05 01:51:43 +02:00
parent a05e33f4a4
commit f9a8202b6b
4 changed files with 102 additions and 17 deletions

View File

@ -0,0 +1,35 @@
use gtk::gio::ListStore;
use xmpp::BareJid;
use std::collections::HashMap;
use std::sync::{Arc, RwLock};
use crate::poezio_logs::load_logs;
use crate::Message;
pub type InnerMessageStore = HashMap<BareJid, ListStore>;
#[derive(Clone, Debug, Default)]
pub struct MessageStore {
/// complete message history
store: Arc<RwLock<InnerMessageStore>>,
}
impl<'a> MessageStore {
pub fn new() -> Self {
Self::default()
}
pub fn with_jid(&self, jid: &BareJid) -> ListStore {
self.store
.write()
.unwrap()
.entry(jid.clone())
.or_insert(load_logs(jid.as_str()))
.clone()
}
pub fn insert_message(&self, jid: &BareJid, message: &Message) {
self.with_jid(jid).append(message);
}
}

1
src/helpers/mod.rs Normal file
View File

@ -0,0 +1 @@
pub mod message_store;

View File

@ -21,6 +21,7 @@ use gtk::{gio, glib};
use std::sync::{Arc, RwLock};
mod config;
mod helpers;
mod message;
mod poezio_logs;
mod tab;
@ -30,6 +31,7 @@ mod xdg;
mod xmpp_client;
use config::ConfigFile;
use helpers::message_store::MessageStore;
use message::Message;
use tab::Tab;
@ -46,7 +48,12 @@ fn xep_0392(input: &str) -> String {
format!("#{:02x}{:02x}{:02x}", r, g, b)
}
fn on_login_pressed(win: window::MainWindow, config: Arc<RwLock<ConfigFile>>) {
fn on_login_pressed(
win: window::MainWindow,
config: Arc<RwLock<ConfigFile>>,
messages: MessageStore,
xmpp_cmd: xmpp_client::CommandSender,
) {
let jid = win.jid().text();
let password = win.password().text();
@ -54,7 +61,7 @@ fn on_login_pressed(win: window::MainWindow, config: Arc<RwLock<ConfigFile>>) {
win.stack().set_visible_child(win.spinner());
let (xmpp_receiver, cmd_sender) = xmpp_client::client(&jid, &password);
// let win2 = win.clone();
xmpp_cmd.set_sender(cmd_sender);
glib::spawn_future_local(async move {
while let Ok(event) = xmpp_receiver.recv().await {
match event {
@ -85,6 +92,10 @@ fn on_login_pressed(win: window::MainWindow, config: Arc<RwLock<ConfigFile>>) {
win.tabs_store().append(&tab);
}
xmpp_client::XMPPEvent::PM(jid, body, time) => {
let message = Message::new(&time, jid.as_str(), &body);
messages.insert_message(&jid, &message);
}
}
}
});
@ -95,6 +106,8 @@ fn main() {
env_logger::init();
let config = Arc::new(RwLock::new(ConfigFile::from_xdg()));
let messages = MessageStore::new();
let xmpp_cmd = xmpp_client::CommandSender::new();
let app = adw::Application::builder()
.application_id("fr.linkmauve.XmppClient")
@ -130,8 +143,15 @@ fn main() {
let win2 = win.clone();
let config2 = config.clone();
let messages2 = messages.clone();
let xmpp_cmd2 = xmpp_cmd.clone();
win.login().connect_clicked(move |_| {
on_login_pressed(win2.clone(), config2.clone());
on_login_pressed(
win2.clone(),
config2.clone(),
messages2.clone(),
xmpp_cmd2.clone(),
);
});
assert!(Tab::static_type().is_valid());
@ -198,12 +218,13 @@ fn main() {
win.tabs_selection().set_model(Some(win.tabs_store()));
let win2 = win.clone();
let messages2 = messages.clone();
win.tabs_selection()
.connect_selection_changed(move |tabs_selection, _, _| {
let item = tabs_selection.selected_item().unwrap();
let tab: &Tab = item.downcast_ref().unwrap();
println!("Switching to {}", tab.jid());
let store = poezio_logs::load_logs(&tab.jid());
let store = messages2.with_jid(&jid::BareJid::new(&tab.jid()).unwrap());
let selection = win2.selection();
selection.set_model(Some(&store));
win2.messages().scroll_to(
@ -216,7 +237,7 @@ fn main() {
});
let win2 = win.clone();
//let cmd_sender2 = cmd_sender.clone();
let xmpp_cmd2 = xmpp_cmd.clone();
win.entry().connect_activate(move |entry| {
let text = entry.text();
entry.set_text("");
@ -226,14 +247,10 @@ fn main() {
.selected_item()
.and_downcast()
.unwrap();
/*
cmd_sender2
.send_blocking(xmpp_client::XMPPCommand::SendPM(
xmpp::BareJid::new(&current_tab.jid()).unwrap(),
text.as_str().to_string(),
))
.unwrap();
*/
xmpp_cmd2.send(xmpp_client::XMPPCommand::SendPM(
xmpp::BareJid::new(&current_tab.jid()).unwrap(),
text.as_str().to_string(),
));
let message = Message::now(&get_own_nick(), &text);
let selection = win2.selection();
let store = selection

View File

@ -1,20 +1,45 @@
use async_channel::{Receiver, Sender};
use chrono::{DateTime, Utc};
use tokio::runtime::Runtime;
use xmpp::{BareJid, ClientBuilder, ClientFeature};
use std::path::PathBuf;
use std::sync::OnceLock;
use std::sync::{Arc, OnceLock, RwLock};
#[derive(Clone, Debug)]
pub enum XMPPCommand {
SendPM(BareJid, String),
}
#[derive(Clone, Debug)]
pub struct CommandSender(Arc<RwLock<Option<Sender<XMPPCommand>>>>);
impl CommandSender {
pub fn new() -> Self {
Self(Arc::new(RwLock::new(None)))
}
pub fn set_sender(&self, sender: Sender<XMPPCommand>) {
*self.0.write().unwrap() = Some(sender);
}
pub fn send(&self, command: XMPPCommand) {
self.0
.write()
.unwrap()
.as_ref()
.expect("bug: CommandSender not init")
.send_blocking(command)
.unwrap();
}
}
#[derive(Clone, Debug)]
pub enum XMPPEvent {
Online,
Avatar(BareJid, String),
Contact(BareJid, Option<String>),
PM(BareJid, String, DateTime<Utc>),
}
pub fn tokio_runtime() -> &'static Runtime {
@ -70,9 +95,16 @@ pub async fn handle_xmpp_event(event: xmpp::Event) -> Option<XMPPEvent> {
Some(XMPPEvent::Contact(avatar_jid, None))
}
}
xmpp::Event::ChatMessage(_id, _from, _body, _time) => {
// TODO: Insert message into tab history
None
xmpp::Event::ChatMessage(_id, from, body, time) => {
if from.is_bare() {
Some(XMPPEvent::PM(
from.to_bare(),
body.0.to_string(),
time.received.clone(),
))
} else {
None
}
}
_ => None,
}