Skip to content

Commit

Permalink
Merge pull request electron#9269 from electron/main-notifications
Browse files Browse the repository at this point in the history
Notifications from the main process
  • Loading branch information
zcbenz authored May 31, 2017
2 parents 717a1a6 + 9d4588a commit e82af41
Show file tree
Hide file tree
Showing 22 changed files with 438 additions and 25 deletions.
174 changes: 174 additions & 0 deletions atom/browser/api/atom_api_notification.cc
Original file line number Diff line number Diff line change
@@ -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)
83 changes: 83 additions & 0 deletions atom/browser/api/atom_api_notification.h
Original file line number Diff line number Diff line change
@@ -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_
1 change: 1 addition & 0 deletions atom/common/node_bindings.cc
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ REFERENCE_MODULE(atom_common_asar);
REFERENCE_MODULE(atom_common_clipboard);
REFERENCE_MODULE(atom_common_crash_reporter);
REFERENCE_MODULE(atom_common_native_image);
REFERENCE_MODULE(atom_common_notification);
REFERENCE_MODULE(atom_common_screen);
REFERENCE_MODULE(atom_common_shell);
REFERENCE_MODULE(atom_common_v8_util);
Expand Down
2 changes: 1 addition & 1 deletion brightray/browser/browser_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ BrowserClient::~BrowserClient() {

NotificationPresenter* BrowserClient::GetNotificationPresenter() {
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());
}
return notification_presenter_.get();
Expand Down
7 changes: 5 additions & 2 deletions brightray/browser/linux/libnotify_notification.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ void LibnotifyNotification::Show(const base::string16& title,
const std::string& tag,
const GURL& icon_url,
const SkBitmap& icon,
const bool silent) {
bool silent,
bool has_reply,
const base::string16& reply_placeholder) {
notification_ = libnotify_loader_.notify_notification_new(
base::UTF16ToUTF8(title).c_str(),
base::UTF16ToUTF8(body).c_str(),
Expand Down Expand Up @@ -137,7 +139,8 @@ void LibnotifyNotification::Show(const base::string16& title,
return;
}

delegate()->NotificationDisplayed();
if (delegate())
delegate()->NotificationDisplayed();
}

void LibnotifyNotification::Dismiss() {
Expand Down
4 changes: 3 additions & 1 deletion brightray/browser/linux/libnotify_notification.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ class LibnotifyNotification : public Notification {
const std::string& tag,
const GURL& icon_url,
const SkBitmap& icon,
const bool silent) override;
bool silent,
bool has_reply,
const base::string16& reply_placeholder) override;
void Dismiss() override;

private:
Expand Down
5 changes: 4 additions & 1 deletion brightray/browser/mac/cocoa_notification.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,13 @@ class CocoaNotification : public Notification {
const std::string& tag,
const GURL& icon_url,
const SkBitmap& icon,
const bool silent) override;
bool silent,
const bool has_reply,
const base::string16& reply_placeholder) override;
void Dismiss() override;

void NotificationDisplayed();
void NotificationReplied(const std::string& reply);

NSUserNotification* notification() const { return notification_; }

Expand Down
17 changes: 15 additions & 2 deletions brightray/browser/mac/cocoa_notification.mm
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
const std::string& tag,
const GURL& icon_url,
const SkBitmap& icon,
const bool silent) {
bool silent,
bool has_reply,
const base::string16& reply_placeholder) {
notification_.reset([[NSUserNotification alloc] init]);
[notification_ setTitle:base::SysUTF16ToNSString(title)];
[notification_ setInformativeText:base::SysUTF16ToNSString(body)];
Expand All @@ -46,6 +48,11 @@
[notification_ setSoundName:NSUserNotificationDefaultSoundName];
}

if (has_reply) {
[notification_ setResponsePlaceholder:base::SysUTF16ToNSString(reply_placeholder)];
[notification_ setHasReplyButton:true];
}

[NSUserNotificationCenter.defaultUserNotificationCenter
deliverNotification:notification_];
}
Expand All @@ -58,7 +65,13 @@
}

void CocoaNotification::NotificationDisplayed() {
delegate()->NotificationDisplayed();
if (delegate())
delegate()->NotificationDisplayed();
}

void CocoaNotification::NotificationReplied(const std::string& reply) {
if (delegate())
delegate()->NotificationReplied(reply);
}

} // namespace brightray
9 changes: 7 additions & 2 deletions brightray/browser/mac/notification_center_delegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,13 @@ - (void)userNotificationCenter:(NSUserNotificationCenter*)center
- (void)userNotificationCenter:(NSUserNotificationCenter*)center
didActivateNotification:(NSUserNotification *)notif {
auto notification = presenter_->GetNotification(notif);
if (notification)
notification->NotificationClicked();
if (notification) {
if (notif.activationType == NSUserNotificationActivationTypeReplied){
notification->NotificationReplied([notif.response.string UTF8String]);
} else {
notification->NotificationClicked();
}
}
}

- (BOOL)userNotificationCenter:(NSUserNotificationCenter*)center
Expand Down
Loading

0 comments on commit e82af41

Please sign in to comment.