plugin.rs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. // Copyright 2019-2023 Tauri Programme within The Commons Conservancy
  2. // SPDX-License-Identifier: Apache-2.0
  3. // SPDX-License-Identifier: MIT
  4. use std::path::PathBuf;
  5. use serde::Deserialize;
  6. use crate::{
  7. command,
  8. ipc::Channel,
  9. menu::{plugin::ItemKind, Menu, Submenu},
  10. plugin::{Builder, TauriPlugin},
  11. resources::ResourceId,
  12. tray::TrayIconBuilder,
  13. AppHandle, IconDto, Manager, Runtime,
  14. };
  15. use super::TrayIcon;
  16. #[derive(Deserialize)]
  17. #[serde(rename_all = "camelCase")]
  18. struct TrayIconOptions {
  19. id: Option<String>,
  20. menu: Option<(ResourceId, ItemKind)>,
  21. icon: Option<IconDto>,
  22. tooltip: Option<String>,
  23. title: Option<String>,
  24. temp_dir_path: Option<PathBuf>,
  25. icon_as_template: Option<bool>,
  26. menu_on_left_click: Option<bool>,
  27. }
  28. #[command(root = "crate")]
  29. fn new<R: Runtime>(
  30. app: AppHandle<R>,
  31. options: TrayIconOptions,
  32. handler: Channel,
  33. ) -> crate::Result<(ResourceId, String)> {
  34. let mut builder = if let Some(id) = options.id {
  35. TrayIconBuilder::<R>::with_id(id)
  36. } else {
  37. TrayIconBuilder::<R>::new()
  38. };
  39. builder = builder.on_tray_icon_event(move |_tray, e| {
  40. let _ = handler.send(e);
  41. });
  42. let mut resources_table = app.resources_table();
  43. if let Some((rid, kind)) = options.menu {
  44. match kind {
  45. ItemKind::Menu => {
  46. let menu = resources_table.get::<Menu<R>>(rid)?;
  47. builder = builder.menu(&*menu);
  48. }
  49. ItemKind::Submenu => {
  50. let submenu = resources_table.get::<Submenu<R>>(rid)?;
  51. builder = builder.menu(&*submenu);
  52. }
  53. _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()),
  54. };
  55. }
  56. if let Some(icon) = options.icon {
  57. builder = builder.icon(icon.into());
  58. }
  59. if let Some(tooltip) = options.tooltip {
  60. builder = builder.tooltip(tooltip);
  61. }
  62. if let Some(title) = options.title {
  63. builder = builder.title(title);
  64. }
  65. if let Some(temp_dir_path) = options.temp_dir_path {
  66. builder = builder.temp_dir_path(temp_dir_path);
  67. }
  68. if let Some(icon_as_template) = options.icon_as_template {
  69. builder = builder.icon_as_template(icon_as_template);
  70. }
  71. if let Some(menu_on_left_click) = options.menu_on_left_click {
  72. builder = builder.menu_on_left_click(menu_on_left_click);
  73. }
  74. let tray = builder.build(&app)?;
  75. let id = tray.id().as_ref().to_string();
  76. let rid = resources_table.add(tray);
  77. Ok((rid, id))
  78. }
  79. #[command(root = "crate")]
  80. fn set_icon<R: Runtime>(
  81. app: AppHandle<R>,
  82. rid: ResourceId,
  83. icon: Option<IconDto>,
  84. ) -> crate::Result<()> {
  85. let resources_table = app.resources_table();
  86. let tray = resources_table.get::<TrayIcon<R>>(rid)?;
  87. tray.set_icon(icon.map(Into::into))
  88. }
  89. #[command(root = "crate")]
  90. fn set_menu<R: Runtime>(
  91. app: AppHandle<R>,
  92. rid: ResourceId,
  93. menu: Option<(ResourceId, ItemKind)>,
  94. ) -> crate::Result<()> {
  95. let resources_table = app.resources_table();
  96. let tray = resources_table.get::<TrayIcon<R>>(rid)?;
  97. if let Some((rid, kind)) = menu {
  98. match kind {
  99. ItemKind::Menu => {
  100. let menu = resources_table.get::<Menu<R>>(rid)?;
  101. tray.set_menu(Some((*menu).clone()))?;
  102. }
  103. ItemKind::Submenu => {
  104. let submenu = resources_table.get::<Submenu<R>>(rid)?;
  105. tray.set_menu(Some((*submenu).clone()))?;
  106. }
  107. _ => return Err(anyhow::anyhow!("unexpected menu item kind").into()),
  108. };
  109. } else {
  110. tray.set_menu(None::<Menu<R>>)?;
  111. }
  112. Ok(())
  113. }
  114. #[command(root = "crate")]
  115. fn set_tooltip<R: Runtime>(
  116. app: AppHandle<R>,
  117. rid: ResourceId,
  118. tooltip: Option<String>,
  119. ) -> crate::Result<()> {
  120. let resources_table = app.resources_table();
  121. let tray = resources_table.get::<TrayIcon<R>>(rid)?;
  122. tray.set_tooltip(tooltip)
  123. }
  124. #[command(root = "crate")]
  125. fn set_title<R: Runtime>(
  126. app: AppHandle<R>,
  127. rid: ResourceId,
  128. title: Option<String>,
  129. ) -> crate::Result<()> {
  130. let resources_table = app.resources_table();
  131. let tray = resources_table.get::<TrayIcon<R>>(rid)?;
  132. tray.set_title(title)
  133. }
  134. #[command(root = "crate")]
  135. fn set_visible<R: Runtime>(app: AppHandle<R>, rid: ResourceId, visible: bool) -> crate::Result<()> {
  136. let resources_table = app.resources_table();
  137. let tray = resources_table.get::<TrayIcon<R>>(rid)?;
  138. tray.set_visible(visible)
  139. }
  140. #[command(root = "crate")]
  141. fn set_temp_dir_path<R: Runtime>(
  142. app: AppHandle<R>,
  143. rid: ResourceId,
  144. path: Option<PathBuf>,
  145. ) -> crate::Result<()> {
  146. let resources_table = app.resources_table();
  147. let tray = resources_table.get::<TrayIcon<R>>(rid)?;
  148. tray.set_temp_dir_path(path)
  149. }
  150. #[command(root = "crate")]
  151. fn set_icon_as_template<R: Runtime>(
  152. app: AppHandle<R>,
  153. rid: ResourceId,
  154. as_template: bool,
  155. ) -> crate::Result<()> {
  156. let resources_table = app.resources_table();
  157. let tray = resources_table.get::<TrayIcon<R>>(rid)?;
  158. tray.set_icon_as_template(as_template)
  159. }
  160. #[command(root = "crate")]
  161. fn set_show_menu_on_left_click<R: Runtime>(
  162. app: AppHandle<R>,
  163. rid: ResourceId,
  164. on_left: bool,
  165. ) -> crate::Result<()> {
  166. let resources_table = app.resources_table();
  167. let tray = resources_table.get::<TrayIcon<R>>(rid)?;
  168. tray.set_show_menu_on_left_click(on_left)
  169. }
  170. pub(crate) fn init<R: Runtime>() -> TauriPlugin<R> {
  171. Builder::new("tray")
  172. .invoke_handler(crate::generate_handler![
  173. new,
  174. set_icon,
  175. set_menu,
  176. set_tooltip,
  177. set_title,
  178. set_visible,
  179. set_temp_dir_path,
  180. set_icon_as_template,
  181. set_show_menu_on_left_click,
  182. ])
  183. .build()
  184. }