lan-party-backend/web/src/components/messages.rs

106 lines
2.7 KiB
Rust

use gloo_timers::future::TimeoutFuture;
use log::debug;
use sycamore::{futures::spawn_local_scoped, prelude::*};
use wasm_bindgen_futures::spawn_local;
const MESSAGE_TIME: u32 = 5000;
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Message {
id: usize,
title: String,
text: String,
}
impl Message {
pub fn new(title: String, text: String) -> Self {
Self { id: 0, title, text }
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Messenger {
counter: RcSignal<usize>,
messages: RcSignal<Vec<Message>>,
}
impl Messenger {
pub fn add_message(&self, mut message: Message) {
message.id = *self.counter.get_untracked();
self.counter.set(*self.counter.get_untracked() + 1);
self.messages.modify().push(message);
}
pub fn info(&self, title: impl Into<String>, text: impl Into<String>) {
self.add_message(Message::new(title.into(), text.into()));
}
pub fn add_result<T>(
&self,
result: anyhow::Result<T>,
success: Option<impl Into<String>>,
fail: Option<impl Into<String>>,
) {
match result {
Ok(_) => {
if let Some(success) = success {
self.add_message(Message::new(success.into(), String::new()))
}
}
Err(e) => {
if let Some(fail) = fail {
self.add_message(Message::new(fail.into(), e.to_string()))
}
}
}
}
pub fn remove_message(&self) {
self.messages.modify().remove(0);
}
pub fn len(&self) -> usize {
self.messages.get_untracked().len()
}
}
#[component]
pub fn Messages<'a, G: Html>(cx: Scope<'a>) -> View<G> {
let messages = use_context::<Messenger>(cx);
create_effect(cx, move || {
messages.messages.track();
if messages.len() > 0 {
spawn_local_scoped(cx, async move {
debug!("Spawn");
TimeoutFuture::new(MESSAGE_TIME).await;
debug!("Remove");
messages.remove_message();
});
}
});
view! { cx,
div(class="messages") {
Keyed(
iterable=&messages.messages,
view=move |cx, message| {
view! { cx,
div(class="message") {
p(class="message-title") {
(message.title)
}
p(class="message-text") {
(message.text)
}
}
}
},
key=|message| (message.id),
)
}
}
}