110 lines
3.3 KiB
Rust
110 lines
3.3 KiB
Rust
use iced::widget::text::Shaping;
|
|
use iced::widget::{Space, button, container, row, text};
|
|
use iced::{Alignment, Background, Border, Color, Element, Length, Padding, Theme};
|
|
|
|
use crate::app::Message;
|
|
use crate::state::toast::{Toast, ToastLevel};
|
|
|
|
/// Background color per toast severity.
|
|
fn toast_bg(level: ToastLevel) -> Color {
|
|
match level {
|
|
ToastLevel::Info => Color::from_rgb(0.16, 0.22, 0.34),
|
|
ToastLevel::Success => Color::from_rgb(0.12, 0.30, 0.16),
|
|
ToastLevel::Warning => Color::from_rgb(0.38, 0.30, 0.10),
|
|
ToastLevel::Error => Color::from_rgb(0.38, 0.14, 0.14),
|
|
}
|
|
}
|
|
|
|
/// Border color per toast severity.
|
|
fn toast_border(level: ToastLevel) -> Color {
|
|
match level {
|
|
ToastLevel::Info => Color::from_rgb(0.25, 0.40, 0.65),
|
|
ToastLevel::Success => Color::from_rgb(0.20, 0.55, 0.25),
|
|
ToastLevel::Warning => Color::from_rgb(0.65, 0.50, 0.15),
|
|
ToastLevel::Error => Color::from_rgb(0.65, 0.20, 0.20),
|
|
}
|
|
}
|
|
|
|
fn toast_style(level: ToastLevel) -> impl Fn(&Theme) -> container::Style {
|
|
move |_theme: &Theme| container::Style {
|
|
background: Some(Background::Color(toast_bg(level))),
|
|
border: Border {
|
|
color: toast_border(level),
|
|
width: 1.0,
|
|
radius: 8.0.into(),
|
|
},
|
|
..container::Style::default()
|
|
}
|
|
}
|
|
|
|
fn dismiss_btn(_theme: &Theme, status: button::Status) -> button::Style {
|
|
let color = match status {
|
|
button::Status::Hovered => Color::WHITE,
|
|
_ => Color::from_rgb(0.65, 0.65, 0.70),
|
|
};
|
|
button::Style {
|
|
background: Some(Background::Color(Color::TRANSPARENT)),
|
|
text_color: color,
|
|
border: Border::default(),
|
|
..button::Style::default()
|
|
}
|
|
}
|
|
|
|
/// Render the toast stack as an overlay element.
|
|
///
|
|
/// Returns `None` when no toasts are visible.
|
|
pub fn view(toasts: &[Toast]) -> Option<Element<'static, Message>> {
|
|
if toasts.is_empty() {
|
|
return None;
|
|
}
|
|
|
|
let items: Vec<Element<'static, Message>> = toasts
|
|
.iter()
|
|
.map(|toast| {
|
|
let level = toast.level;
|
|
let dismiss = button(text("\u{2715}").size(11).shaping(Shaping::Advanced))
|
|
.on_press(Message::DismissToast(toast.id))
|
|
.padding([2, 4])
|
|
.style(dismiss_btn);
|
|
|
|
container(
|
|
row![
|
|
text(toast.message.clone())
|
|
.size(12)
|
|
.shaping(Shaping::Advanced)
|
|
.color(Color::WHITE),
|
|
Space::with_width(Length::Fill),
|
|
dismiss,
|
|
]
|
|
.spacing(8)
|
|
.align_y(Alignment::Center)
|
|
.padding([6, 12]),
|
|
)
|
|
.width(Length::Fixed(420.0))
|
|
.style(toast_style(level))
|
|
.into()
|
|
})
|
|
.collect();
|
|
|
|
Some(
|
|
container(
|
|
container(
|
|
iced::widget::Column::with_children(items)
|
|
.spacing(4)
|
|
.align_x(Alignment::Center),
|
|
)
|
|
.width(Length::Fill)
|
|
.align_x(Alignment::Center)
|
|
.padding(Padding {
|
|
top: 8.0,
|
|
right: 0.0,
|
|
bottom: 0.0,
|
|
left: 0.0,
|
|
}),
|
|
)
|
|
.width(Length::Fill)
|
|
.height(Length::Shrink)
|
|
.into(),
|
|
)
|
|
}
|