1use serde::{Deserialize, Serialize};
2use std::time::Duration;
3use crate::fabric::{
4 prelude::*,
5 services::timeout::{TimeoutService, TimeoutTask},
6};
7
8pub enum Msg {
9 RemoveShow,
10}
11
12#[derive(Clone, Serialize, Deserialize)]
13pub enum ToastStatus {
14 Success,
15 Error,
16}
17
18impl std::fmt::Display for ToastStatus {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 let s = match self {
21 ToastStatus::Success => "success",
22 ToastStatus::Error => "error",
23 };
24 write!(f, "{}", s)
25 }
26}
27
28#[derive(Clone, Serialize, Deserialize)]
29pub struct ToastBody {
30 pub status: ToastStatus,
31 pub title: String,
32 pub delay: u64,
33}
34
35#[derive(Clone, Properties)]
36pub struct Props {
37 pub body: ToastBody,
38}
39
40pub struct Toast {
41 body: ToastBody,
42 #[allow(dead_code)]
43 timeout_task: Option<TimeoutTask>,
44 toast_show: bool,
45}
46
47impl Component for Toast {
48 type Message = Msg;
49 type Properties = Props;
50
51 fn create(props: Self::Properties, link: ComponentLink<Self>) -> Toast {
52 let mut timeout_service = TimeoutService::new();
53 let callback = link.callback(|_| Msg::RemoveShow);
54 let timeout_task = timeout_service.spawn(Duration::from_millis(500), callback);
55
56 Toast {
57 body: props.body,
58 timeout_task: Some(timeout_task),
59 toast_show: true,
60 }
61 }
62
63 fn update(&mut self, msg: Self::Message) -> ShouldRender {
64 match msg {
65 Msg::RemoveShow => {
66 self.toast_show = false;
67 }
68 }
69 true
70 }
71
72 fn view(&self) -> Html {
73 let toast_class = format!("toast toast-{} {}", self.body.status, self.toast_show());
74
75 html! {
76 <div class=toast_class>
77 <div class="toast-header">
78 { self.body.title.clone() }
79 </div>
80 </div>
81 }
82 }
83}
84
85impl Toast {
86 fn toast_show(&self) -> &str {
87 if self.toast_show {
88 "toast-show"
89 } else {
90 ""
91 }
92 }
93}