mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-06-12 14:17:48 +02:00
feat(notification): add plugin (#326)
This commit is contained in:
committed by
GitHub
parent
864b9d790f
commit
e9bbe94181
@@ -0,0 +1,267 @@
|
||||
// Copyright 2019-2023 Tauri Programme within The Commons Conservancy
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
use serde::de::DeserializeOwned;
|
||||
use tauri::{plugin::PluginApi, AppHandle, Runtime};
|
||||
|
||||
use crate::{models::*, NotificationBuilder};
|
||||
|
||||
pub fn init<R: Runtime, C: DeserializeOwned>(
|
||||
app: &AppHandle<R>,
|
||||
_api: PluginApi<R, C>,
|
||||
) -> crate::Result<Notification<R>> {
|
||||
Ok(Notification(app.clone()))
|
||||
}
|
||||
|
||||
/// Access to the {{ plugin_name }} APIs.
|
||||
pub struct Notification<R: Runtime>(AppHandle<R>);
|
||||
|
||||
impl<R: Runtime> crate::NotificationBuilder<R> {
|
||||
pub fn show(self) -> crate::Result<()> {
|
||||
let mut notification =
|
||||
imp::Notification::new(self.app.config().tauri.bundle.identifier.clone());
|
||||
|
||||
if let Some(title) = self
|
||||
.data
|
||||
.title
|
||||
.or_else(|| self.app.config().package.product_name.clone())
|
||||
{
|
||||
notification = notification.title(title);
|
||||
}
|
||||
if let Some(body) = self.data.body {
|
||||
notification = notification.body(body);
|
||||
}
|
||||
if let Some(icon) = self.data.icon {
|
||||
notification = notification.icon(icon);
|
||||
}
|
||||
#[cfg(feature = "windows7-compat")]
|
||||
{
|
||||
notification.notify(&self.app)?;
|
||||
}
|
||||
#[cfg(not(feature = "windows7-compat"))]
|
||||
notification.show()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<R: Runtime> Notification<R> {
|
||||
pub fn builder(&self) -> NotificationBuilder<R> {
|
||||
NotificationBuilder::new(self.0.clone())
|
||||
}
|
||||
|
||||
pub fn request_permission(&self) -> crate::Result<PermissionState> {
|
||||
Ok(PermissionState::Granted)
|
||||
}
|
||||
|
||||
pub fn permission_state(&self) -> crate::Result<PermissionState> {
|
||||
Ok(PermissionState::Granted)
|
||||
}
|
||||
}
|
||||
|
||||
mod imp {
|
||||
//! Types and functions related to desktop notifications.
|
||||
|
||||
#[cfg(windows)]
|
||||
use std::path::MAIN_SEPARATOR as SEP;
|
||||
|
||||
/// The desktop notification definition.
|
||||
///
|
||||
/// Allows you to construct a Notification data and send it.
|
||||
///
|
||||
/// # Examples
|
||||
/// ```rust,no_run
|
||||
/// use tauri::api::notification::Notification;
|
||||
/// // first we build the application to access the Tauri configuration
|
||||
/// let app = tauri::Builder::default()
|
||||
/// // on an actual app, remove the string argument
|
||||
/// .build(tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json"))
|
||||
/// .expect("error while building tauri application");
|
||||
///
|
||||
/// // shows a notification with the given title and body
|
||||
/// Notification::new(&app.config().tauri.bundle.identifier)
|
||||
/// .title("New message")
|
||||
/// .body("You've got a new message.")
|
||||
/// .show();
|
||||
///
|
||||
/// // run the app
|
||||
/// app.run(|_app_handle, _event| {});
|
||||
/// ```
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Notification {
|
||||
/// The notification body.
|
||||
body: Option<String>,
|
||||
/// The notification title.
|
||||
title: Option<String>,
|
||||
/// The notification icon.
|
||||
icon: Option<String>,
|
||||
/// The notification identifier
|
||||
identifier: String,
|
||||
}
|
||||
|
||||
impl Notification {
|
||||
/// Initializes a instance of a Notification.
|
||||
pub fn new(identifier: impl Into<String>) -> Self {
|
||||
Self {
|
||||
identifier: identifier.into(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the notification body.
|
||||
#[must_use]
|
||||
pub fn body(mut self, body: impl Into<String>) -> Self {
|
||||
self.body = Some(body.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the notification title.
|
||||
#[must_use]
|
||||
pub fn title(mut self, title: impl Into<String>) -> Self {
|
||||
self.title = Some(title.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets the notification icon.
|
||||
#[must_use]
|
||||
pub fn icon(mut self, icon: impl Into<String>) -> Self {
|
||||
self.icon = Some(icon.into());
|
||||
self
|
||||
}
|
||||
|
||||
/// Shows the notification.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tauri::api::notification::Notification;
|
||||
///
|
||||
/// // on an actual app, remove the string argument
|
||||
/// let context = tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json");
|
||||
/// Notification::new(&context.config().tauri.bundle.identifier)
|
||||
/// .title("Tauri")
|
||||
/// .body("Tauri is awesome!")
|
||||
/// .show()
|
||||
/// .unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - **Windows**: Not supported on Windows 7. If your app targets it, enable the `windows7-compat` feature and use [`Self::notify`].
|
||||
#[cfg_attr(
|
||||
all(not(doc_cfg), feature = "windows7-compat"),
|
||||
deprecated = "This function does not work on Windows 7. Use `Self::notify` instead."
|
||||
)]
|
||||
pub fn show(self) -> crate::Result<()> {
|
||||
let mut notification = notify_rust::Notification::new();
|
||||
if let Some(body) = self.body {
|
||||
notification.body(&body);
|
||||
}
|
||||
if let Some(title) = self.title {
|
||||
notification.summary(&title);
|
||||
}
|
||||
if let Some(icon) = self.icon {
|
||||
notification.icon(&icon);
|
||||
} else {
|
||||
notification.auto_icon();
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
let exe = tauri::utils::platform::current_exe()?;
|
||||
let exe_dir = exe.parent().expect("failed to get exe directory");
|
||||
let curr_dir = exe_dir.display().to_string();
|
||||
// set the notification's System.AppUserModel.ID only when running the installed app
|
||||
if !(curr_dir.ends_with(format!("{SEP}target{SEP}debug").as_str())
|
||||
|| curr_dir.ends_with(format!("{SEP}target{SEP}release").as_str()))
|
||||
{
|
||||
notification.app_id(&self.identifier);
|
||||
}
|
||||
}
|
||||
#[cfg(target_os = "macos")]
|
||||
{
|
||||
let _ = notify_rust::set_application(if cfg!(feature = "custom-protocol") {
|
||||
&self.identifier
|
||||
} else {
|
||||
"com.apple.Terminal"
|
||||
});
|
||||
}
|
||||
|
||||
tauri::async_runtime::spawn(async move {
|
||||
let _ = notification.show();
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Shows the notification. This API is similar to [`Self::show`], but it also works on Windows 7.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tauri::api::notification::Notification;
|
||||
///
|
||||
/// // on an actual app, remove the string argument
|
||||
/// let context = tauri::generate_context!("test/fixture/src-tauri/tauri.conf.json");
|
||||
/// let identifier = context.config().tauri.bundle.identifier.clone();
|
||||
///
|
||||
/// tauri::Builder::default()
|
||||
/// .setup(move |app| {
|
||||
/// Notification::new(&identifier)
|
||||
/// .title("Tauri")
|
||||
/// .body("Tauri is awesome!")
|
||||
/// .notify(&app.handle())
|
||||
/// .unwrap();
|
||||
/// Ok(())
|
||||
/// })
|
||||
/// .run(context)
|
||||
/// .expect("error while running tauri application");
|
||||
/// ```
|
||||
#[cfg(feature = "windows7-compat")]
|
||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "windows7-compat")))]
|
||||
#[allow(unused_variables)]
|
||||
pub fn notify<R: tauri::Runtime>(self, app: &tauri::AppHandle<R>) -> crate::Result<()> {
|
||||
#[cfg(windows)]
|
||||
{
|
||||
if tauri::utils::platform::is_windows_7() {
|
||||
self.notify_win7(app)
|
||||
} else {
|
||||
#[allow(deprecated)]
|
||||
self.show()
|
||||
}
|
||||
}
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
#[allow(deprecated)]
|
||||
self.show()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(windows, feature = "windows7-compat"))]
|
||||
fn notify_win7<R: tauri::Runtime>(self, app: &tauri::AppHandle<R>) -> crate::Result<()> {
|
||||
let app = app.clone();
|
||||
let default_window_icon = app.manager.inner.default_window_icon.clone();
|
||||
let _ = app.run_on_main_thread(move || {
|
||||
let mut notification = win7_notifications::Notification::new();
|
||||
if let Some(body) = self.body {
|
||||
notification.body(&body);
|
||||
}
|
||||
if let Some(title) = self.title {
|
||||
notification.summary(&title);
|
||||
}
|
||||
if let Some(tauri::Icon::Rgba {
|
||||
rgba,
|
||||
width,
|
||||
height,
|
||||
}) = default_window_icon
|
||||
{
|
||||
notification.icon(rgba, width, height);
|
||||
}
|
||||
let _ = notification.show();
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user