Merge pull request #9269 from electron/main-notifications

Notifications from the main process
This commit is contained in:
Cheng Zhao 2017-05-31 17:21:05 +09:00 committed by GitHub
commit e82af41591
22 changed files with 438 additions and 25 deletions

View file

@ -0,0 +1,174 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#include "atom/browser/api/atom_api_notification.h"
#include "atom/browser/api/atom_api_menu.h"
#include "atom/browser/browser.h"
#include "atom/common/native_mate_converters/gfx_converter.h"
#include "atom/common/native_mate_converters/image_converter.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/node_includes.h"
#include "base/strings/utf_string_conversions.h"
#include "brightray/browser/browser_client.h"
#include "native_mate/constructor.h"
#include "native_mate/dictionary.h"
#include "url/gurl.h"
namespace atom {
namespace api {
Notification::Notification(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
mate::Arguments* args) {
InitWith(isolate, wrapper);
presenter_ = brightray::BrowserClient::Get()->GetNotificationPresenter();
mate::Dictionary opts;
if (args->GetNext(&opts)) {
opts.Get("title", &title_);
opts.Get("body", &body_);
has_icon_ = opts.Get("icon", &icon_);
if (has_icon_) {
opts.Get("icon", &icon_path_);
}
opts.Get("silent", &silent_);
opts.Get("replyPlaceholder", &reply_placeholder_);
opts.Get("hasReply", &has_reply_);
}
}
Notification::~Notification() {
if (notification_)
notification_->set_delegate(nullptr);
}
// static
mate::WrappableBase* Notification::New(mate::Arguments* args) {
if (!Browser::Get()->is_ready()) {
args->ThrowError("Cannot create Notification before app is ready");
return nullptr;
}
return new Notification(args->isolate(), args->GetThis(), args);
}
// Getters
base::string16 Notification::GetTitle() {
return title_;
}
base::string16 Notification::GetBody() {
return body_;
}
bool Notification::GetSilent() {
return silent_;
}
base::string16 Notification::GetReplyPlaceholder() {
return reply_placeholder_;
}
bool Notification::GetHasReply() {
return has_reply_;
}
// Setters
void Notification::SetTitle(const base::string16& new_title) {
title_ = new_title;
}
void Notification::SetBody(const base::string16& new_body) {
body_ = new_body;
}
void Notification::SetSilent(bool new_silent) {
silent_ = new_silent;
}
void Notification::SetReplyPlaceholder(const base::string16& new_placeholder) {
reply_placeholder_ = new_placeholder;
}
void Notification::SetHasReply(bool new_has_reply) {
has_reply_ = new_has_reply;
}
void Notification::NotificationClick() {
Emit("click");
}
void Notification::NotificationReplied(const std::string& reply) {
Emit("reply", reply);
}
void Notification::NotificationDisplayed() {
Emit("show");
}
void Notification::NotificationDestroyed() {
Emit("close");
}
void Notification::NotificationClosed() {
}
// Showing notifications
void Notification::Show() {
if (presenter_) {
notification_ = presenter_->CreateNotification(this);
if (notification_) {
notification_->Show(title_, body_, "", GURL(), icon_.AsBitmap(), silent_,
has_reply_, reply_placeholder_);
}
}
}
bool Notification::IsSupported() {
return !!brightray::BrowserClient::Get()->GetNotificationPresenter();
}
// static
void Notification::BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype) {
prototype->SetClassName(mate::StringToV8(isolate, "Notification"));
mate::ObjectTemplateBuilder(isolate, prototype->PrototypeTemplate())
.MakeDestroyable()
.SetMethod("show", &Notification::Show)
.SetProperty("title", &Notification::GetTitle, &Notification::SetTitle)
.SetProperty("body", &Notification::GetBody, &Notification::SetBody)
.SetProperty("silent", &Notification::GetSilent, &Notification::SetSilent)
.SetProperty("replyPlaceholder", &Notification::GetReplyPlaceholder,
&Notification::SetReplyPlaceholder)
.SetProperty("hasReply", &Notification::GetHasReply,
&Notification::SetHasReply);
}
} // namespace api
} // namespace atom
namespace {
using atom::api::Notification;
void Initialize(v8::Local<v8::Object> exports,
v8::Local<v8::Value> unused,
v8::Local<v8::Context> context,
void* priv) {
v8::Isolate* isolate = context->GetIsolate();
Notification::SetConstructor(isolate, base::Bind(&Notification::New));
mate::Dictionary dict(isolate, exports);
dict.Set("Notification",
Notification::GetConstructor(isolate)->GetFunction());
dict.SetMethod("isSupported", &Notification::IsSupported);
}
} // namespace
NODE_MODULE_CONTEXT_AWARE_BUILTIN(atom_common_notification, Initialize)

