send + receive message
This commit is contained in:
parent
a05e33f4a4
commit
f9a8202b6b
35
src/helpers/message_store.rs
Normal file
35
src/helpers/message_store.rs
Normal 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
1
src/helpers/mod.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub mod message_store;
|
43
src/main.rs
43
src/main.rs
|
@ -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(¤t_tab.jid()).unwrap(),
|
||||
text.as_str().to_string(),
|
||||
))
|
||||
.unwrap();
|
||||
*/
|
||||
xmpp_cmd2.send(xmpp_client::XMPPCommand::SendPM(
|
||||
xmpp::BareJid::new(¤t_tab.jid()).unwrap(),
|
||||
text.as_str().to_string(),
|
||||
));
|
||||
let message = Message::now(&get_own_nick(), &text);
|
||||
let selection = win2.selection();
|
||||
let store = selection
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user