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;
|
39
src/main.rs
39
src/main.rs
|
@ -21,6 +21,7 @@ use gtk::{gio, glib};
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
|
mod helpers;
|
||||||
mod message;
|
mod message;
|
||||||
mod poezio_logs;
|
mod poezio_logs;
|
||||||
mod tab;
|
mod tab;
|
||||||
|
@ -30,6 +31,7 @@ mod xdg;
|
||||||
mod xmpp_client;
|
mod xmpp_client;
|
||||||
|
|
||||||
use config::ConfigFile;
|
use config::ConfigFile;
|
||||||
|
use helpers::message_store::MessageStore;
|
||||||
use message::Message;
|
use message::Message;
|
||||||
use tab::Tab;
|
use tab::Tab;
|
||||||
|
|
||||||
|
@ -46,7 +48,12 @@ fn xep_0392(input: &str) -> String {
|
||||||
format!("#{:02x}{:02x}{:02x}", r, g, b)
|
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 jid = win.jid().text();
|
||||||
let password = win.password().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());
|
win.stack().set_visible_child(win.spinner());
|
||||||
|
|
||||||
let (xmpp_receiver, cmd_sender) = xmpp_client::client(&jid, &password);
|
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 {
|
glib::spawn_future_local(async move {
|
||||||
while let Ok(event) = xmpp_receiver.recv().await {
|
while let Ok(event) = xmpp_receiver.recv().await {
|
||||||
match event {
|
match event {
|
||||||
|
@ -85,6 +92,10 @@ fn on_login_pressed(win: window::MainWindow, config: Arc<RwLock<ConfigFile>>) {
|
||||||
|
|
||||||
win.tabs_store().append(&tab);
|
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();
|
env_logger::init();
|
||||||
|
|
||||||
let config = Arc::new(RwLock::new(ConfigFile::from_xdg()));
|
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()
|
let app = adw::Application::builder()
|
||||||
.application_id("fr.linkmauve.XmppClient")
|
.application_id("fr.linkmauve.XmppClient")
|
||||||
|
@ -130,8 +143,15 @@ fn main() {
|
||||||
|
|
||||||
let win2 = win.clone();
|
let win2 = win.clone();
|
||||||
let config2 = config.clone();
|
let config2 = config.clone();
|
||||||
|
let messages2 = messages.clone();
|
||||||
|
let xmpp_cmd2 = xmpp_cmd.clone();
|
||||||
win.login().connect_clicked(move |_| {
|
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());
|
assert!(Tab::static_type().is_valid());
|
||||||
|
@ -198,12 +218,13 @@ fn main() {
|
||||||
win.tabs_selection().set_model(Some(win.tabs_store()));
|
win.tabs_selection().set_model(Some(win.tabs_store()));
|
||||||
|
|
||||||
let win2 = win.clone();
|
let win2 = win.clone();
|
||||||
|
let messages2 = messages.clone();
|
||||||
win.tabs_selection()
|
win.tabs_selection()
|
||||||
.connect_selection_changed(move |tabs_selection, _, _| {
|
.connect_selection_changed(move |tabs_selection, _, _| {
|
||||||
let item = tabs_selection.selected_item().unwrap();
|
let item = tabs_selection.selected_item().unwrap();
|
||||||
let tab: &Tab = item.downcast_ref().unwrap();
|
let tab: &Tab = item.downcast_ref().unwrap();
|
||||||
println!("Switching to {}", tab.jid());
|
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();
|
let selection = win2.selection();
|
||||||
selection.set_model(Some(&store));
|
selection.set_model(Some(&store));
|
||||||
win2.messages().scroll_to(
|
win2.messages().scroll_to(
|
||||||
|
@ -216,7 +237,7 @@ fn main() {
|
||||||
});
|
});
|
||||||
|
|
||||||
let win2 = win.clone();
|
let win2 = win.clone();
|
||||||
//let cmd_sender2 = cmd_sender.clone();
|
let xmpp_cmd2 = xmpp_cmd.clone();
|
||||||
win.entry().connect_activate(move |entry| {
|
win.entry().connect_activate(move |entry| {
|
||||||
let text = entry.text();
|
let text = entry.text();
|
||||||
entry.set_text("");
|
entry.set_text("");
|
||||||
|
@ -226,14 +247,10 @@ fn main() {
|
||||||
.selected_item()
|
.selected_item()
|
||||||
.and_downcast()
|
.and_downcast()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
/*
|
xmpp_cmd2.send(xmpp_client::XMPPCommand::SendPM(
|
||||||
cmd_sender2
|
|
||||||
.send_blocking(xmpp_client::XMPPCommand::SendPM(
|
|
||||||
xmpp::BareJid::new(¤t_tab.jid()).unwrap(),
|
xmpp::BareJid::new(¤t_tab.jid()).unwrap(),
|
||||||
text.as_str().to_string(),
|
text.as_str().to_string(),
|
||||||
))
|
));
|
||||||
.unwrap();
|
|
||||||
*/
|
|
||||||
let message = Message::now(&get_own_nick(), &text);
|
let message = Message::now(&get_own_nick(), &text);
|
||||||
let selection = win2.selection();
|
let selection = win2.selection();
|
||||||
let store = selection
|
let store = selection
|
||||||
|
|
|
@ -1,20 +1,45 @@
|
||||||
use async_channel::{Receiver, Sender};
|
use async_channel::{Receiver, Sender};
|
||||||
|
use chrono::{DateTime, Utc};
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
use xmpp::{BareJid, ClientBuilder, ClientFeature};
|
use xmpp::{BareJid, ClientBuilder, ClientFeature};
|
||||||
|
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::sync::OnceLock;
|
use std::sync::{Arc, OnceLock, RwLock};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum XMPPCommand {
|
pub enum XMPPCommand {
|
||||||
SendPM(BareJid, String),
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum XMPPEvent {
|
pub enum XMPPEvent {
|
||||||
Online,
|
Online,
|
||||||
Avatar(BareJid, String),
|
Avatar(BareJid, String),
|
||||||
Contact(BareJid, Option<String>),
|
Contact(BareJid, Option<String>),
|
||||||
|
PM(BareJid, String, DateTime<Utc>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tokio_runtime() -> &'static Runtime {
|
pub fn tokio_runtime() -> &'static Runtime {
|
||||||
|
@ -70,10 +95,17 @@ pub async fn handle_xmpp_event(event: xmpp::Event) -> Option<XMPPEvent> {
|
||||||
Some(XMPPEvent::Contact(avatar_jid, None))
|
Some(XMPPEvent::Contact(avatar_jid, None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
xmpp::Event::ChatMessage(_id, _from, _body, _time) => {
|
xmpp::Event::ChatMessage(_id, from, body, time) => {
|
||||||
// TODO: Insert message into tab history
|
if from.is_bare() {
|
||||||
|
Some(XMPPEvent::PM(
|
||||||
|
from.to_bare(),
|
||||||
|
body.0.to_string(),
|
||||||
|
time.received.clone(),
|
||||||
|
))
|
||||||
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user