View file

@ -0,0 +1,83 @@
// Copyright (c) 2014 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.
#ifndef ATOM_BROWSER_API_ATOM_API_NOTIFICATION_H_
#define ATOM_BROWSER_API_ATOM_API_NOTIFICATION_H_
#include <memory>
#include <string>
#include <vector>
#include "atom/browser/api/trackable_object.h"
#include "base/strings/utf_string_conversions.h"
#include "brightray/browser/notification.h"
#include "brightray/browser/notification_delegate.h"
#include "brightray/browser/notification_presenter.h"
#include "native_mate/handle.h"
#include "ui/gfx/image/image.h"
namespace atom {
namespace api {
class Notification : public mate::TrackableObject<Notification>,
public brightray::NotificationDelegate {
public:
static mate::WrappableBase* New(mate::Arguments* args);
static bool IsSupported();
static void BuildPrototype(v8::Isolate* isolate,
v8::Local<v8::FunctionTemplate> prototype);
// NotificationDelegate:
void NotificationClick() override;
void NotificationReplied(const std::string& reply) override;
void NotificationDisplayed() override;
void NotificationDestroyed() override;
void NotificationClosed() override;
protected:
Notification(v8::Isolate* isolate,
v8::Local<v8::Object> wrapper,
mate::Arguments* args);
~Notification() override;
void Show();
// Prop Getters
base::string16 GetTitle();
base::string16 GetBody();
bool GetSilent();
base::string16 GetReplyPlaceholder();
bool GetHasReply();
// Prop Setters
void SetTitle(const base::string16& new_title);
void SetBody(const base::string16& new_body);
void SetSilent(bool new_silent);
void SetReplyPlaceholder(const base::string16& new_reply_placeholder);
void SetHasReply(bool new_has_reply);
private:
base::string16 title_;
base::string16 body_;
gfx::Image icon_;
base::string16 icon_path_;
bool has_icon_ = false;
bool silent_ = false;
base::string16 reply_placeholder_;
bool has_reply_ = false;
brightray::NotificationPresenter* presenter_;
base::WeakPtr<brightray::Notification> notification_;
DISALLOW_COPY_AND_ASSIGN(Notification);
};
} // namespace api
} // namespace atom
#endif // ATOM_BROWSER_API_ATOM_API_NOTIFICATION_H_

View file

@ -56,6 +56,7 @@ REFERENCE_MODULE(atom_common_asar);
REFERENCE_MODULE(atom_common_clipboard); REFERENCE_MODULE(atom_common_clipboard);
REFERENCE_MODULE(atom_common_crash_reporter); REFERENCE_MODULE(atom_common_crash_reporter);
REFERENCE_MODULE(atom_common_native_image); REFERENCE_MODULE(atom_common_native_image);
REFERENCE_MODULE(atom_common_notification);
REFERENCE_MODULE(atom_common_screen); REFERENCE_MODULE(atom_common_screen);
REFERENCE_MODULE(atom_common_shell); REFERENCE_MODULE(atom_common_shell);
REFERENCE_MODULE(atom_common_v8_util); REFERENCE_MODULE(atom_common_v8_util);

View file

