mirror of
https://gitea.mizah.xyz/mizah/dergchat
synced 2024-11-21 14:05:00 -05:00
Update UI layout and design in chat application.
Minor refactorings.
This commit is contained in:
parent
0d80360b58
commit
4da80010ff
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +1,2 @@
|
||||
/target
|
||||
/dist
|
208
src/main.rs
208
src/main.rs
@ -1,24 +1,47 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::future::Future;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use futures_util::stream::StreamExt;
|
||||
use dioxus::html::textarea;
|
||||
// import the prelude to get access to the `rsx!` macro and the `Scope` and `Element` types
|
||||
use dioxus::prelude::*;
|
||||
use dioxus_desktop::Config;
|
||||
use dioxus_elements::{h1, li, ul};
|
||||
use log::info;
|
||||
use tokio::select;
|
||||
use xmpp::{BareJid, ClientBuilder, ClientType, RoomNick};
|
||||
use xmpp::parsers::message::MessageType;
|
||||
|
||||
fn main() {
|
||||
const STYLESHEET: &str = r#"
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: lightgray;
|
||||
}
|
||||
|
||||
#main {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
"#;
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
||||
// launch the dioxus app in a webview
|
||||
dioxus_desktop::launch(App);
|
||||
dioxus_desktop::launch_cfg(App,
|
||||
Config::default()
|
||||
.with_custom_head(format!(r#"<style>{}</style>"#, STYLESHEET))
|
||||
.with_background_color((32,64,32,255)));
|
||||
}
|
||||
|
||||
#[derive(Props)]
|
||||
@ -30,7 +53,6 @@ struct RoomListProps<'a> {
|
||||
/// A Dioxus component that renders a list of rooms
|
||||
fn RoomList<'a>(cx: Scope<'a, RoomListProps>) -> Element<'a> {
|
||||
render! {
|
||||
h1 { "Rooms" }
|
||||
ul {
|
||||
for room in cx.props.rooms.iter() {
|
||||
rsx! { li {
|
||||
@ -43,39 +65,41 @@ fn RoomList<'a>(cx: Scope<'a, RoomListProps>) -> Element<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Message {
|
||||
sender: String,
|
||||
body: String,
|
||||
}
|
||||
|
||||
#[derive(Props)]
|
||||
struct RoomViewProps<'a> {
|
||||
room: BareJid,
|
||||
messages: Vec<String>,
|
||||
messages: Vec<Message>,
|
||||
on_message_sent: EventHandler<'a, String>,
|
||||
}
|
||||
|
||||
// impl PartialEq for RoomViewProps {
|
||||
// fn eq(&self, other: &Self) -> bool {
|
||||
// self.room == other.room && self.messages == other.messages
|
||||
// }
|
||||
// }
|
||||
|
||||
fn RoomView<'a>(cx: Scope<'a, RoomViewProps>) -> Element<'a> {
|
||||
|
||||
let message = use_state(cx, || "".to_owned());
|
||||
|
||||
render! {
|
||||
div {
|
||||
h1 { "Messages" }
|
||||
ul {
|
||||
for message in cx.props.messages.iter() {
|
||||
rsx! { li {
|
||||
"{message}"
|
||||
"{message.sender}: {message.body}"
|
||||
} }
|
||||
}
|
||||
}
|
||||
div {
|
||||
display: "flex",
|
||||
flex_direction: "row",
|
||||
textarea {
|
||||
flex_grow: 1,
|
||||
oninput: |evt| {
|
||||
message.set(evt.value.clone());
|
||||
}
|
||||
}
|
||||
button {
|
||||
height: "100%",
|
||||
onclick: move |_| {
|
||||
cx.props.on_message_sent.call(message.current().to_string());
|
||||
},
|
||||
@ -85,50 +109,10 @@ fn RoomView<'a>(cx: Scope<'a, RoomViewProps>) -> Element<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
// define a component that renders a div with the text "Hello, world!"
|
||||
fn App(cx: Scope) -> Element {
|
||||
|
||||
let rooms = use_state(cx, || vec![]);
|
||||
let messages = use_state(cx, || HashMap::new());
|
||||
let current_room = use_state(cx, || None::<BareJid>);
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SendMessage {
|
||||
recipient: BareJid,
|
||||
message: String,
|
||||
}
|
||||
|
||||
let cr = use_coroutine(cx, |mut commands: UnboundedReceiver<SendMessage>| {
|
||||
let mut rooms = rooms.to_owned();
|
||||
let mut messages = messages.to_owned();
|
||||
let current_room = current_room.to_owned();
|
||||
|
||||
async move {
|
||||
|
||||
let jid = BareJid::from_str("bot@mizah.xyz").unwrap();
|
||||
|
||||
let password = "G0cEiYp98G8nBzOdkKMF";
|
||||
|
||||
let mut agent = ClientBuilder::new(jid, &password)
|
||||
.set_client(ClientType::Pc, "dergchat")
|
||||
.set_default_nick("dergchat")
|
||||
.build();
|
||||
|
||||
// tokio::spawn({
|
||||
// async move {
|
||||
// while let Some(command) = commands.next().await {
|
||||
// println!("Sending command: {:?}", command);
|
||||
// agent.borrow_mut().send_message(command.recipient.into(), MessageType::Chat, "en/us", &command.message).await;
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
loop {
|
||||
|
||||
select! {
|
||||
events = agent.wait_for_events() => {
|
||||
if let Some(events) = events {
|
||||
for event in events {
|
||||
async fn handle_event(event: xmpp::Event,
|
||||
agent: &mut xmpp::Agent,
|
||||
rooms: &mut UseState<Vec<BareJid>>,
|
||||
messages: &mut UseState<HashMap<BareJid, Vec<Message>>>) {
|
||||
match event {
|
||||
xmpp::Event::JoinRoom(jid, conference) => {
|
||||
println!("Joining room: {}", &jid);
|
||||
@ -137,41 +121,59 @@ fn App(cx: Scope) -> Element {
|
||||
},
|
||||
xmpp::Event::ChatMessage(id, sender, body) => {
|
||||
println!("Message from {}: {}", &sender, &body.0);
|
||||
messages.make_mut().entry(sender).or_insert(vec![]).push(body.0);
|
||||
messages.make_mut().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.make_mut().entry(room_jid).or_insert(vec![]).push(body.0);
|
||||
messages.make_mut().entry(room_jid).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.make_mut().entry(room_jid).or_insert(vec![]).push(body.0);
|
||||
messages.make_mut().entry(room_jid).or_insert(vec![]).push(Message {
|
||||
sender: sender_nick,
|
||||
body: body.0,
|
||||
});
|
||||
},
|
||||
_ => {
|
||||
log::debug!("Received unsupported event {:?}", event);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
info!("Disconnected");
|
||||
}
|
||||
},
|
||||
command = commands.next() => {
|
||||
if let Some(command) = command {
|
||||
println!("Sending command: {:?}", command);
|
||||
agent.send_message(command.recipient.into(), MessageType::Groupchat, "en-us", &command.message).await;
|
||||
} else {
|
||||
info!("Command channel closed");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SendMessage {
|
||||
recipient: BareJid,
|
||||
message: String,
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
// define a component that renders a div with the text "Hello, world!"
|
||||
fn App(cx: Scope) -> Element {
|
||||
|
||||
let rooms = use_state(cx, || vec![]);
|
||||
let messages = use_state(cx, || HashMap::new());
|
||||
let current_room = use_state(cx, || None::<BareJid>);
|
||||
|
||||
let cr = use_coroutine(cx,
|
||||
|rx: UnboundedReceiver<SendMessage>| run_xmpp(rooms.clone(), messages.clone(), rx)
|
||||
);
|
||||
|
||||
render! {
|
||||
div {
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
display: "flex",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
|
||||
div {
|
||||
background_color: "#1d852d",
|
||||
RoomList {
|
||||
rooms: rooms.to_vec(),
|
||||
on_room_picked: move |x:BareJid| {
|
||||
@ -179,8 +181,11 @@ fn App(cx: Scope) -> Element {
|
||||
current_room.set(Some(x));
|
||||
},
|
||||
}
|
||||
}
|
||||
div {
|
||||
flex_grow: 1,
|
||||
background_color: "#166322",
|
||||
if let Some(room) = current_room.get() {
|
||||
|
||||
let messages = messages.get().get(&room).expect("Selected non-existant room").to_vec();
|
||||
|
||||
rsx! {
|
||||
@ -196,6 +201,53 @@ fn App(cx: Scope) -> Element {
|
||||
},
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rsx! {
|
||||
div {
|
||||
"No room selected"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn run_xmpp(mut rooms: UseState<Vec<BareJid>>,
|
||||
mut messages: UseState<HashMap<BareJid, Vec<Message>>>,
|
||||
mut commands: UnboundedReceiver<SendMessage>) -> impl Future<Output=()> + Sized {
|
||||
|
||||
async move {
|
||||
let jid = BareJid::from_str("bot@mizah.xyz").unwrap();
|
||||
|
||||
let password = "G0cEiYp98G8nBzOdkKMF";
|
||||
|
||||
let mut agent = ClientBuilder::new(jid, &password)
|
||||
.set_client(ClientType::Pc, "dergchat")
|
||||
.set_default_nick("dergchat")
|
||||
.build();
|
||||
|
||||
loop {
|
||||
select! {
|
||||
events = agent.wait_for_events() => {
|
||||
if let Some(events) = events {
|
||||
for event in events {
|
||||
handle_event(event, &mut agent, &mut rooms, &mut messages).await;
|
||||
}
|
||||
} else {
|
||||
info!("Disconnected");
|
||||
}
|
||||
},
|
||||
command = commands.next() => {
|
||||
if let Some(command) = command {
|
||||
println!("Sending command: {:?}", command);
|
||||
agent.send_message(command.recipient.into(), MessageType::Groupchat, "en-us", &command.message).await;
|
||||
} else {
|
||||
info!("Command channel closed");
|
||||
break;
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user