Files
jap_learn/src/notification.rs
T

178 lines
5.3 KiB
Rust
Raw Normal View History

2026-08-23 21:00:48 +03:00
use crate::navigation::RootMessage;
use crate::styling::{BUTTON_RADIUS, HALF_SPACING};
use chrono::Utc;
use iced::widget::container::Style;
2026-08-23 22:05:08 +03:00
use iced::widget::{Column, column, container, row, scrollable, text};
2026-08-23 21:00:48 +03:00
use iced::{Element, Task};
2026-08-23 22:05:08 +03:00
use iced_core::Alignment::Center;
2026-08-23 21:00:48 +03:00
use iced_core::Background::Color;
use iced_core::Border;
use iced_core::Length::Fill;
2026-08-23 22:05:08 +03:00
use iced_core::alignment::Horizontal::Right;
use iced_core::alignment::Vertical;
2026-08-23 21:00:48 +03:00
pub struct NotificationManager {
list: Vec<(u32, NotificationRequest, u32)>,
notification_lifetime: u32,
next_id: u32,
}
#[derive(Clone)]
pub enum NotificationMessage {
Remove(u32),
}
impl Default for NotificationManager {
fn default() -> Self {
Self::new()
}
}
impl NotificationManager {
pub fn new() -> Self {
Self {
list: Vec::new(),
notification_lifetime: 10,
next_id: 1,
}
}
pub fn draw(&self) -> Element<'_, NotificationMessage> {
let mut column = Column::new().spacing(HALF_SPACING);
for (id, notif, time) in &self.list {
column = column.push(Self::draw_notif(id, notif, time));
}
2026-08-23 22:05:08 +03:00
container(scrollable(column))
.width(Fill)
.height(Fill)
2026-08-23 21:00:48 +03:00
.align_x(Right)
2026-08-23 22:05:08 +03:00
.align_y(Vertical::Top)
.padding(HALF_SPACING)
2026-08-23 21:00:48 +03:00
.into()
}
pub fn push(&mut self, notification: NotificationRequest) -> Task<RootMessage> {
let id = self.next_id;
self.list.push((
id,
notification,
Utc::now().timestamp() as u32 + self.notification_lifetime,
));
self.next_id += 1;
let message = NotificationMessage::Remove(id);
let time = self.notification_lifetime;
Task::perform(
async move {
tokio::time::sleep(core::time::Duration::from_secs(time as u64)).await;
},
|_| RootMessage::Notification(message),
)
}
pub fn update(&mut self, message: NotificationMessage) -> Task<RootMessage> {
match message {
NotificationMessage::Remove(id) => {
if let Some(index) = self.list.iter().position(|item| item.0 == id) {
self.list.remove(index);
}
}
}
Task::none()
}
fn draw_notif<'a>(
id: &u32,
notif: &NotificationRequest,
_time: &u32,
) -> Element<'a, NotificationMessage> {
let color_id;
let content = match notif {
NotificationRequest::Info(data) => {
color_id = 1;
Self::draw_data(data)
}
NotificationRequest::Warning(data) => {
color_id = 2;
Self::draw_data(data)
}
NotificationRequest::Error(data) => {
color_id = 3;
Self::draw_data(data)
}
};
2026-08-23 22:05:08 +03:00
let container = container(
row![
content,
iced::widget::button("✕")
.on_press(NotificationMessage::Remove(*id))
.style(iced::widget::button::text)
].align_y(Center).width(300)
.padding(HALF_SPACING),
);
2026-08-23 21:00:48 +03:00
container
.style(move |theme| {
let color = match color_id {
1 => theme.palette().success,
2 => theme.palette().warning,
3 => theme.palette().danger,
_ => theme.palette().warning,
};
Style {
text_color: None,
background: Some(Color(color.scale_alpha(0.3))),
2026-08-23 22:05:08 +03:00
border: Border::default()
.width(1)
.color(color)
.rounded(BUTTON_RADIUS),
2026-08-23 21:00:48 +03:00
shadow: Default::default(),
snap: false,
}
})
.into()
}
fn draw_data<'a>(data: &NotificationData) -> Element<'a, NotificationMessage> {
match data {
NotificationData::DataLoaded => {
text!("Данные успешно скачаны")
}
NotificationData::ImportError => {
text!("Ошибка при импорте данных из Anki")
}
NotificationData::IncorrectAnkiFile => {
text!("Неподдерживаемый формат файла .apkg")
}
NotificationData::OpenFileError => {
text!("Ошибка открытия файла пакета")
}
NotificationData::VoiceVoxUnavailable => {
text!("Не получается подключиться к VoiceVox")
}
NotificationData::PermissionDenied => {
text!("У приложение недостаточно прав")
}
2026-08-23 21:00:48 +03:00
}
2026-08-23 22:05:08 +03:00
.width(Fill)
2026-08-23 21:00:48 +03:00
.into()
}
}
#[derive(Clone)]
pub enum NotificationRequest {
Info(NotificationData),
Warning(NotificationData),
Error(NotificationData),
}
#[derive(Clone)]
pub enum NotificationData {
PermissionDenied,
2026-08-23 21:00:48 +03:00
DataLoaded,
ImportError,
IncorrectAnkiFile,
OpenFileError,
2026-08-23 22:05:08 +03:00
VoiceVoxUnavailable,
2026-08-23 21:00:48 +03:00
}