Skip to content

Commit

Permalink
Merge pull request #184 from hoodie/feature/configurable-busname
Browse files Browse the repository at this point in the history
configurable busname
  • Loading branch information
hoodie committed Apr 4, 2023
2 parents 09abb2a + f8e89cf commit bac08b0
Show file tree
Hide file tree
Showing 13 changed files with 445 additions and 115 deletions.
47 changes: 41 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ jobs:
toolchain: ${{ matrix.rust }}
override: true
- run: rustup component add clippy
- run: sudo apt-get install -y libdbus-1-dev

- name: check
uses: actions-rs/cargo@v1
Expand Down Expand Up @@ -142,7 +141,6 @@ jobs:
toolchain: ${{ matrix.rust }}
override: true
- run: rustup component add clippy
- run: sudo apt-get install -y libdbus-1-dev

- name: check
uses: actions-rs/cargo@v1
Expand All @@ -154,19 +152,56 @@ jobs:
uses: actions-rs/cargo@v1
with:
command: test
args: --lib --no-default-features --features "z images"
args: --lib --no-default-features --features z,images

- name: doctest_features_images (zbus)
uses: actions-rs/cargo@v1
with:
command: test
args: --doc --no-default-features --features "z images"
args: --doc --no-default-features --features z,images

- name: clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: --no-default-features --features "z images" -- -D warnings
args: --no-default-features --features z,images -- -D warnings

linux_zbus_and_dbus:
name: linux (zbus and dbus)
runs-on: ubuntu-latest
strategy:
matrix:
rust:
- stable
- 1.60.0
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: ${{ matrix.rust }}
override: true
- run: rustup component add clippy
- run: sudo apt-get install -y libdbus-1-dev

- name: check
uses: actions-rs/cargo@v1
with:
command: check
args: --no-default-features --features z,d

- name: test (zbus)
uses: actions-rs/cargo@v1
with:
command: test
args: --lib --no-default-features --features z,d

- name: doc_test (zbus)
uses: actions-rs/cargo@v1
with:
command: test
args: --doc --no-default-features --features z,d


windows:
name: windows
Expand Down Expand Up @@ -206,7 +241,7 @@ jobs:
matrix:
rust:
- stable
- 1.62.0
- 1.63.0
steps:
- uses: actions/checkout@v2
- uses: actions-rs/toolchain@v1
Expand Down
8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ authors = ["Hendrik Sollich <hendrik@hoodie.de>"]
description = "Show desktop notifications (linux, bsd, mac). Pure Rust dbus client and server."
repository = "https://github.com/hoodie/notify-rust"
documentation = "https://docs.rs/notify-rust/"
edition = "2018"
edition = "2021"
rust-version = "1.59.0"
license = "MIT/Apache-2.0"
keywords = ["desktop", "notification", "notify", "linux", "macos"]
Expand Down Expand Up @@ -38,7 +38,7 @@ winrt-notification = { package = "tauri-winrt-notification", version = "0.1" }

[features]
default = ["z"]
server = []
#`server = []
d = ["dbus"]
z = ["zbus", "serde", "async"]
async = []
Expand All @@ -50,6 +50,10 @@ color-backtrace = "0.5"
ctor = "0.1"
maplit = "1.0"

[dev-dependencies.async-std]
version = "1.12.0"
features = ["attributes"]

[[example]]
name = "images"
path = "examples/images.rs"
Expand Down
29 changes: 29 additions & 0 deletions examples/at_bus.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#[cfg(target_os = "macos")]
fn main() {
println!("this is an xdg only feature")
}

#[cfg(target_os = "windows")]
fn main() {
println!("this is an xdg only feature")
}

#[cfg(all(unix, not(target_os = "macos",)))]
fn main() -> Result<(), Box<dyn std::error::Error>> {
use notify_rust::Notification;
std::env::set_var(
"RUST_LOG",
"simple=trace,zbus=trace,server=trace,notify_rust=trace",
);
color_backtrace::install();
#[cfg(feature = "env_logger")]
env_logger::init();

#[allow(deprecated)]
Notification::at_bus("example")
.summary("Critical Error")
.body("Just <b>kidding</b>, this is just the notification (example).")
.icon("dialog-error")
.show()?;
Ok(())
}
19 changes: 9 additions & 10 deletions examples/simple_async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,15 @@ fn main() {
println!("this is an xdg only feature")
}