@ -36,7 +36,7 @@ BrowserClient::~BrowserClient() {
NotificationPresenter* BrowserClient::GetNotificationPresenter() { NotificationPresenter* BrowserClient::GetNotificationPresenter() {
if (!notification_presenter_) { if (!notification_presenter_) {
// Create a new presenter if on OS X, Linux, or Windows 8+ // Create a new presenter if on OS X, Linux, or Windows 7+
notification_presenter_.reset(NotificationPresenter::Create()); notification_presenter_.reset(NotificationPresenter::Create());
} }
return notification_presenter_.get(); return notification_presenter_.get();

View file

@ -88,7 +88,9 @@ void LibnotifyNotification::Show(const base::string16& title,
const std::string& tag, const std::string& tag,
const GURL& icon_url, const GURL& icon_url,
const SkBitmap& icon, const SkBitmap& icon,
const bool silent) { bool silent,
bool has_reply,
const base::string16& reply_placeholder) {
notification_ = libnotify_loader_.notify_notification_new( notification_ = libnotify_loader_.notify_notification_new(
base::UTF16ToUTF8(title).c_str(), base::UTF16ToUTF8(title).c_str(),
base::UTF16ToUTF8(body).c_str(), base::UTF16ToUTF8(body).c_str(),
@ -137,7 +139,8 @@ void LibnotifyNotification::Show(const base::string16& title,
return; return;
} }
delegate()->NotificationDisplayed(); if (delegate())
delegate()->NotificationDisplayed();
} }
void LibnotifyNotification::Dismiss() { void LibnotifyNotification::Dismiss() {

View file

@ -27,7 +27,9 @@ class LibnotifyNotification : public Notification {
const std::string& tag, const std::string& tag,
const GURL& icon_url, const GURL& icon_url,
const SkBitmap& icon, const SkBitmap& icon,
const bool silent) override; bool silent,
bool has_reply,
const base::string16& reply_placeholder) override;
void Dismiss() override; void Dismiss() override;
private: private:

View file

@ -26,10 +26,13 @@ class CocoaNotification : public Notification {
const std::string& tag, const std::string& tag,
const GURL& icon_url, const GURL& icon_url,
const SkBitmap& icon, const SkBitmap& icon,
const bool silent) override; bool silent,
const bool has_reply,
const base::string16& reply_placeholder) override;
void Dismiss() override; void Dismiss() override;
void NotificationDisplayed(); void NotificationDisplayed();
void NotificationReplied(const std::string& reply);
NSUserNotification* notification() const { return notification_; } NSUserNotification* notification() const { return notification_; }

View file

@ -28,7 +28,9 @@ void CocoaNotification::Show(const base::string16& title,
const std::string& tag, const std::string& tag,
const GURL& icon_url, const GURL& icon_url,
const SkBitmap& icon, const SkBitmap& icon,
const bool silent) { bool silent,
bool has_reply,
const base::string16& reply_placeholder) {
notification_.reset([[NSUserNotification alloc] init]); notification_.reset([[NSUserNotification alloc] init]);
[notification_ setTitle:base::SysUTF16ToNSString(title)]; [notification_ setTitle:base::SysUTF16ToNSString(title)];
[notification_ setInformativeText:base::SysUTF16ToNSString(body)]; [notification_ setInformativeText:base::SysUTF16ToNSString(body)];
@ -46,6 +48,11 @@ void CocoaNotification::Show(const base::string16& title,
[notification_ setSoundName:NSUserNotificationDefaultSoundName]; [notification_ setSoundName:NSUserNotificationDefaultSoundName];
} }
if (has_reply) {
[notification_ setResponsePlaceholder:base::SysUTF16ToNSString(reply_placeholder)];
[notification_ setHasReplyButton:true];
}
[NSUserNotificationCenter.defaultUserNotificationCenter [NSUserNotificationCenter.defaultUserNotificationCenter
deliverNotification:notification_]; deliverNotification:notification_];
} }
@ -58,7 +65,13 @@ void CocoaNotification::Dismiss() {
} }
void CocoaNotification::NotificationDisplayed() { void CocoaNotification::NotificationDisplayed() {
delegate()->NotificationDisplayed(); if (delegate())
delegate()->NotificationDisplayed();
}
void CocoaNotification::NotificationReplied(const std::string& reply) {
if (delegate())
delegate()->NotificationReplied(reply);
} }
} // namespace brightray } // namespace brightray

View file

