notification.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. // Copyright 2019-2021 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use super::InvokeResponse;
  5. use serde::Deserialize;
  6. #[cfg(notification_all)]
  7. use crate::api::notification::Notification;
  8. use crate::{Config, PackageInfo, Runtime, Window};
  9. use std::sync::Arc;
  10. // `Granted` response from `request_permission`. Matches the Web API return value.
  11. #[cfg(notification_all)]
  12. const PERMISSION_GRANTED: &str = "granted";
  13. // `Denied` response from `request_permission`. Matches the Web API return value.
  14. const PERMISSION_DENIED: &str = "denied";
  15. /// The options for the notification API.
  16. #[derive(Deserialize)]
  17. pub struct NotificationOptions {
  18. /// The notification title.
  19. pub title: String,
  20. /// The notification body.
  21. pub body: Option<String>,
  22. /// The notification icon.
  23. pub icon: Option<String>,
  24. }
  25. /// The API descriptor.
  26. #[derive(Deserialize)]
  27. #[serde(tag = "cmd", rename_all = "camelCase")]
  28. pub enum Cmd {
  29. /// The show notification API.
  30. Notification { options: NotificationOptions },
  31. /// The request notification permission API.
  32. RequestNotificationPermission,
  33. /// The notification permission check API.
  34. IsNotificationPermissionGranted,
  35. }
  36. impl Cmd {
  37. #[allow(unused_variables)]
  38. pub fn run<R: Runtime>(
  39. self,
  40. window: Window<R>,
  41. config: Arc<Config>,
  42. package_info: &PackageInfo,
  43. ) -> crate::Result<InvokeResponse> {
  44. match self {
  45. #[cfg(notification_all)]
  46. Self::Notification { options } => send(options, &config).map(Into::into),
  47. #[cfg(not(notification_all))]
  48. Self::Notification { .. } => Err(crate::Error::ApiNotAllowlisted("notification".to_string())),
  49. Self::IsNotificationPermissionGranted => {
  50. #[cfg(notification_all)]
  51. return is_permission_granted(&config, package_info).map(Into::into);
  52. #[cfg(not(notification_all))]
  53. Ok(false.into())
  54. }
  55. Self::RequestNotificationPermission => {
  56. #[cfg(notification_all)]
  57. return request_permission(&window, &config, package_info).map(Into::into);
  58. #[cfg(not(notification_all))]
  59. Ok(PERMISSION_DENIED.into())
  60. }
  61. }
  62. }
  63. }
  64. #[cfg(notification_all)]
  65. pub fn send(options: NotificationOptions, config: &Config) -> crate::Result<InvokeResponse> {
  66. let mut notification =
  67. Notification::new(config.tauri.bundle.identifier.clone()).title(options.title);
  68. if let Some(body) = options.body {
  69. notification = notification.body(body);
  70. }
  71. if let Some(icon) = options.icon {
  72. notification = notification.icon(icon);
  73. }
  74. notification.show()?;
  75. Ok(().into())
  76. }
  77. #[cfg(notification_all)]
  78. pub fn is_permission_granted(
  79. config: &Config,
  80. package_info: &PackageInfo,
  81. ) -> crate::Result<InvokeResponse> {
  82. let settings = crate::settings::read_settings(config, package_info);
  83. if let Some(allow_notification) = settings.allow_notification {
  84. Ok(allow_notification.into())
  85. } else {
  86. Ok(().into())
  87. }
  88. }
  89. #[cfg(notification_all)]
  90. pub fn request_permission<R: Runtime>(
  91. window: &Window<R>,
  92. config: &Config,
  93. package_info: &PackageInfo,
  94. ) -> crate::Result<String> {
  95. let mut settings = crate::settings::read_settings(config, package_info);
  96. if let Some(allow_notification) = settings.allow_notification {
  97. return Ok(if allow_notification {
  98. PERMISSION_GRANTED.to_string()
  99. } else {
  100. PERMISSION_DENIED.to_string()
  101. });
  102. }
  103. let (tx, rx) = std::sync::mpsc::channel();
  104. crate::api::dialog::ask(
  105. Some(window),
  106. "Permissions",
  107. "This app wants to show notifications. Do you allow?",
  108. move |answer| {
  109. tx.send(answer).unwrap();
  110. },
  111. );
  112. let answer = rx.recv().unwrap();
  113. settings.allow_notification = Some(answer);
  114. crate::settings::write_settings(config, package_info, settings)?;
  115. if answer {
  116. Ok(PERMISSION_GRANTED.to_string())
  117. } else {
  118. Ok(PERMISSION_DENIED.to_string())
  119. }
  120. }