Co-authored-by: Sharang Parnerkar <parnerkarsharang@gmail.com> Reviewed-on: #1
93 lines
2.3 KiB
Rust
93 lines
2.3 KiB
Rust
use dioxus::prelude::*;
|
|
|
|
#[derive(Clone, PartialEq)]
|
|
pub enum ToastType {
|
|
Success,
|
|
Error,
|
|
Info,
|
|
}
|
|
|
|
#[derive(Clone, PartialEq)]
|
|
pub struct ToastMessage {
|
|
pub id: usize,
|
|
pub message: String,
|
|
pub toast_type: ToastType,
|
|
}
|
|
|
|
#[derive(Clone, Copy)]
|
|
pub struct Toasts {
|
|
items: Signal<Vec<ToastMessage>>,
|
|
next_id: Signal<usize>,
|
|
}
|
|
|
|
impl Default for Toasts {
|
|
fn default() -> Self {
|
|
Self::new()
|
|
}
|
|
}
|
|
|
|
impl Toasts {
|
|
pub fn new() -> Self {
|
|
Self {
|
|
items: Signal::new(vec![]),
|
|
next_id: Signal::new(0),
|
|
}
|
|
}
|
|
|
|
pub fn push(&mut self, toast_type: ToastType, message: impl Into<String>) {
|
|
let id = *self.next_id.read();
|
|
*self.next_id.write() = id + 1;
|
|
self.items.write().push(ToastMessage {
|
|
id,
|
|
message: message.into(),
|
|
toast_type,
|
|
});
|
|
|
|
#[cfg(feature = "web")]
|
|
{
|
|
let mut items = self.items;
|
|
spawn(async move {
|
|
gloo_timers::future::TimeoutFuture::new(4_000).await;
|
|
items.write().retain(|t| t.id != id);
|
|
});
|
|
}
|
|
}
|
|
|
|
pub fn remove(&mut self, id: usize) {
|
|
self.items.write().retain(|t| t.id != id);
|
|
}
|
|
}
|
|
|
|
#[component]
|
|
pub fn ToastContainer() -> Element {
|
|
let mut toasts = use_context::<Toasts>();
|
|
let items = toasts.items.read();
|
|
|
|
rsx! {
|
|
div { class: "toast-container",
|
|
for toast in items.iter() {
|
|
{
|
|
let toast_id = toast.id;
|
|
let type_class = match toast.toast_type {
|
|
ToastType::Success => "toast-success",
|
|
ToastType::Error => "toast-error",
|
|
ToastType::Info => "toast-info",
|
|
};
|
|
rsx! {
|
|
div {
|
|
key: "{toast_id}",
|
|
class: "toast {type_class}",
|
|
span { "{toast.message}" }
|
|
button {
|
|
class: "toast-dismiss",
|
|
onclick: move |_| toasts.remove(toast_id),
|
|
"\u{00d7}"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|