Files
leaf/examples/meet/src/components/chat.rs
Timur Gordon 7ca492346d livekit wip
2025-08-29 15:29:24 +02:00

116 lines
4.0 KiB
Rust

use yew::prelude::*;
use web_sys::HtmlTextAreaElement;
use crate::pages::room::ChatMessage;
#[derive(Properties, PartialEq)]
pub struct ChatSidebarProps {
pub messages: Vec<ChatMessage>,
pub on_send_message: Callback<String>,
}
#[function_component(ChatSidebar)]
pub fn chat_sidebar(props: &ChatSidebarProps) -> Html {
let input_ref = use_node_ref();
let message_input = use_state(|| String::new());
let on_input_change = {
let message_input = message_input.clone();
Callback::from(move |e: InputEvent| {
let input: HtmlTextAreaElement = e.target_unchecked_into();
message_input.set(input.value());
})
};
let on_send = {
let message_input = message_input.clone();
let on_send_message = props.on_send_message.clone();
let input_ref = input_ref.clone();
Callback::from(move |e: KeyboardEvent| {
if e.key() == "Enter" && !e.shift_key() {
e.prevent_default();
let content = (*message_input).trim().to_string();
if !content.is_empty() {
on_send_message.emit(content);
message_input.set(String::new());
if let Some(input) = input_ref.cast::<HtmlTextAreaElement>() {
input.set_value("");
}
}
}
})
};
let on_send_button = {
let message_input = message_input.clone();
let on_send_message = props.on_send_message.clone();
let input_ref = input_ref.clone();
Callback::from(move |_: MouseEvent| {
let content = (*message_input).trim().to_string();
if !content.is_empty() {
on_send_message.emit(content);
message_input.set(String::new());
if let Some(input) = input_ref.cast::<HtmlTextAreaElement>() {
input.set_value("");
}
}
})
};
html! {
<div class="chat-sidebar">
<div class="chat-header">
{"Chat"}
</div>
<div class="chat-messages">
{for props.messages.iter().map(|message| {
html! {
<div key={message.id.clone()} class="chat-message">
<div class="chat-message-author">
{&message.author}
<span style="margin-left: 0.5rem; font-size: 0.75rem; color: var(--lk-fg-2);">
{message.timestamp.format("%H:%M").to_string()}
</span>
</div>
<div class="chat-message-content">
{&message.content}
</div>
</div>
}
})}
{if props.messages.is_empty() {
html! {
<div style="text-align: center; color: var(--lk-fg-2); margin-top: 2rem;">
{"No messages yet. Start the conversation!"}
</div>
}
} else {
html! {}
}}
</div>
<div class="chat-input-container">
<textarea
ref={input_ref}
class="chat-input"
placeholder="Type a message..."
value={(*message_input).clone()}
oninput={on_input_change}
onkeydown={on_send}
rows="2"
/>
<button
class="primary-button"
style="margin-top: 0.5rem; padding: 0.5rem 1rem;"
onclick={on_send_button}
disabled={message_input.trim().is_empty()}
>
{"Send"}
</button>
</div>
</div>
}
}