@ -28,8 +28,13 @@
- (void)userNotificationCenter:(NSUserNotificationCenter*)center - (void)userNotificationCenter:(NSUserNotificationCenter*)center
didActivateNotification:(NSUserNotification *)notif { didActivateNotification:(NSUserNotification *)notif {
auto notification = presenter_->GetNotification(notif); auto notification = presenter_->GetNotification(notif);
if (notification) if (notification) {
notification->NotificationClicked(); if (notif.activationType == NSUserNotificationActivationTypeReplied){
notification->NotificationReplied([notif.response.string UTF8String]);
} else {
notification->NotificationClicked();
}
}
} }
- (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center - (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center

View file

@ -17,21 +17,25 @@ Notification::Notification(NotificationDelegate* delegate,
} }
Notification::~Notification() { Notification::~Notification() {
delegate()->NotificationDestroyed(); if (delegate())
delegate()->NotificationDestroyed();
} }
void Notification::NotificationClicked() { void Notification::NotificationClicked() {
delegate()->NotificationClick(); if (delegate())
delegate()->NotificationClick();
Destroy(); Destroy();
} }
void Notification::NotificationDismissed() { void Notification::NotificationDismissed() {
delegate()->NotificationClosed(); if (delegate())
delegate()->NotificationClosed();
Destroy(); Destroy();
} }
void Notification::NotificationFailed() { void Notification::NotificationFailed() {
delegate()->NotificationFailed(); if (delegate())
delegate()->NotificationFailed();
Destroy(); Destroy();
} }

View file

@ -20,13 +20,17 @@ class NotificationPresenter;
class Notification { class Notification {
public: public:
virtual ~Notification();
// Shows the notification. // Shows the notification.
virtual void Show(const base::string16& title, virtual void Show(const base::string16& title,
const base::string16& msg, const base::string16& msg,
const std::string& tag, const std::string& tag,
const GURL& icon_url, const GURL& icon_url,
const SkBitmap& icon, const SkBitmap& icon,
const bool silent) = 0; bool silent,
bool has_reply,
const base::string16& reply_placeholder) = 0;
// Closes the notification, this instance will be destroyed after the // Closes the notification, this instance will be destroyed after the
// notification gets closed. // notification gets closed.
virtual void Dismiss() = 0; virtual void Dismiss() = 0;
@ -43,6 +47,7 @@ class Notification {
return weak_factory_.GetWeakPtr(); return weak_factory_.GetWeakPtr();
} }
void set_delegate(NotificationDelegate* delegate) { delegate_ = delegate; }
NotificationDelegate* delegate() const { return delegate_; } NotificationDelegate* delegate() const { return delegate_; }
NotificationPresenter* presenter() const { return presenter_; } NotificationPresenter* presenter() const { return presenter_; }
@ -50,9 +55,6 @@ class Notification {
Notification(NotificationDelegate* delegate, Notification(NotificationDelegate* delegate,
NotificationPresenter* presenter); NotificationPresenter* presenter);
public:
virtual ~Notification();
private: private:
NotificationDelegate* delegate_; NotificationDelegate* delegate_;
NotificationPresenter* presenter_; NotificationPresenter* presenter_;

View file

@ -5,6 +5,8 @@
#ifndef BRIGHTRAY_BROWSER_NOTIFICATION_DELEGATE_H_ #ifndef BRIGHTRAY_BROWSER_NOTIFICATION_DELEGATE_H_
#define BRIGHTRAY_BROWSER_NOTIFICATION_DELEGATE_H_ #define BRIGHTRAY_BROWSER_NOTIFICATION_DELEGATE_H_
#include <string>
#include "content/public/browser/desktop_notification_delegate.h" #include "content/public/browser/desktop_notification_delegate.h"
namespace brightray { namespace brightray {
@ -16,6 +18,9 @@ class NotificationDelegate : public content::DesktopNotificationDelegate {
// Failed to send the notification. // Failed to send the notification.
virtual void NotificationFailed() {} virtual void NotificationFailed() {}
// Notification was replied to
virtual void NotificationReplied(const std::string& reply) {}
}; };
} // namespace brightray } // namespace brightray

View file

@ -4,6 +4,7 @@
#include "brightray/browser/platform_notification_service.h" #include "brightray/browser/platform_notification_service.h"
#include "base/strings/utf_string_conversions.h"
#include "brightray/browser/browser_client.h" #include "brightray/browser/browser_client.h"
#include "brightray/browser/notification.h" #include "brightray/browser/notification.h"
#include "brightray/browser/notification_delegate_adapter.h" #include "brightray/browser/notification_delegate_adapter.h"
@ -30,7 +31,8 @@ void OnWebNotificationAllowed(base::WeakPtr<Notification> notification,
return; return;
if (allowed) if (allowed)
notification->Show(data.title, data.body, data.tag, data.icon, icon, notification->Show(data.title, data.body, data.tag, data.icon, icon,
audio_muted ? true : data.silent); audio_muted ? true : data.silent, false,
base::UTF8ToUTF16(""));
else else
notification->Destroy(); notification->Destroy();
} }

View file

@ -12,7 +12,8 @@ namespace brightray {
void Win32Notification::Show( void Win32Notification::Show(
const base::string16& title, const base::string16& msg, const base::string16& title, const base::string16& msg,
const std::string& tag, const GURL& icon_url, const std::string& tag, const GURL& icon_url,
const SkBitmap& icon, const bool silent) { const SkBitmap& icon, bool silent,
bool has_reply, const base::string16& reply_placeholder) {
auto presenter = static_cast<NotificationPresenterWin7*>(this->presenter()); auto presenter = static_cast<NotificationPresenterWin7*>(this->presenter());
if (!presenter) return; if (!presenter) return;

View file

@ -12,7 +12,8 @@ class Win32Notification : public brightray::Notification {
} }
void Show(const base::string16& title, const base::string16& msg, void Show(const base::string16& title, const base::string16& msg,
const std::string& tag, const GURL& icon_url, const std::string& tag, const GURL& icon_url,
const SkBitmap& icon, const bool silent) override; const SkBitmap& icon, bool silent,
bool has_reply, const base::string16& reply_placeholder) override;
void Dismiss() override; void Dismiss() override;
const DesktopNotificationController::Notification& GetRef() const { const DesktopNotificationController::Notification& GetRef() const {

View file

@ -89,7 +89,9 @@ void WindowsToastNotification::Show(const base::string16& title,
const std::string& tag, const std::string& tag,
const GURL& icon_url, const GURL& icon_url,
const SkBitmap& icon, const SkBitmap& icon,
const bool silent) { bool silent,
bool has_reply,
const base::string16& reply_placeholder) {
auto presenter_win = static_cast<NotificationPresenterWin*>(presenter()); auto presenter_win = static_cast<NotificationPresenterWin*>(presenter());
std::wstring icon_path = presenter_win->SaveIconToFilesystem(icon, icon_url); std::wstring icon_path = presenter_win->SaveIconToFilesystem(icon, icon_url);
@ -131,7 +133,8 @@ void WindowsToastNotification::Show(const base::string16& title,
return; return;
} }
delegate()->NotificationDisplayed(); if (delegate())
delegate()->NotificationDisplayed();
} }
void WindowsToastNotification::Dismiss() { void WindowsToastNotification::Dismiss() {
@ -144,7 +147,7 @@ bool WindowsToastNotification::GetToastXml(
const std::wstring& title, const std::wstring& title,
const std::wstring& msg, const std::wstring& msg,
const std::wstring& icon_path, const std::wstring& icon_path,
const bool silent, bool silent,
IXmlDocument** toast_xml) { IXmlDocument** toast_xml) {
ABI::Windows::UI::Notifications::ToastTemplateType template_type; ABI::Windows::UI::Notifications::ToastTemplateType template_type;
if (title.empty() || msg.empty()) { if (title.empty() || msg.empty()) {

View file

@ -55,7 +55,9 @@ class WindowsToastNotification : public Notification {
const std::string& tag, const std::string& tag,
const GURL& icon_url, const GURL& icon_url,
const SkBitmap& icon, const SkBitmap& icon,
const bool silent) override; bool silent,
bool has_reply,
const base::string16& reply_placeholder) override;
void Dismiss() override; void Dismiss() override;
private: private:

95
docs/api/notification.md Normal file
View file

@ -0,0 +1,95 @@
# Notification
> Create OS desktop notifications
Process: [Main](../glossary.md#main-process)
## Using in the renderer process
If you want to show Notifications from a renderer process you should use the [HTML5 Notification API](../tutorial/notifications.md)
## Class: Notification
> Create OS desktop notifications
Process: [Main](../glossary.md#main-process)
`Notification` is an
[EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter).
It creates a new `Notification` with native properties as set by the `options`.
### Static Methods
The `Notification` class has the following static methods:
#### `BrowserWindow.isSupported()`
Returns `Boolean` - Whether or not desktop notifications are supported on the current system
### `new Notification([options])` _Experimental_
* `options` Object
* `title` String - A title for the notification, which will be shown at the top of the notification window when it is shown
* `body` String - The body text of the notification, which will be displayed below the title
* `silent` Boolean - (Optional) Whether or not to emit an OS notification noise when showing the notification
* `icon` [NativeImage](native-image.md) - (Optional) An icon to use in the notification
* `hasReply` Boolean - (Optional) Whether or not to add an inline reply option to the notification. _macOS_
* `replyPlaceholder` String - (Optional) The placeholder to write in the inline reply input field. _macOS_
### Instance Events
Objects created with `new Notification` emit the following events:
**Note:** Some events are only available on specific operating systems and are
labeled as such.
#### Event: 'show'
Returns:
* `event` Event
Emitted when the notification is shown to the user, note this could be fired
multiple times as a notification can be shown multiple times through the
`show()` method.
#### Event: 'click'
Returns:
* `event` Event
Emitted when the notification is clicked by the user.
#### Event: 'close'
Returns:
* `event` Event
Emitted when the notification is closed by manual intervention from the user.
This event is not guarunteed to be emitted in all cases where the notification
is closed.
#### Event: 'reply' _macOS_
Returns:
* `event` Event
* `reply` String - The string the user entered into the inline reply field
Emitted when the user clicks the "Reply" button on a notification with `hasReply: true`.
### Instance Methods
Objects created with `new Notification` have the following instance methods:
#### `notification.show()`
Immediately shows the notification to the user, please note this means unlike the
HTML5 Notification implementation, simply instantiating a `new Notification` does
not immediately show it to the user, you need to call this method before the OS
will display it.

View file

@ -5,7 +5,9 @@ to the user. Electron conveniently allows developers to send notifications with
the [HTML5 Notification API](https://notifications.spec.whatwg.org/), using the [HTML5 Notification API](https://notifications.spec.whatwg.org/), using
the currently running operating system's native notification APIs to display it. the currently running operating system's native notification APIs to display it.
**Note:** Since this is an HTML5 API it is only available in the renderer process. **Note:** Since this is an HTML5 API it is only available in the renderer process. If
you want to show Notifications in the main process please check out the
[Notification](../api/notification.md) module.
```javascript ```javascript
let myNotification = new Notification('Title', { let myNotification = new Notification('Title', {

View file

@ -26,6 +26,7 @@
'lib/browser/api/module-list.js', 'lib/browser/api/module-list.js',
'lib/browser/api/navigation-controller.js', 'lib/browser/api/navigation-controller.js',
'lib/browser/api/net.js', 'lib/browser/api/net.js',
'lib/browser/api/notification.js',
'lib/browser/api/power-monitor.js', 'lib/browser/api/power-monitor.js',
'lib/browser/api/power-save-blocker.js', 'lib/browser/api/power-save-blocker.js',
'lib/browser/api/protocol.js', 'lib/browser/api/protocol.js',
@ -127,6 +128,8 @@
'atom/browser/api/atom_api_menu_views.h', 'atom/browser/api/atom_api_menu_views.h',
'atom/browser/api/atom_api_net.cc', 'atom/browser/api/atom_api_net.cc',
'atom/browser/api/atom_api_net.h', 'atom/browser/api/atom_api_net.h',
'atom/browser/api/atom_api_notification.cc',
'atom/browser/api/atom_api_notification.h',
'atom/browser/api/atom_api_power_monitor.cc', 'atom/browser/api/atom_api_power_monitor.cc',
'atom/browser/api/atom_api_power_monitor.h', 'atom/browser/api/atom_api_power_monitor.h',
'atom/browser/api/atom_api_power_save_blocker.cc', 'atom/browser/api/atom_api_power_save_blocker.cc',

View file

@ -11,6 +11,7 @@ module.exports = [
{name: 'Menu', file: 'menu'}, {name: 'Menu', file: 'menu'},
{name: 'MenuItem', file: 'menu-item'}, {name: 'MenuItem', file: 'menu-item'},
{name: 'net', file: 'net'}, {name: 'net', file: 'net'},
{name: 'Notification', file: 'notification'},
{name: 'powerMonitor', file: 'power-monitor'}, {name: 'powerMonitor', file: 'power-monitor'},
{name: 'powerSaveBlocker', file: 'power-save-blocker'}, {name: 'powerSaveBlocker', file: 'power-save-blocker'},
{name: 'protocol', file: 'protocol'}, {name: 'protocol', file: 'protocol'},

View file

@ -0,0 +1,8 @@
const {EventEmitter} = require('events')
const {Notification, isSupported} = process.atomBinding('notification')
Object.setPrototypeOf(Notification.prototype, EventEmitter.prototype)
Notification.isSupported = isSupported
module.exports = Notification