use notify_rust::Notification;

#[cfg(all(unix, not(target_os = "macos")))]
fn main() -> Result<(), Box<dyn std::error::Error>> {
zbus::block_on(
Notification::new()
.summary("async notification")
.body("this notification was sent via an async api")
.icon("dialog-positive")
.show_async(),
)?;
#[async_std::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
use notify_rust::Notification;
Notification::new()
.summary("async notification")
.body("this notification was sent via an async api")
.icon("dialog-positive")
.show_async()
.await?;
Ok(())
}
12 changes: 5 additions & 7 deletions examples/wait_for_closing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,13 @@ fn main() {
#[cfg(all(unix, not(target_os = "macos")))]

fn main() {
let handle = notify_rust::Notification::new()
use notify_rust::CloseReason;

notify_rust::Notification::new()
.summary("Don't Mind me")
.hint(notify_rust::Hint::Transient(true))
.body("I'll be gone soon enough.\nSorry for the inconvenience.")
.show()
.unwrap();
handle.wait_for_action(|action| {
if "__closed" == action {
println!("the notification was closed")
}
});
.unwrap()
.on_close(|reason: CloseReason| println!("the notification was closed reason: {reason:?}"));
}
7 changes: 3 additions & 4 deletions examples/wait_for_closing_async.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ fn main() {
#[cfg(all(unix, not(target_os = "macos")))]

fn main() {
use notify_rust::CloseReason;
use zbus::export::futures_util::FutureExt;

zbus::block_on(async {
Expand All @@ -21,10 +22,8 @@ fn main() {
.show_async()
.then(|handle| async move {
match handle {
Ok(handle) => handle.wait_for_action(|action| {
if "__closed" == action {
println!("the notification was closed")
}
Ok(handle) => handle.on_close(|reason: CloseReason| {
println!("the notification was closed reason: {reason:?}")
}),
Err(error) => println!("failed to send notification {error}"),
}
Expand Down
40 changes: 35 additions & 5 deletions src/notification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,9 @@ use crate::{error::*, timeout::Timeout};
#[cfg(all(unix, not(target_os = "macos")))]
use std::collections::{HashMap, HashSet};

use std::default::Default;
use std::env;

// Returns the name of the current executable, used as a default for `Notification.appname`.
fn exe_name() -> String {
env::current_exe()
std::env::current_exe()
.unwrap()
.file_name()
.unwrap()
Expand Down Expand Up @@ -81,12 +78,19 @@ pub struct Notification {

#[cfg(target_os = "macos")]
pub(crate) sound_name: Option<String>,

#[cfg(target_os = "windows")]
pub(crate) sound_name: Option<String>,

#[cfg(target_os = "windows")]
pub(crate) path_to_image: Option<String>,

#[cfg(target_os = "windows")]
pub(crate) app_id: Option<String>,

#[cfg(all(unix, not(target_os = "macos")))]
pub(crate) bus: xdg::NotificationBus,

/// Lifetime of the Notification in ms. Often not respected by server, sorry.
pub timeout: Timeout, // both gnome and galago want allow for -1

Expand All @@ -104,6 +108,20 @@ impl Notification {
Notification::default()
}

/// This is for testing purposes only and will not work with actual implementations.
#[cfg(all(unix, not(target_os = "macos")))]
#[doc(hidden)]
#[deprecated(note = "this is a test only feature")]
pub fn at_bus(sub_bus: &str) -> Notification {
let bus = xdg::NotificationBus::custom(sub_bus)
.ok_or("invalid subpath")
.unwrap();
Notification {
bus,
..Notification::default()
}
}

/// Overwrite the appname field used for Notification.
///
/// # Platform Support
Expand Down Expand Up @@ -400,11 +418,22 @@ impl Notification {
///
/// Returns a handle to a notification
#[cfg(all(unix, not(target_os = "macos")))]
#[cfg(feature = "async")]
#[cfg(all(feature = "async", feature = "zbus"))]
pub async fn show_async(&self) -> Result<xdg::NotificationHandle> {
xdg::show_notification_async(self).await
}

/// Sends Notification to D-Bus.
///
/// Returns a handle to a notification
#[cfg(all(unix, not(target_os = "macos")))]
#[cfg(feature = "async")]
// #[cfg(test)]
pub async fn show_async_at_bus(&self, sub_bus: &str) -> Result<xdg::NotificationHandle> {
let bus = crate::xdg::NotificationBus::custom(sub_bus).ok_or("invalid subpath")?;
xdg::show_notification_async_at_bus(self, bus).await
}

/// Sends Notification to `NSUserNotificationCenter`.
///
/// Returns an `Ok` no matter what, since there is currently no way of telling the success of
Expand Down Expand Up @@ -452,6 +481,7 @@ impl Default for Notification {
hints_unique: HashMap::new(),
actions: Vec::new(),
timeout: Timeout::Default,
bus: Default::default(),
id: None,
}
}
Expand Down
7 changes: 2 additions & 5 deletions src/timeout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,10 @@ impl std::ops::Deref for TimeoutMessage {
}

#[cfg(all(feature = "dbus", unix, not(target_os = "macos")))]
use dbus::arg::messageitem::MessageItem;

#[cfg(all(feature = "dbus", unix, not(target_os = "macos")))]
impl std::convert::TryFrom<&MessageItem> for TimeoutMessage {
impl TryFrom<&dbus::arg::messageitem::MessageItem> for TimeoutMessage {
type Error = ();

fn try_from(mi: &MessageItem) -> Result<TimeoutMessage, ()> {
fn try_from(mi: &dbus::arg::messageitem::MessageItem) -> Result<TimeoutMessage, ()> {
mi.inner::<i32>().map(|i| TimeoutMessage(i.into()))
}
}
4 changes: 2 additions & 2 deletions src/urgency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ use std::convert::TryFrom;
///
#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
pub enum Urgency {
/// The behaviour for `Low` urgency depends on the notification server.
/// The behavior for `Low` urgency depends on the notification server.
Low = 0,
/// The behaviour for `Normal` urgency depends on the notification server.
/// The behavior for `Normal` urgency depends on the notification server.
Normal = 1,
/// A critical notification will not time out.
Critical = 2,
Expand Down
68 changes: 68 additions & 0 deletions src/xdg/bus.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use crate::xdg::NOTIFICATION_DEFAULT_BUS;

fn skip_first_slash(s: &str) -> &str {
if let Some('/') = s.chars().next() {
&s[1..]
} else {
s
}
}

use std::path::PathBuf;

type BusNameType = std::borrow::Cow<'static, str>;

#[derive(Clone, Debug)]
pub struct NotificationBus(BusNameType);

impl Default for NotificationBus {
#[cfg(feature = "zbus")]
fn default() -> Self {
Self(
zbus::names::WellKnownName::from_static_str(NOTIFICATION_DEFAULT_BUS)
.unwrap()
.to_string()
.into(),
)
}

#[cfg(all(feature = "dbus", not(feature = "zbus")))]
fn default() -> Self {
Self(
dbus::strings::BusName::from_slice(NOTIFICATION_DEFAULT_BUS)
.unwrap()
.to_string()
.into(),
)
}
}

impl NotificationBus {
fn namespaced_custom(custom_path: &str) -> Option<String> {
// abusing path for semantic join
skip_first_slash(
PathBuf::from("/de/hoodie/Notification")
.join(custom_path)
.to_str()?,
)
.replace('/', ".")
.into()
}

#[cfg(feature = "zbus")]
pub fn custom(custom_path: &str) -> Option<Self> {
let name =
zbus::names::WellKnownName::try_from(Self::namespaced_custom(custom_path)?).ok()?;
Some(Self(name.to_string().into()))
}

#[cfg(all(feature = "dbus", not(feature = "zbus")))]
pub fn custom(custom_path: &str) -> Option<Self> {
let name = dbus::strings::BusName::new(Self::namespaced_custom(custom_path)?).ok()?;
Some(Self(name.to_string().into()))
}

pub fn into_name(self) -> BusNameType {
self.0
}
}
Loading

0 comments on commit bac08b0

Please sign in to comment.