mirror of
https://gitea.mizah.xyz/mizah/dergchat
synced 2024-11-21 13:15:01 -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
|
/target
|
||||||
|
/dist
|
258
src/main.rs
258
src/main.rs
@ -1,24 +1,47 @@
|
|||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::future::Future;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use futures_util::stream::StreamExt;
|
use futures_util::stream::StreamExt;
|
||||||
use dioxus::html::textarea;
|
use dioxus::html::textarea;
|
||||||
// import the prelude to get access to the `rsx!` macro and the `Scope` and `Element` types
|
// import the prelude to get access to the `rsx!` macro and the `Scope` and `Element` types
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
use dioxus_desktop::Config;
|
||||||
use dioxus_elements::{h1, li, ul};
|
use dioxus_elements::{h1, li, ul};
|
||||||
use log::info;
|
use log::info;
|
||||||
use tokio::select;
|
use tokio::select;
|
||||||
use xmpp::{BareJid, ClientBuilder, ClientType, RoomNick};
|
use xmpp::{BareJid, ClientBuilder, ClientType, RoomNick};
|
||||||
use xmpp::parsers::message::MessageType;
|
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();
|
env_logger::init();
|
||||||
|
|
||||||
// launch the dioxus app in a webview
|
// 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)]
|
#[derive(Props)]
|
||||||
@ -30,7 +53,6 @@ struct RoomListProps<'a> {
|
|||||||
/// A Dioxus component that renders a list of rooms
|
/// A Dioxus component that renders a list of rooms
|
||||||
fn RoomList<'a>(cx: Scope<'a, RoomListProps>) -> Element<'a> {
|
fn RoomList<'a>(cx: Scope<'a, RoomListProps>) -> Element<'a> {
|
||||||
render! {
|
render! {
|
||||||
h1 { "Rooms" }
|
|
||||||
ul {
|
ul {
|
||||||
for room in cx.props.rooms.iter() {
|
for room in cx.props.rooms.iter() {
|
||||||
rsx! { li {
|
rsx! { li {
|
||||||
@ -43,48 +65,94 @@ fn RoomList<'a>(cx: Scope<'a, RoomListProps>) -> Element<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
struct Message {
|
||||||
|
sender: String,
|
||||||
|
body: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Props)]
|
#[derive(Props)]
|
||||||
struct RoomViewProps<'a> {
|
struct RoomViewProps<'a> {
|
||||||
room: BareJid,
|
room: BareJid,
|
||||||
messages: Vec<String>,
|
messages: Vec<Message>,
|
||||||
on_message_sent: EventHandler<'a, String>,
|
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> {
|
fn RoomView<'a>(cx: Scope<'a, RoomViewProps>) -> Element<'a> {
|
||||||
|
|
||||||
let message = use_state(cx, || "".to_owned());
|
let message = use_state(cx, || "".to_owned());
|
||||||
|
|
||||||
render! {
|
render! {
|
||||||
div {
|
|
||||||
h1 { "Messages" }
|
|
||||||
ul {
|
ul {
|
||||||
for message in cx.props.messages.iter() {
|
for message in cx.props.messages.iter() {
|
||||||
rsx! { li {
|
rsx! { li {
|
||||||
"{message}"
|
"{message.sender}: {message.body}"
|
||||||
} }
|
} }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
textarea {
|
div {
|
||||||
oninput: |evt| {
|
display: "flex",
|
||||||
message.set(evt.value.clone());
|
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());
|
||||||
|
},
|
||||||
|
"Send"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
button {
|
}
|
||||||
onclick: move |_| {
|
}
|
||||||
cx.props.on_message_sent.call(message.current().to_string());
|
|
||||||
},
|
async fn handle_event(event: xmpp::Event,
|
||||||
"Send"
|
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);
|
||||||
|
rooms.make_mut().push(jid.clone());
|
||||||
|
agent.join_room(jid, None, None, "en/us", "online").await;
|
||||||
|
},
|
||||||
|
xmpp::Event::ChatMessage(id, sender, body) => {
|
||||||
|
println!("Message from {}: {}", &sender, &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(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(Message {
|
||||||
|
sender: sender_nick,
|
||||||
|
body: body.0,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
log::debug!("Received unsupported event {:?}", event);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct SendMessage {
|
||||||
|
recipient: BareJid,
|
||||||
|
message: String,
|
||||||
|
}
|
||||||
|
|
||||||
// define a component that renders a div with the text "Hello, world!"
|
// define a component that renders a div with the text "Hello, world!"
|
||||||
fn App(cx: Scope) -> Element {
|
fn App(cx: Scope) -> Element {
|
||||||
|
|
||||||
@ -92,65 +160,79 @@ fn App(cx: Scope) -> Element {
|
|||||||
let messages = use_state(cx, || HashMap::new());
|
let messages = use_state(cx, || HashMap::new());
|
||||||
let current_room = use_state(cx, || None::<BareJid>);
|
let current_room = use_state(cx, || None::<BareJid>);
|
||||||
|
|
||||||
#[derive(Debug)]
|
let cr = use_coroutine(cx,
|
||||||
struct SendMessage {
|
|rx: UnboundedReceiver<SendMessage>| run_xmpp(rooms.clone(), messages.clone(), rx)
|
||||||
recipient: BareJid,
|
);
|
||||||
message: String,
|
|
||||||
|
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| {
|
||||||
|
println!("Room selected: {:?}", x);
|
||||||
|
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! {
|
||||||
|
RoomView {
|
||||||
|
room: room.clone(),
|
||||||
|
messages: messages,
|
||||||
|
on_message_sent: move |x:String| {
|
||||||
|
println!("Message sent: {:?}", x);
|
||||||
|
cr.send(SendMessage {
|
||||||
|
recipient: room.clone(),
|
||||||
|
message: x,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rsx! {
|
||||||
|
div {
|
||||||
|
"No room selected"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let cr = use_coroutine(cx, |mut commands: UnboundedReceiver<SendMessage>| {
|
fn run_xmpp(mut rooms: UseState<Vec<BareJid>>,
|
||||||
let mut rooms = rooms.to_owned();
|
mut messages: UseState<HashMap<BareJid, Vec<Message>>>,
|
||||||
let mut messages = messages.to_owned();
|
mut commands: UnboundedReceiver<SendMessage>) -> impl Future<Output=()> + Sized {
|
||||||
let current_room = current_room.to_owned();
|
|
||||||
|
|
||||||
async move {
|
async move {
|
||||||
|
let jid = BareJid::from_str("bot@mizah.xyz").unwrap();
|
||||||
|
|
||||||
let jid = BareJid::from_str("bot@mizah.xyz").unwrap();
|
let password = "G0cEiYp98G8nBzOdkKMF";
|
||||||
|
|
||||||
let password = "G0cEiYp98G8nBzOdkKMF";
|
let mut agent = ClientBuilder::new(jid, &password)
|
||||||
|
.set_client(ClientType::Pc, "dergchat")
|
||||||
|
.set_default_nick("dergchat")
|
||||||
|
.build();
|
||||||
|
|
||||||
let mut agent = ClientBuilder::new(jid, &password)
|
loop {
|
||||||
.set_client(ClientType::Pc, "dergchat")
|
select! {
|
||||||
.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() => {
|
events = agent.wait_for_events() => {
|
||||||
if let Some(events) = events {
|
if let Some(events) = events {
|
||||||
for event in events {
|
for event in events {
|
||||||
match event {
|
handle_event(event, &mut agent, &mut rooms, &mut messages).await;
|
||||||
xmpp::Event::JoinRoom(jid, conference) => {
|
|
||||||
println!("Joining room: {}", &jid);
|
|
||||||
rooms.make_mut().push(jid.clone());
|
|
||||||
agent.join_room(jid, None, None, "en/us", "online").await;
|
|
||||||
},
|
|
||||||
xmpp::Event::ChatMessage(id, sender, body) => {
|
|
||||||
println!("Message from {}: {}", &sender, &body.0);
|
|
||||||
messages.make_mut().entry(sender).or_insert(vec![]).push(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);
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
log::debug!("Received unsupported event {:?}", event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
info!("Disconnected");
|
info!("Disconnected");
|
||||||
@ -166,36 +248,6 @@ fn App(cx: Scope) -> Element {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
render! {
|
|
||||||
RoomList {
|
|
||||||
rooms: rooms.to_vec(),
|
|
||||||
on_room_picked: move |x:BareJid| {
|
|
||||||
println!("Room selected: {:?}", x);
|
|
||||||
current_room.set(Some(x));
|
|
||||||
},
|
|
||||||
}
|
|
||||||
if let Some(room) = current_room.get() {
|
|
||||||
|
|
||||||
let messages = messages.get().get(&room).expect("Selected non-existant room").to_vec();
|
|
||||||
|
|
||||||
rsx! {
|
|
||||||
RoomView {
|
|
||||||
room: room.clone(),
|
|
||||||
messages: messages,
|
|
||||||
on_message_sent: move |x:String| {
|
|
||||||
println!("Message sent: {:?}", x);
|
|
||||||
cr.send(SendMessage {
|
|
||||||
recipient: room.clone(),
|
|
||||||
message: x,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user