use crate::types::{LoginCredentials, Message}; use dioxus::hooks::{UnboundedReceiver, UseRef}; use futures_util::stream::StreamExt; use jid::BareJid; use log::{error, info}; use std::collections::HashMap; use std::future::Future; use std::str::FromStr; use tokio::select; use xmpp::parsers::message::MessageType; use xmpp::{Agent, ClientBuilder, ClientType}; async fn handle_event( event: xmpp::Event, agent: &mut xmpp::Agent, messages: &mut UseRef>>, ) { match event { xmpp::Event::JoinRoom(jid, conference) => { println!("Will auto-join room: {}", &jid); agent.join_room(jid, None, None, "en/us", "online").await; } xmpp::Event::RoomJoined(room_jid) => { println!("Joined room: {}", &room_jid); messages.with_mut(move |m| { m.entry(room_jid.clone()).or_insert(vec![]); }); } xmpp::Event::RoomLeft(room_jid) => { println!("Left room: {}", &room_jid); messages.with_mut(move |m| { m.remove(&room_jid); }); } xmpp::Event::ChatMessage(id, sender, body) => { println!("Message from {}: {}", &sender, &body.0); messages.with_mut(move |m| { m.entry(sender.clone()).or_insert(vec![]).push(Message { sender: sender.to_string(), body: body.0, }); }); } xmpp::Event::RoomMessage(id, room_jid, sender_nick, body) => { println!( "Message in {} from {}: {}", &room_jid, &sender_nick, &body.0 ); messages.with_mut(move |m| { m.entry(room_jid.clone()).or_insert(vec![]).push(Message { sender: sender_nick, body: body.0, }) }); } xmpp::Event::RoomPrivateMessage(id, room_jid, sender_nick, body) => { println!( "Private message in {} from {}: {}", &room_jid, &sender_nick, &body.0 ); messages.with_mut(move |m| { m.entry(room_jid.clone()).or_insert(vec![]).push(Message { sender: sender_nick, body: body.0, }) }); } _ => { log::debug!("Received unsupported event {:?}", event); } } } #[derive(Debug)] pub enum NetworkCommand { TryLogin { credentials: LoginCredentials }, JoinRoom { room: BareJid }, LeaveRoom { room: BareJid }, SendMessage { recipient: BareJid, message: String }, } pub fn xmpp_mainloop<'a>( agent: &'a mut Agent, mut room_data: &'a mut UseRef>>, commands: &'a mut UnboundedReceiver, ) -> impl Future + Sized + 'a { async move { loop { select! { events = agent.wait_for_events() => { if let Some(events) = events { for event in events { handle_event(event, agent, &mut room_data).await; } } else { info!("Disconnected"); } }, command = commands.next() => { if let Some(command) = command { match command { NetworkCommand::JoinRoom { room } => { agent.join_room(room.clone(), None, None, "en-us", "online").await; }, NetworkCommand::LeaveRoom { room } => { agent.leave_room( room, "dergchat".to_string(), "en-us", "User left the room.").await; }, NetworkCommand::SendMessage { recipient, message } => { agent.send_message(recipient.into(), MessageType::Groupchat, "en-us", &message).await; }, NetworkCommand::TryLogin { credentials } => { panic!("Already logged in."); }, } } else { info!("Command channel closed"); break; } }, } } } }