use std::path::Path;
use std::time::Duration;
use ::app::application::get_current_team_and_thread;
use ::app::{Message, Messenger, ROSTER};
use ::kernel::teams::Team;
use ::support::Result;
const NOTIFICATION_MESSAGE: u32 = haiku_constant!('n','s','s','m');
const NOTIFICATION_SERVER_SIGNATURE: &str = "application/x-vnd.Haiku-notification_server";
#[derive(PartialEq)]
pub enum NotificationType {
Information,
Important,
Error,
Progress
}
pub struct Notification {
pub notification_type: NotificationType,
pub group: Option<String>,
pub title: Option<String>,
pub content: Option<String>,
pub id: Option<String>,
pub progress: f32,
source_signature: String,
source_name: String,
}
impl Default for Notification {
fn default() -> Self {
let (team, _) = get_current_team_and_thread();
let info = ROSTER.get_running_app_info(&Team::from(team).unwrap()).unwrap();
let filename = match Path::new(&info.path).file_name() {
Some(file) => String::from(file.to_str().unwrap()),
None => String::new()
};
Notification {
notification_type: NotificationType::Information,
group: None,
title: None,
content: None,
id: None,
progress: 0.0,
source_signature: info.signature,
source_name: filename,
}
}
}
impl Notification {
fn to_message(&self) -> Result<Message> {
let mut message = Message::new(NOTIFICATION_MESSAGE);
message.add_data("_appname", &self.source_name).unwrap();
message.add_data("_signature", &self.source_signature).unwrap();
let type_: i32 = match &self.notification_type {
NotificationType::Information => 0,
NotificationType::Important => 1,
NotificationType::Error => 2,
NotificationType::Progress => 3
};
message.add_data("_type", &type_).unwrap();
self.group.as_ref().map(|group| message.add_data("_group", group).unwrap());
self.title.as_ref().map(|title| message.add_data("_title", title).unwrap());
self.content.as_ref().map(|content| message.add_data("_content", content).unwrap());
self.id.as_ref().map(|id| message.add_data("_messageID", id).unwrap());
if self.notification_type == NotificationType::Progress {
message.add_data("_progress", &self.progress).unwrap();
}
if self.notification_type == NotificationType::Progress {
let progress = if self.progress < 0.0 {
0.0
} else if self.progress > 1.0 {
1.0
} else {
self.progress
};
message.add_data("_progress", &progress).unwrap();
}
Ok(message)
}
pub fn send(&self, replyto: &Messenger, duration: Option<Duration>) -> Result<()> {
let mut message = self.to_message()?;
let timeout_ms: i64 = match duration {
Some(d) => d.as_secs() as i64 * 1_000_000 + d.subsec_micros() as i64,
None => 0
};
if timeout_ms > 0 {
message.add_data("timeout", &timeout_ms).unwrap();
}
let messenger = Messenger::from_signature(NOTIFICATION_SERVER_SIGNATURE, None)?;
messenger.send(message, replyto)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use app::{Application, ApplicationDelegate, ApplicationHooks};
use super::*;
struct MockApplicationState { }
impl ApplicationHooks for MockApplicationState {
fn ready_to_run(&mut self, application: &ApplicationDelegate) {
let notification = Notification {
title: Some(String::from("Information")),
content: Some(String::from("This notification comes from Rust")),
.. Default::default()
};
notification.send(&application.messenger, None).unwrap();
application.quit();
}
}
const MOCK_SIGNATURE: &str = "application/notification_test";
#[test]
fn test_notification() {
let application = Application::new(MOCK_SIGNATURE, MockApplicationState {});
application.run().unwrap();
}
}