소스 검색

refactor(menu,tray): add wrappers (#7622)

Amr Bashir 2 년 전
부모
커밋
af3268a4be

+ 4 - 4
core/tauri/src/app.rs

@@ -1461,16 +1461,16 @@ impl<R: Runtime> Builder<R> {
     {
       // setup menu event handler
       let proxy = runtime.create_proxy();
-      crate::menu::MenuEvent::set_event_handler(Some(move |e| {
-        let _ = proxy.send_event(EventLoopMessage::MenuEvent(e));
+      muda::MenuEvent::set_event_handler(Some(move |e: muda::MenuEvent| {
+        let _ = proxy.send_event(EventLoopMessage::MenuEvent(e.into()));
       }));
 
       // setup tray event handler
       #[cfg(feature = "tray-icon")]
       {
         let proxy = runtime.create_proxy();
-        crate::tray::TrayIconEvent::set_event_handler(Some(move |e| {
-          let _ = proxy.send_event(EventLoopMessage::TrayIconEvent(e));
+        tray_icon::TrayIconEvent::set_event_handler(Some(move |e: tray_icon::TrayIconEvent| {
+          let _ = proxy.send_event(EventLoopMessage::TrayIconEvent(e.into()));
         }));
       }
     }

+ 4 - 3
core/tauri/src/menu/builders/icon.rs

@@ -2,9 +2,10 @@
 // SPDX-License-Identifier: Apache-2.0
 // SPDX-License-Identifier: MIT
 
-use muda::{MenuId, NativeIcon};
-
-use crate::{menu::IconMenuItem, Icon, Manager, Runtime};
+use crate::{
+  menu::{IconMenuItem, MenuId, NativeIcon},
+  Icon, Manager, Runtime,
+};
 
 /// A builder type for [`IconMenuItem`]
 pub struct IconMenuItemBuilder {

+ 5 - 3
core/tauri/src/menu/icon.rs

@@ -115,7 +115,7 @@ impl<R: Runtime> IconMenuItem<R> {
     let item = muda::IconMenuItem::with_native_icon(
       text,
       enabled,
-      native_icon,
+      native_icon.map(Into::into),
       acccelerator.and_then(|s| s.as_ref().parse().ok()),
     );
     Self {
@@ -144,7 +144,7 @@ impl<R: Runtime> IconMenuItem<R> {
       id,
       text,
       enabled,
-      native_icon,
+      native_icon.map(Into::into),
       acccelerator.and_then(|s| s.as_ref().parse().ok()),
     );
     Self {
@@ -207,7 +207,9 @@ impl<R: Runtime> IconMenuItem<R> {
   /// - **Windows / Linux**: Unsupported.
   pub fn set_native_icon(&mut self, _icon: Option<NativeIcon>) -> crate::Result<()> {
     #[cfg(target_os = "macos")]
-    return run_main_thread!(self, |mut self_: Self| self_.inner.set_native_icon(_icon));
+    return run_main_thread!(self, |mut self_: Self| self_
+      .inner
+      .set_native_icon(_icon.map(Into::into)));
     #[allow(unreachable_code)]
     Ok(())
   }

+ 2 - 2
core/tauri/src/menu/menu.rs

@@ -3,11 +3,11 @@
 // SPDX-License-Identifier: MIT
 
 use super::sealed::ContextMenuBase;
-use super::{IsMenuItem, MenuItemKind, PredefinedMenuItem, Submenu};
+use super::{AboutMetadata, IsMenuItem, MenuItemKind, PredefinedMenuItem, Submenu};
 use crate::Window;
 use crate::{run_main_thread, AppHandle, Manager, Position, Runtime};
 use muda::ContextMenu;
-use muda::{AboutMetadata, MenuId};
+use muda::MenuId;
 
 /// Expected submenu id of the Window menu for macOS.
 pub const WINDOW_SUBMENU_ID: &str = "__tauri_window_menu__";

+ 387 - 2
core/tauri/src/menu/mod.rs

@@ -24,8 +24,393 @@ pub use normal::MenuItem;
 pub use predefined::PredefinedMenuItem;
 pub use submenu::Submenu;
 
-use crate::Runtime;
-pub use muda::{AboutMetadata, MenuEvent, MenuId, NativeIcon};
+use crate::{Icon, Runtime};
+pub use muda::MenuId;
+
+/// Describes a menu event emitted when a menu item is activated
+#[derive(Debug, Clone)]
+pub struct MenuEvent {
+  /// Id of the menu item which triggered this event
+  pub id: MenuId,
+}
+
+impl MenuEvent {
+  /// Returns the id of the menu item which triggered this event
+  pub fn id(&self) -> &MenuId {
+    &self.id
+  }
+}
+
+impl From<muda::MenuEvent> for MenuEvent {
+  fn from(value: muda::MenuEvent) -> Self {
+    Self { id: value.id }
+  }
+}
+
+/// Application metadata for the [`PredefinedMenuItem::about`](crate::PredefinedMenuItem::about).
+#[derive(Debug, Clone, Default)]
+pub struct AboutMetadata {
+  /// Sets the application name.
+  pub name: Option<String>,
+  /// The application version.
+  pub version: Option<String>,
+  /// The short version, e.g. "1.0".
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Windows / Linux:** Appended to the end of `version` in parentheses.
+  pub short_version: Option<String>,
+  /// The authors of the application.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Unsupported.
+  pub authors: Option<Vec<String>>,
+  /// Application comments.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Unsupported.
+  pub comments: Option<String>,
+  /// The copyright of the application.
+  pub copyright: Option<String>,
+  /// The license of the application.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Unsupported.
+  pub license: Option<String>,
+  /// The application website.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Unsupported.
+  pub website: Option<String>,
+  /// The website label.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Unsupported.
+  pub website_label: Option<String>,
+  /// The credits.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Windows / Linux:** Unsupported.
+  pub credits: Option<String>,
+  /// The application icon.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Windows:** Unsupported.
+  pub icon: Option<Icon>,
+}
+
+/// A builder type for [`AboutMetadata`].
+#[derive(Clone, Debug, Default)]
+pub struct AboutMetadataBuilder(AboutMetadata);
+
+impl AboutMetadataBuilder {
+  /// Create a new about metdata builder.
+  pub fn new() -> Self {
+    Default::default()
+  }
+
+  /// Sets the application name.
+  pub fn name<S: Into<String>>(mut self, name: Option<S>) -> Self {
+    self.0.name = name.map(|s| s.into());
+    self
+  }
+  /// Sets the application version.
+  pub fn version<S: Into<String>>(mut self, version: Option<S>) -> Self {
+    self.0.version = version.map(|s| s.into());
+    self
+  }
+  /// Sets the short version, e.g. "1.0".
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Windows / Linux:** Appended to the end of `version` in parentheses.
+  pub fn short_version<S: Into<String>>(mut self, short_version: Option<S>) -> Self {
+    self.0.short_version = short_version.map(|s| s.into());
+    self
+  }
+  /// Sets the authors of the application.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Unsupported.
+  pub fn authors(mut self, authors: Option<Vec<String>>) -> Self {
+    self.0.authors = authors;
+    self
+  }
+  /// Application comments.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Unsupported.
+  pub fn comments<S: Into<String>>(mut self, comments: Option<S>) -> Self {
+    self.0.comments = comments.map(|s| s.into());
+    self
+  }
+  /// Sets the copyright of the application.
+  pub fn copyright<S: Into<String>>(mut self, copyright: Option<S>) -> Self {
+    self.0.copyright = copyright.map(|s| s.into());
+    self
+  }
+  /// Sets the license of the application.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Unsupported.
+  pub fn license<S: Into<String>>(mut self, license: Option<S>) -> Self {
+    self.0.license = license.map(|s| s.into());
+    self
+  }
+  /// Sets the application website.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Unsupported.
+  pub fn website<S: Into<String>>(mut self, website: Option<S>) -> Self {
+    self.0.website = website.map(|s| s.into());
+    self
+  }
+  /// Sets the website label.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **macOS:** Unsupported.
+  pub fn website_label<S: Into<String>>(mut self, website_label: Option<S>) -> Self {
+    self.0.website_label = website_label.map(|s| s.into());
+    self
+  }
+  /// Sets the credits.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Windows / Linux:** Unsupported.
+  pub fn credits<S: Into<String>>(mut self, credits: Option<S>) -> Self {
+    self.0.credits = credits.map(|s| s.into());
+    self
+  }
+  /// Sets the application icon.
+  ///
+  /// ## Platform-specific
+  ///
+  /// - **Windows:** Unsupported.
+  pub fn icon(mut self, icon: Option<Icon>) -> Self {
+    self.0.icon = icon;
+    self
+  }
+
+  /// Construct the final [`AboutMetadata`]
+  pub fn build(self) -> AboutMetadata {
+    self.0
+  }
+}
+
+impl From<AboutMetadata> for muda::AboutMetadata {
+  fn from(value: AboutMetadata) -> Self {
+    Self {
+      authors: value.authors,
+      name: value.name,
+      version: value.version,
+      short_version: value.short_version,
+      comments: value.comments,
+      copyright: value.copyright,
+      license: value.license,
+      website: value.website,
+      website_label: value.website_label,
+      credits: value.credits,
+      icon: value.icon.and_then(|i| i.try_into().ok()),
+    }
+  }
+}
+
+/// A native Icon to be used for the menu item
+///
+/// ## Platform-specific:
+///
+/// - **Windows / Linux**: Unsupported.
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum NativeIcon {
+  /// An add item template image.
+  Add,
+  /// Advanced preferences toolbar icon for the preferences window.
+  Advanced,
+  /// A Bluetooth template image.
+  Bluetooth,
+  /// Bookmarks image suitable for a template.
+  Bookmarks,
+  /// A caution image.
+  Caution,
+  /// A color panel toolbar icon.
+  ColorPanel,
+  /// A column view mode template image.
+  ColumnView,
+  /// A computer icon.
+  Computer,
+  /// An enter full-screen mode template image.
+  EnterFullScreen,
+  /// Permissions for all users.
+  Everyone,
+  /// An exit full-screen mode template image.
+  ExitFullScreen,
+  /// A cover flow view mode template image.
+  FlowView,
+  /// A folder image.
+  Folder,
+  /// A burnable folder icon.
+  FolderBurnable,
+  /// A smart folder icon.
+  FolderSmart,
+  /// A link template image.
+  FollowLinkFreestanding,
+  /// A font panel toolbar icon.
+  FontPanel,
+  /// A `go back` template image.
+  GoLeft,
+  /// A `go forward` template image.
+  GoRight,
+  /// Home image suitable for a template.
+  Home,
+  /// An iChat Theater template image.
+  IChatTheater,
+  /// An icon view mode template image.
+  IconView,
+  /// An information toolbar icon.
+  Info,
+  /// A template image used to denote invalid data.
+  InvalidDataFreestanding,
+  /// A generic left-facing triangle template image.
+  LeftFacingTriangle,
+  /// A list view mode template image.
+  ListView,
+  /// A locked padlock template image.
+  LockLocked,
+  /// An unlocked padlock template image.
+  LockUnlocked,
+  /// A horizontal dash, for use in menus.
+  MenuMixedState,
+  /// A check mark template image, for use in menus.
+  MenuOnState,
+  /// A MobileMe icon.
+  MobileMe,
+  /// A drag image for multiple items.
+  MultipleDocuments,
+  /// A network icon.
+  Network,
+  /// A path button template image.
+  Path,
+  /// General preferences toolbar icon for the preferences window.
+  PreferencesGeneral,
+  /// A Quick Look template image.
+  QuickLook,
+  /// A refresh template image.
+  RefreshFreestanding,
+  /// A refresh template image.
+  Refresh,
+  /// A remove item template image.
+  Remove,
+  /// A reveal contents template image.
+  RevealFreestanding,
+  /// A generic right-facing triangle template image.
+  RightFacingTriangle,
+  /// A share view template image.
+  Share,
+  /// A slideshow template image.
+  Slideshow,
+  /// A badge for a `smart` item.
+  SmartBadge,
+  /// Small green indicator, similar to iChat’s available image.
+  StatusAvailable,
+  /// Small clear indicator.
+  StatusNone,
+  /// Small yellow indicator, similar to iChat’s idle image.
+  StatusPartiallyAvailable,
+  /// Small red indicator, similar to iChat’s unavailable image.
+  StatusUnavailable,
+  /// A stop progress template image.
+  StopProgressFreestanding,
+  /// A stop progress button template image.
+  StopProgress,
+  /// An image of the empty trash can.
+  TrashEmpty,
+  /// An image of the full trash can.
+  TrashFull,
+  /// Permissions for a single user.
+  User,
+  /// User account toolbar icon for the preferences window.
+  UserAccounts,
+  /// Permissions for a group of users.
+  UserGroup,
+  /// Permissions for guests.
+  UserGuest,
+}
+
+impl From<NativeIcon> for muda::NativeIcon {
+  fn from(value: NativeIcon) -> Self {
+    match value {
+      NativeIcon::Add => muda::NativeIcon::Add,
+      NativeIcon::Advanced => muda::NativeIcon::Advanced,
+      NativeIcon::Bluetooth => muda::NativeIcon::Bluetooth,
+      NativeIcon::Bookmarks => muda::NativeIcon::Bookmarks,
+      NativeIcon::Caution => muda::NativeIcon::Caution,
+      NativeIcon::ColorPanel => muda::NativeIcon::ColorPanel,
+      NativeIcon::ColumnView => muda::NativeIcon::ColumnView,
+      NativeIcon::Computer => muda::NativeIcon::Computer,
+      NativeIcon::EnterFullScreen => muda::NativeIcon::EnterFullScreen,
+      NativeIcon::Everyone => muda::NativeIcon::Everyone,
+      NativeIcon::ExitFullScreen => muda::NativeIcon::ExitFullScreen,
+      NativeIcon::FlowView => muda::NativeIcon::FlowView,
+      NativeIcon::Folder => muda::NativeIcon::Folder,
+      NativeIcon::FolderBurnable => muda::NativeIcon::FolderBurnable,
+      NativeIcon::FolderSmart => muda::NativeIcon::FolderSmart,
+      NativeIcon::FollowLinkFreestanding => muda::NativeIcon::FollowLinkFreestanding,
+      NativeIcon::FontPanel => muda::NativeIcon::FontPanel,
+      NativeIcon::GoLeft => muda::NativeIcon::GoLeft,
+      NativeIcon::GoRight => muda::NativeIcon::GoRight,
+      NativeIcon::Home => muda::NativeIcon::Home,
+      NativeIcon::IChatTheater => muda::NativeIcon::IChatTheater,
+      NativeIcon::IconView => muda::NativeIcon::IconView,
+      NativeIcon::Info => muda::NativeIcon::Info,
+      NativeIcon::InvalidDataFreestanding => muda::NativeIcon::InvalidDataFreestanding,
+      NativeIcon::LeftFacingTriangle => muda::NativeIcon::LeftFacingTriangle,
+      NativeIcon::ListView => muda::NativeIcon::ListView,
+      NativeIcon::LockLocked => muda::NativeIcon::LockLocked,
+      NativeIcon::LockUnlocked => muda::NativeIcon::LockUnlocked,
+      NativeIcon::MenuMixedState => muda::NativeIcon::MenuMixedState,
+      NativeIcon::MenuOnState => muda::NativeIcon::MenuOnState,
+      NativeIcon::MobileMe => muda::NativeIcon::MobileMe,
+      NativeIcon::MultipleDocuments => muda::NativeIcon::MultipleDocuments,
+      NativeIcon::Network => muda::NativeIcon::Network,
+      NativeIcon::Path => muda::NativeIcon::Path,
+      NativeIcon::PreferencesGeneral => muda::NativeIcon::PreferencesGeneral,
+      NativeIcon::QuickLook => muda::NativeIcon::QuickLook,
+      NativeIcon::RefreshFreestanding => muda::NativeIcon::RefreshFreestanding,
+      NativeIcon::Refresh => muda::NativeIcon::Refresh,
+      NativeIcon::Remove => muda::NativeIcon::Remove,
+      NativeIcon::RevealFreestanding => muda::NativeIcon::RevealFreestanding,
+      NativeIcon::RightFacingTriangle => muda::NativeIcon::RightFacingTriangle,
+      NativeIcon::Share => muda::NativeIcon::Share,
+      NativeIcon::Slideshow => muda::NativeIcon::Slideshow,
+      NativeIcon::SmartBadge => muda::NativeIcon::SmartBadge,
+      NativeIcon::StatusAvailable => muda::NativeIcon::StatusAvailable,
+      NativeIcon::StatusNone => muda::NativeIcon::StatusNone,
+      NativeIcon::StatusPartiallyAvailable => muda::NativeIcon::StatusPartiallyAvailable,
+      NativeIcon::StatusUnavailable => muda::NativeIcon::StatusUnavailable,
+      NativeIcon::StopProgressFreestanding => muda::NativeIcon::StopProgressFreestanding,
+      NativeIcon::StopProgress => muda::NativeIcon::StopProgress,
+      NativeIcon::TrashEmpty => muda::NativeIcon::TrashEmpty,
+      NativeIcon::TrashFull => muda::NativeIcon::TrashFull,
+      NativeIcon::User => muda::NativeIcon::User,
+      NativeIcon::UserAccounts => muda::NativeIcon::UserAccounts,
+      NativeIcon::UserGroup => muda::NativeIcon::UserGroup,
+      NativeIcon::UserGuest => muda::NativeIcon::UserGuest,
+    }
+  }
+}
 
 /// An enumeration of all menu item kinds that could be added to
 /// a [`Menu`] or [`Submenu`]

+ 1 - 1
core/tauri/src/menu/predefined.rs

@@ -240,7 +240,7 @@ impl<R: Runtime> PredefinedMenuItem<R> {
     text: Option<&str>,
     metadata: Option<AboutMetadata>,
   ) -> Self {
-    let inner = muda::PredefinedMenuItem::about(text, metadata);
+    let inner = muda::PredefinedMenuItem::about(text, metadata.map(Into::into));
     Self {
       id: inner.id().clone(),
       inner,

+ 91 - 1
core/tauri/src/tray.rs

@@ -11,10 +11,100 @@ use crate::menu::ContextMenu;
 use crate::menu::MenuEvent;
 use crate::{run_main_thread, AppHandle, Icon, Manager, Runtime};
 use std::path::Path;
-pub use tray_icon::{ClickType, Rectangle, TrayIconEvent, TrayIconId};
+pub use tray_icon::TrayIconId;
 
 // TODO(muda-migration): figure out js events
 
+/// Describes a rectangle including position (x - y axis) and size.
+#[derive(Debug, PartialEq, Clone, Copy, Default)]
+pub struct Rectangle {
+  /// The x-coordinate of the upper-left corner of the rectangle.
+  pub left: f64,
+  /// The y-coordinate of the upper-left corner of the rectangle.
+  pub top: f64,
+  /// The x-coordinate of the lower-right corner of the rectangle.
+  pub right: f64,
+  /// The y-coordinate of the lower-right corner of the rectangle.
+  pub bottom: f64,
+}
+
+/// Describes the click type that triggered this tray icon event.
+#[derive(Clone, Copy, PartialEq, Eq, Debug)]
+pub enum ClickType {
+  /// Left mouse click.
+  Left,
+  /// Right mouse click.
+  Right,
+  /// Double left mouse click.
+  Double,
+}
+
+impl Default for ClickType {
+  fn default() -> Self {
+    Self::Left
+  }
+}
+
+/// Describes a tray event emitted when a tray icon is clicked
+///
+/// ## Platform-specific:
+///
+/// - **Linux**: Unsupported. The event is not emmited even though the icon is shown,
+/// the icon will still show a context menu on right click.
+#[derive(Debug, Clone, Default)]
+pub struct TrayIconEvent {
+  /// Id of the tray icon which triggered this event.
+  pub id: TrayIconId,
+  /// Physical X Position of the click the triggered this event.
+  pub x: f64,
+  /// Physical Y Position of the click the triggered this event.
+  pub y: f64,
+  /// Position and size of the tray icon
+  pub icon_rect: Rectangle,
+  /// The click type that triggered this event.
+  pub click_type: ClickType,
+}
+
+impl TrayIconEvent {
+  /// Returns the id of the tray icon which triggered this event.
+  pub fn id(&self) -> &TrayIconId {
+    &self.id
+  }
+}
+
+impl From<tray_icon::Rectangle> for Rectangle {
+  fn from(value: tray_icon::Rectangle) -> Self {
+    Self {
+      bottom: value.bottom,
+      left: value.left,
+      top: value.top,
+      right: value.right,
+    }
+  }
+}
+
+impl From<tray_icon::ClickType> for ClickType {
+  fn from(value: tray_icon::ClickType) -> Self {
+    match value {
+      tray_icon::ClickType::Left => Self::Left,
+      tray_icon::ClickType::Right => Self::Right,
+      tray_icon::ClickType::Double => Self::Double,
+    }
+  }
+}
+
+impl From<tray_icon::TrayIconEvent> for TrayIconEvent {
+  fn from(value: tray_icon::TrayIconEvent) -> Self {
+    Self {
+      id: value.id,
+      x: value.x,
+      y: value.y,
+      icon_rect: value.icon_rect.into(),
+      click_type: value.click_type.into(),
+    }
+  }
+}
+
 /// [`TrayIcon`] builder struct and associated methods.
 #[derive(Default)]
 pub struct TrayIconBuilder<R: Runtime> {