use std::{fmt, str::FromStr};
use serde::{self, Deserialize, Serialize, Serializer};
use zbus::zvariant::{DeserializeDict, OwnedValue, SerializeDict, Signature, Type};
use super::{DESTINATION, PATH};
use crate::{
helpers::{call_method, receive_signal},
Error,
};
#[derive(Debug, Clone, Deserialize, PartialEq, Eq)]
pub enum Priority {
Low,
Normal,
High,
Urgent,
}
impl fmt::Display for Priority {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Low => write!(f, "Low"),
Self::Normal => write!(f, "Normal"),
Self::High => write!(f, "High"),
Self::Urgent => write!(f, "Urgent"),
}
}
}
impl AsRef<str> for Priority {
fn as_ref(&self) -> &str {
match self {
Self::Low => "Low",
Self::Normal => "Normal",
Self::High => "High",
Self::Urgent => "Urgent",
}
}
}
impl From<Priority> for &'static str {
fn from(d: Priority) -> Self {
match d {
Priority::Low => "Low",
Priority::Normal => "Normal",
Priority::High => "High",
Priority::Urgent => "Urgent",
}
}
}
impl FromStr for Priority {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"Low" | "low" => Ok(Priority::Low),
"Normal" | "normal" => Ok(Priority::Normal),
"High" | "high" => Ok(Priority::High),
"Urgent" | "urgent" => Ok(Priority::Urgent),
_ => Err(Error::ParseError(
"Failed to parse priority, invalid value".to_string(),
)),
}
}
}
impl Serialize for Priority {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string().to_lowercase())
}
}
impl Type for Priority {
fn signature() -> Signature<'static> {
String::signature()
}
}
#[derive(SerializeDict, DeserializeDict, Type, Debug)]
#[zvariant(signature = "dict")]
pub struct Notification {
title: String,
body: Option<String>,
icon: Option<OwnedValue>,
priority: Option<Priority>,
#[zvariant(rename = "default-action")]
default_action: Option<String>,
#[zvariant(rename = "default-action-target")]
default_action_target: Option<OwnedValue>,
buttons: Option<Vec<Button>>,
}
impl Notification {
pub fn new(title: &str) -> Self {
Self {
title: title.to_string(),
body: None,
priority: None,
icon: None,
default_action: None,
default_action_target: None,
buttons: None,
}
}
#[must_use]
pub fn body(mut self, body: &str) -> Self {
self.body = Some(body.to_string());
self
}
#[must_use]
pub fn icon(mut self, icon: OwnedValue) -> Self {
self.icon = Some(icon);
self
}
#[must_use]
pub fn priority(mut self, priority: Priority) -> Self {
self.priority = Some(priority);
self
}
#[must_use]
pub fn default_action(mut self, default_action: &str) -> Self {
self.default_action = Some(default_action.to_string());
self
}
#[must_use]
pub fn default_action_target(mut self, default_action_target: OwnedValue) -> Self {
self.default_action_target = Some(default_action_target);
self
}
#[must_use]
pub fn button(mut self, button: Button) -> Self {
match self.buttons {
Some(ref mut buttons) => buttons.push(button),
None => {
self.buttons.replace(vec![button]);
}
};
self
}
}
#[derive(SerializeDict, DeserializeDict, Type, Debug)]
#[zvariant(signature = "dict")]
pub struct Button {
label: String,
action: String,
target: Option<OwnedValue>,
}
impl Button {
pub fn new(label: &str, action: &str) -> Self {
Self {
label: label.to_string(),
action: action.to_string(),
target: None,
}
}
#[must_use]
pub fn target(mut self, target: OwnedValue) -> Self {
self.target = Some(target);
self
}
}
#[derive(Debug, Serialize, Deserialize, Type)]
pub struct Action(String, String, Vec<OwnedValue>);
impl Action {
pub fn id(&self) -> &str {
&self.0
}
pub fn name(&self) -> &str {
&self.1
}
pub fn parameter(&self) -> &Vec<OwnedValue> {
&self.2
}
}
#[derive(Debug)]
#[doc(alias = "org.freedesktop.portal.Notification")]
pub struct NotificationProxy<'a>(zbus::Proxy<'a>);
impl<'a> NotificationProxy<'a> {
pub async fn new(connection: &zbus::Connection) -> Result<NotificationProxy<'a>, Error> {
let proxy = zbus::ProxyBuilder::new_bare(connection)
.interface("org.freedesktop.portal.Notification")?
.path(PATH)?
.destination(DESTINATION)?
.build()
.await?;
Ok(Self(proxy))
}
pub fn inner(&self) -> &zbus::Proxy<'_> {
&self.0
}
#[doc(alias = "ActionInvoked")]
#[doc(alias = "XdpPortal::notification-action-invoked")]
pub async fn receive_action_invoked(&self) -> Result<Action, Error> {
receive_signal(self.inner(), "ActionInvoked").await
}
#[doc(alias = "AddNotification")]
#[doc(alias = "xdp_portal_add_notification")]
pub async fn add_notification(
&self,
id: &str,
notification: Notification,
) -> Result<(), Error> {
call_method(self.inner(), "AddNotification", &(id, notification)).await
}
#[doc(alias = "RemoveNotification")]
#[doc(alias = "xdp_portal_remove_notification")]
pub async fn remove_notification(&self, id: &str) -> Result<(), Error> {
call_method(self.inner(), "RemoveNotification", &(id)).await
}
}