Browse Source

feat: add new options to tray.displayBalloon() (#19544)

Milan Burda 5 years ago
parent
commit
0fb3c8cb7c

+ 9 - 1
docs/api/tray.md

@@ -222,12 +222,20 @@ Returns `Boolean` - Whether double click events will be ignored.
 #### `tray.displayBalloon(options)` _Windows_
 
 * `options` Object
-  * `icon` ([NativeImage](native-image.md) | String) (optional) -
+  * `icon` ([NativeImage](native-image.md) | String) (optional) - Icon to use when `iconType` is `custom`.
+  * `iconType` String (optional) - Can be `none`, `info`, `warning`, `error` or `custom`. Default is `custom`.
   * `title` String
   * `content` String
+  * `largeIcon` Boolean (optional) - The large version of the icon should be used. Default is `true`. Maps to [`NIIF_LARGE_ICON`][NIIF_LARGE_ICON].
+  * `noSound` Boolean (optional) - Do not play the associated sound. Default is `false`. Maps to [`NIIF_NOSOUND`][NIIF_NOSOUND].
+  * `respectQuietTime` Boolean (optional) - Do not display the balloon notification if the current user is in "quiet time". Default is `false`. Maps to [`NIIF_RESPECT_QUIET_TIME`][NIIF_RESPECT_QUIET_TIME].
 
 Displays a tray balloon.
 
+[NIIF_NOSOUND]: https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataa#niif_nosound-0x00000010
+[NIIF_LARGE_ICON]: https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataa#niif_large_icon-0x00000020
+[NIIF_RESPECT_QUIET_TIME]: https://docs.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataa#niif_respect_quiet_time-0x00000080
+
 #### `tray.removeBalloon()` _Windows_
 
 Removes a tray balloon.

+ 51 - 9
shell/browser/api/atom_api_tray.cc

@@ -18,6 +18,39 @@
 #include "shell/common/node_includes.h"
 #include "ui/gfx/image/image.h"
 
+namespace mate {
+
+template <>
+struct Converter<electron::TrayIcon::IconType> {
+  static bool FromV8(v8::Isolate* isolate,
+                     v8::Local<v8::Value> val,
+                     electron::TrayIcon::IconType* out) {
+    using IconType = electron::TrayIcon::IconType;
+    std::string mode;
+    if (ConvertFromV8(isolate, val, &mode)) {
+      if (mode == "none") {
+        *out = IconType::None;
+        return true;
+      } else if (mode == "info") {
+        *out = IconType::Info;
+        return true;
+      } else if (mode == "warning") {
+        *out = IconType::Warning;
+        return true;
+      } else if (mode == "error") {
+        *out = IconType::Error;
+        return true;
+      } else if (mode == "custom") {
+        *out = IconType::Custom;
+        return true;
+      }
+    }
+    return false;
+  }
+};
+
+}  // namespace mate
+
 namespace electron {
 
 namespace api {
@@ -157,22 +190,31 @@ bool Tray::GetIgnoreDoubleClickEvents() {
 
 void Tray::DisplayBalloon(mate::Arguments* args,
                           const mate::Dictionary& options) {
-  mate::Handle<NativeImage> icon;
-  options.Get("icon", &icon);
-  base::string16 title, content;
-  if (!options.Get("title", &title) || !options.Get("content", &content)) {
+  TrayIcon::BalloonOptions balloon_options;
+
+  if (!options.Get("title", &balloon_options.title) ||
+      !options.Get("content", &balloon_options.content)) {
     args->ThrowError("'title' and 'content' must be defined");
     return;
   }
 
+  mate::Handle<NativeImage> icon;
+  options.Get("icon", &icon);
+  options.Get("iconType", &balloon_options.icon_type);
+  options.Get("largeIcon", &balloon_options.large_icon);
+  options.Get("noSound", &balloon_options.no_sound);
+  options.Get("respectQuietTime", &balloon_options.respect_quiet_time);
+
+  if (!icon.IsEmpty()) {
 #if defined(OS_WIN)
-  tray_icon_->DisplayBalloon(
-      icon.IsEmpty() ? NULL : icon->GetHICON(GetSystemMetrics(SM_CXICON)),
-      title, content);
+    balloon_options.icon = icon->GetHICON(
+        GetSystemMetrics(balloon_options.large_icon ? SM_CXICON : SM_CXSMICON));
 #else
-  tray_icon_->DisplayBalloon(icon.IsEmpty() ? gfx::Image() : icon->image(),
-                             title, content);
+    balloon_options.icon = icon->image();
 #endif
+  }
+
+  tray_icon_->DisplayBalloon(balloon_options);
 }
 
 void Tray::RemoveBalloon() {

+ 3 - 3
shell/browser/ui/tray_icon.cc

@@ -6,15 +6,15 @@
 
 namespace electron {
 
+TrayIcon::BalloonOptions::BalloonOptions() = default;
+
 TrayIcon::TrayIcon() {}
 
 TrayIcon::~TrayIcon() {}
 
 void TrayIcon::SetPressedImage(ImageType image) {}
 
-void TrayIcon::DisplayBalloon(ImageType icon,
-                              const base::string16& title,
-                              const base::string16& contents) {}
+void TrayIcon::DisplayBalloon(const BalloonOptions& options) {}
 
 void TrayIcon::RemoveBalloon() {}
 

+ 19 - 3
shell/browser/ui/tray_icon.h

@@ -49,11 +49,27 @@ class TrayIcon {
   virtual std::string GetTitle() = 0;
 #endif
 
+  enum class IconType { None, Info, Warning, Error, Custom };
+
+  struct BalloonOptions {
+    IconType icon_type = IconType::Custom;
+#if defined(OS_WIN)
+    HICON icon = nullptr;
+#else
+    gfx::Image icon;
+#endif
+    base::string16 title;
+    base::string16 content;
+    bool large_icon = true;
+    bool no_sound = false;
+    bool respect_quiet_time = false;
+
+    BalloonOptions();
+  };
+
   // Displays a notification balloon with the specified contents.
   // Depending on the platform it might not appear by the icon tray.
-  virtual void DisplayBalloon(ImageType icon,
-                              const base::string16& title,
-                              const base::string16& contents);
+  virtual void DisplayBalloon(const BalloonOptions& options);
 
   // Removes the notification balloon.
   virtual void RemoveBalloon();

+ 36 - 8
shell/browser/ui/win/notify_icon.cc

@@ -17,6 +17,28 @@
 #include "ui/views/controls/menu/menu_runner.h"
 #include "ui/views/widget/widget.h"
 
+namespace {
+
+UINT ConvertIconType(electron::TrayIcon::IconType type) {
+  using IconType = electron::TrayIcon::IconType;
+  switch (type) {
+    case IconType::None:
+      return NIIF_NONE;
+    case IconType::Info:
+      return NIIF_INFO;
+    case IconType::Warning:
+      return NIIF_WARNING;
+    case IconType::Error:
+      return NIIF_ERROR;
+    case IconType::Custom:
+      return NIIF_USER;
+    default:
+      NOTREACHED() << "Invalid icon type";
+  }
+}
+
+}  // namespace
+
 namespace electron {
 
 NotifyIcon::NotifyIcon(NotifyIconHost* host, UINT id, HWND window, UINT message)
@@ -120,18 +142,24 @@ void NotifyIcon::SetToolTip(const std::string& tool_tip) {
     LOG(WARNING) << "Unable to set tooltip for status tray icon";
 }
 
-void NotifyIcon::DisplayBalloon(HICON icon,
-                                const base::string16& title,
-                                const base::string16& contents) {
+void NotifyIcon::DisplayBalloon(const BalloonOptions& options) {
   NOTIFYICONDATA icon_data;
   InitIconData(&icon_data);
   icon_data.uFlags |= NIF_INFO;
-  icon_data.dwInfoFlags = NIIF_INFO;
-  wcsncpy_s(icon_data.szInfoTitle, title.c_str(), _TRUNCATE);
-  wcsncpy_s(icon_data.szInfo, contents.c_str(), _TRUNCATE);
+  wcsncpy_s(icon_data.szInfoTitle, options.title.c_str(), _TRUNCATE);
+  wcsncpy_s(icon_data.szInfo, options.content.c_str(), _TRUNCATE);
   icon_data.uTimeout = 0;
-  icon_data.hBalloonIcon = icon;
-  icon_data.dwInfoFlags = NIIF_USER | NIIF_LARGE_ICON;
+  icon_data.hBalloonIcon = options.icon;
+  icon_data.dwInfoFlags = ConvertIconType(options.icon_type);
+
+  if (options.large_icon)
+    icon_data.dwInfoFlags |= NIIF_LARGE_ICON;
+
+  if (options.no_sound)
+    icon_data.dwInfoFlags |= NIIF_NOSOUND;
+
+  if (options.respect_quiet_time)
+    icon_data.dwInfoFlags |= NIIF_RESPECT_QUIET_TIME;
 
   BOOL result = Shell_NotifyIcon(NIM_MODIFY, &icon_data);
   if (!result)

+ 1 - 3
shell/browser/ui/win/notify_icon.h

@@ -58,9 +58,7 @@ class NotifyIcon : public TrayIcon {
   void SetImage(HICON image) override;
   void SetPressedImage(HICON image) override;
   void SetToolTip(const std::string& tool_tip) override;
-  void DisplayBalloon(HICON icon,
-                      const base::string16& title,
-                      const base::string16& contents) override;
+  void DisplayBalloon(const BalloonOptions& options) override;
   void RemoveBalloon() override;
   void PopUpContextMenu(const gfx::Point& pos,
                         AtomMenuModel* menu_model) override;