2024-07-23 22:45:45 -04:00
|
|
|
use crate::components::websocket::WebSocketContext;
|
|
|
|
use html::{Input, Textarea};
|
|
|
|
use leptos::*;
|
|
|
|
use leptos_use::core::ConnectionReadyState;
|
2024-08-04 18:14:10 -04:00
|
|
|
use lib::*;
|
2024-07-25 00:18:27 -04:00
|
|
|
use serde_json::to_string;
|
2024-07-23 22:45:45 -04:00
|
|
|
|
|
|
|
#[component]
|
|
|
|
pub fn Chat() -> impl IntoView {
|
|
|
|
let websocket = expect_context::<WebSocketContext>();
|
2024-07-24 22:06:19 -04:00
|
|
|
let chat_context = expect_context::<ReadSignal<Option<ChatMessage>>>();
|
2024-07-28 01:38:32 -04:00
|
|
|
let chat_update_context = expect_context::<ReadSignal<Option<ChatUpdate>>>();
|
2024-08-04 22:20:28 -04:00
|
|
|
let connected = move || websocket.ready_state.get() == ConnectionReadyState::Open;
|
2024-07-23 22:45:45 -04:00
|
|
|
|
|
|
|
// Chat stuff
|
|
|
|
let (chat_history, set_chat_history) = create_signal::<Vec<String>>(vec![]);
|
2024-07-28 01:38:32 -04:00
|
|
|
let (users, set_users) = create_signal::<Vec<String>>(vec![]);
|
2024-07-29 00:53:42 -04:00
|
|
|
let (chat_name, set_chat_name) = create_signal::<String>("".to_string());
|
2024-07-23 22:45:45 -04:00
|
|
|
let chat_history_ref = create_node_ref::<Textarea>();
|
|
|
|
let chat_input_ref = create_node_ref::<Input>();
|
|
|
|
|
|
|
|
fn update_chat_history(&history: &WriteSignal<Vec<String>>, message: String) {
|
|
|
|
let _ = &history.update(|history: &mut Vec<_>| history.push(message));
|
|
|
|
}
|
|
|
|
|
|
|
|
// Connection status updates in chat window
|
|
|
|
create_effect(move |_| {
|
|
|
|
websocket.ready_state.with(move |state| match *state {
|
|
|
|
ConnectionReadyState::Connecting => {
|
2024-07-24 19:21:16 -04:00
|
|
|
update_chat_history(
|
|
|
|
&set_chat_history,
|
|
|
|
"Connecting to game server...\n".to_string(),
|
|
|
|
);
|
2024-07-23 22:45:45 -04:00
|
|
|
}
|
|
|
|
ConnectionReadyState::Open => {
|
2024-07-24 19:21:16 -04:00
|
|
|
update_chat_history(&set_chat_history, "Connected!\n".to_string());
|
2024-07-23 22:45:45 -04:00
|
|
|
}
|
|
|
|
ConnectionReadyState::Closing => {
|
2024-07-24 19:21:16 -04:00
|
|
|
update_chat_history(&set_chat_history, "Disconnecting...\n".to_string());
|
2024-07-23 22:45:45 -04:00
|
|
|
}
|
|
|
|
ConnectionReadyState::Closed => {
|
2024-07-24 19:21:16 -04:00
|
|
|
update_chat_history(&set_chat_history, "Disconnected.\n".to_string());
|
2024-07-23 22:45:45 -04:00
|
|
|
}
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
2024-07-24 22:06:19 -04:00
|
|
|
// Handle incoming chat messages
|
2024-07-23 22:45:45 -04:00
|
|
|
create_effect(move |_| {
|
2024-07-24 22:06:19 -04:00
|
|
|
chat_context.with(move |chat_message| {
|
|
|
|
if let Some(message) = chat_message {
|
|
|
|
update_chat_history(&set_chat_history, format!("{}\n", message.text));
|
2024-07-23 22:45:45 -04:00
|
|
|
}
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
2024-07-28 01:38:32 -04:00
|
|
|
// Handle users
|
|
|
|
create_effect(move |_| {
|
|
|
|
chat_update_context.with(move |chat_update| {
|
|
|
|
if let Some(update) = chat_update {
|
|
|
|
set_users(update.users.clone());
|
2024-07-29 00:53:42 -04:00
|
|
|
set_chat_name(update.room.clone());
|
2024-07-28 01:38:32 -04:00
|
|
|
}
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
|
|
|
// Clear user list on disconnect
|
|
|
|
create_effect(move |_| {
|
|
|
|
websocket.ready_state.with(move |status| {
|
|
|
|
if *status == ConnectionReadyState::Closed {
|
|
|
|
set_users(vec![]);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
2024-07-24 22:06:19 -04:00
|
|
|
// Handle sending messages
|
2024-07-23 22:45:45 -04:00
|
|
|
let send_message = move |_| {
|
2024-08-04 22:20:28 -04:00
|
|
|
if let Some(input) = chat_input_ref.get() {
|
|
|
|
if input.value() != String::from("") {
|
|
|
|
websocket.send(
|
|
|
|
&to_string(&ChatMessage {
|
|
|
|
text: input.value(),
|
|
|
|
})
|
|
|
|
.unwrap(),
|
|
|
|
);
|
|
|
|
input.set_value("");
|
|
|
|
}
|
|
|
|
}
|
2024-07-23 22:45:45 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
// Keep chat scrolled to the bottom
|
|
|
|
create_effect(move |_| {
|
|
|
|
chat_history.with(move |_| {
|
|
|
|
// Scroll chat textarea to bottom
|
|
|
|
if let Some(hist) = chat_history_ref.get() {
|
|
|
|
hist.set_scroll_top(hist.scroll_height());
|
|
|
|
}
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
|
|
|
view! {
|
|
|
|
<div class="p-1">
|
2024-07-29 00:53:42 -04:00
|
|
|
<h2 class="text-2xl">Chat: {move || chat_name()}</h2>
|
2024-07-28 01:38:32 -04:00
|
|
|
<span class="flex">
|
2024-07-28 02:36:04 -04:00
|
|
|
<textarea
|
|
|
|
node_ref=chat_history_ref
|
|
|
|
class="w-96 h-60 font-mono rounded-sm resize-none bg-slate-900 text-slate-200"
|
|
|
|
readonly=true
|
|
|
|
wrap="soft"
|
|
|
|
>
|
|
|
|
{move || chat_history.get()}
|
|
|
|
</textarea>
|
|
|
|
<ul>
|
2024-07-29 00:53:42 -04:00
|
|
|
<h2 class="text-2xl">Users: {move || users().len()}</h2>
|
2024-07-28 02:36:04 -04:00
|
|
|
{move || users().into_iter().map(|n| view! { <li>{n}</li> }).collect_view()}
|
|
|
|
</ul>
|
2024-07-28 01:38:32 -04:00
|
|
|
</span>
|
|
|
|
|
2024-07-23 22:45:45 -04:00
|
|
|
<br/>
|
|
|
|
<span>
|
2024-07-28 02:36:04 -04:00
|
|
|
<form onsubmit="return false" on:submit=send_message>
|
|
|
|
<input
|
|
|
|
class="w-80 h-11 font-mono rounded-sm bg-slate-900 text-slate-200"
|
|
|
|
placeholder="talk shit..."
|
|
|
|
node_ref=chat_input_ref
|
|
|
|
/>
|
|
|
|
<input
|
|
|
|
class="py-2 px-4 pl-4 font-bold text-white rounded border-b-4 bg-slate-600 border-slate-800 hover:bg-slate-700 hover:border-slate-500"
|
|
|
|
type="submit"
|
|
|
|
value="Send"
|
2024-08-04 22:20:28 -04:00
|
|
|
disabled=move || !connected()
|
2024-07-28 02:36:04 -04:00
|
|
|
/>
|
|
|
|
</form>
|
2024-07-23 22:45:45 -04:00
|
|
|
</span>
|
|
|
|
<br/>
|
|
|
|
</div>
|
|
|
|
}
|
|
|
|
}
|