toast_logger_win/
notification.rs

1use crate::Result;
2
3#[cfg(doc)]
4use crate::ToastLoggerBuilder;
5
6/// A struct to own copies of parts of [`log::Record`] for buffering.
7///
8/// The [`log::Record`] has lifetime for the lower overhead,
9/// and it's not suitable to buffer them.
10/// This struct captures the data needed for longer lifetime.
11#[derive(Debug, PartialEq, Eq)]
12pub struct BufferedRecord {
13    pub level: log::Level,
14    pub args: String,
15}
16
17impl BufferedRecord {
18    pub fn new_with_formatted_args(record: &log::Record, args: &str) -> Self {
19        Self {
20            level: record.level(),
21            args: args.to_string(),
22        }
23    }
24
25    pub fn level(&self) -> log::Level {
26        self.level
27    }
28
29    pub fn args(&self) -> &str {
30        &self.args
31    }
32}
33
34/// Abstracted notification.
35///
36/// This struct is to provide a hook point before the notification is shown.
37/// Please see [`ToastLoggerBuilder::create_notification`] for
38/// how to add the hook.
39///
40/// # Underlying Implementations
41///
42/// There are two underlying implementations.
43/// * An internal implementation using the [`windows` crate].
44///   This is the default.
45/// * The [`winrt-toast` crate] implementation is
46///   enabled by the feature `winrt-toast`.
47///   This crate provides additional features and controls.
48///
49/// [`windows` crate]: https://crates.io/crates/windows
50/// [`winrt-toast` crate]: https://docs.rs/winrt-toast/latest/winrt_toast/
51pub struct Notification {
52    #[cfg(not(feature = "winrt-toast"))]
53    inner: crate::win::NotificationImpl,
54    #[cfg(feature = "winrt-toast")]
55    inner: winrt_toast::Toast,
56}
57
58impl Notification {
59    /// Construct from a string.
60    pub fn new_with_text(text: &str) -> Result<Self> {
61        Ok(Self {
62            #[cfg(not(feature = "winrt-toast"))]
63            inner: crate::win::NotificationImpl::new_with_text(text)?,
64            #[cfg(feature = "winrt-toast")]
65            inner: {
66                let mut toast = winrt_toast::Toast::new();
67                toast.text1(text);
68                toast
69            },
70        })
71    }
72
73    /// Construct from a list of [`BufferedRecord`].
74    pub fn new_with_records(records: &[BufferedRecord]) -> Result<Self> {
75        let text = records
76            .iter()
77            .map(|r| r.args.as_str())
78            .collect::<Vec<_>>()
79            .join("\n");
80        Self::new_with_text(&text)
81    }
82
83    /// Set the expirations of this notification.
84    /// Please see [`ToastNotification.ExpirationTime`].
85    ///
86    /// [`ToastNotification.ExpirationTime`]: https://learn.microsoft.com/uwp/api/windows.ui.notifications.toastnotification.expirationtime
87    pub fn expires_in(&mut self, duration: std::time::Duration) -> Result<()> {
88        #[cfg(not(feature = "winrt-toast"))]
89        self.inner.expires_in(duration)?;
90        #[cfg(feature = "winrt-toast")]
91        self.inner.expires_in(duration);
92        Ok(())
93    }
94
95    /// The inner [`winrt_toast::Toast`].
96    ///
97    /// Available only when the "`winrt-toast`" feature is enabled.
98    #[cfg(feature = "winrt-toast")]
99    // error[E0658]: `#[doc(cfg)]` is experimental
100    // https://github.com/rust-lang/rust/issues/43781
101    // #[cfg_attr(docsrs, doc(cfg(feature = "winrt-toast")))]
102    pub fn inner(&self) -> &winrt_toast::Toast {
103        &self.inner
104    }
105
106    /// The mutable inner [`winrt_toast::Toast`].
107    ///
108    /// Available only when the "`winrt-toast`" feature is enabled.
109    #[cfg(feature = "winrt-toast")]
110    // error[E0658]: `#[doc(cfg)]` is experimental
111    // https://github.com/rust-lang/rust/issues/43781
112    // #[cfg_attr(docsrs, doc(cfg(feature = "winrt-toast")))]
113    pub fn inner_mut(&mut self) -> &mut winrt_toast::Toast {
114        &mut self.inner
115    }
116}
117
118/// Abstracted notifier for the `Notification`.
119pub(crate) struct Notifier {
120    #[cfg(not(feature = "winrt-toast"))]
121    inner: crate::win::NotifierImpl,
122    #[cfg(feature = "winrt-toast")]
123    inner: winrt_toast::ToastManager,
124}
125
126impl Notifier {
127    pub fn new_with_application_id(application_id: &str) -> Result<Self> {
128        Ok(Self {
129            #[cfg(not(feature = "winrt-toast"))]
130            inner: crate::win::NotifierImpl::new_with_application_id(application_id)?,
131            #[cfg(feature = "winrt-toast")]
132            inner: winrt_toast::ToastManager::new(application_id),
133        })
134    }
135
136    pub fn show(&self, notification: &Notification) -> Result<()> {
137        self.inner.show(&notification.inner)?;
138        Ok(())
139    }
140}