Use NotificationPresenter - macOS

This commit is contained in:
Samuel Attard 2017-05-29 20:02:33 +10:00
parent 193c561815
commit 058bdfbced
17 changed files with 93 additions and 80 deletions

View file

@ -7,89 +7,48 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#include "atom/browser/browser.h" #include "atom/browser/browser.h"
#include "atom/browser/ui/notification_delegate_adapter.h"
#include "base/mac/mac_util.h" #include "base/mac/mac_util.h"
#include "base/mac/scoped_nsobject.h" #include "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h" #include "base/strings/sys_string_conversions.h"
#include "brightray/browser/notification.h"
std::map<int, base::scoped_nsobject<NSUserNotification>> native_notifications_; #include "brightray/browser/notification_presenter.h"
#include "brightray/browser/mac/notification_presenter_mac.h"
@interface AtomNotificationCenter : NSObject<NSUserNotificationCenterDelegate> { #include "third_party/skia/include/core/SkBitmap.h"
} #include "ui/gfx/codec/png_codec.h"
@end #include "url/gurl.h"
@implementation AtomNotificationCenter
- (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center
shouldPresentNotification:(NSUserNotification *)notification {
return YES;
}
- (void)userNotificationCenter:(NSUserNotificationCenter *)center
didActivateNotification:(NSUserNotification *)notification {
int n_id = [[notification.userInfo objectForKey:@"id"] intValue];
if (atom::api::Notification::HasID(n_id)) {
auto atomNotification = atom::api::Notification::FromID(n_id);
if (notification.activationType == NSUserNotificationActivationTypeReplied){
atomNotification->OnReplied([notification.response.string UTF8String]);
} else {
atomNotification->OnClicked();
}
}
}
@end
namespace atom { namespace atom {
namespace api { namespace api {
AtomNotificationCenter* del = [[AtomNotificationCenter alloc] init]; brightray::NotificationPresenterMac* presenter;
bool set_del_ = false;
void Notification::Show() { void Notification::Show() {
base::scoped_nsobject<NSUserNotification> notification_ = native_notifications_[id_]; SkBitmap image = *(new SkBitmap);
[NSUserNotificationCenter.defaultUserNotificationCenter if (has_icon_) {
deliverNotification:notification_]; image = *(icon_.ToSkBitmap());
OnShown();
}
void Notification::OnInitialProps() {
if (!set_del_) {
[[NSUserNotificationCenter defaultUserNotificationCenter] setDelegate:del];
set_del_ = true;
} }
base::scoped_nsobject<NSUserNotification> notification_; std::unique_ptr<AtomNotificationDelegateAdapter> adapter(
notification_.reset([[NSUserNotification alloc] init]); new AtomNotificationDelegateAdapter(this));
auto notif = presenter->CreateNotification(adapter.get());
if (notif) {
ignore_result(adapter.release()); // it will release itself automatically.
GURL nullUrl = *(new GURL);
notif->Show(title_, body_, "", nullUrl, image, silent_, has_reply_, reply_placeholder_);
}
}
native_notifications_[id_] = notification_; bool initialized_ = false;
void Notification::OnInitialProps() {
NotifyPropsUpdated(); if (!initialized_) {
presenter = new brightray::NotificationPresenterMac;
initialized_ = true;
}
} }
void Notification::NotifyPropsUpdated() { void Notification::NotifyPropsUpdated() {
base::scoped_nsobject<NSUserNotification> notification_ = native_notifications_[id_];
[notification_ setTitle:base::SysUTF16ToNSString(title_)];
[notification_ setInformativeText:base::SysUTF16ToNSString(body_)];
NSDictionary * userInfo = [NSMutableDictionary dictionary];
[userInfo setValue:[NSNumber numberWithInt:id_] forKey:@"id"];
[notification_ setUserInfo:userInfo];
if ([notification_ respondsToSelector:@selector(setContentImage:)] && has_icon_) {
[notification_ setContentImage:icon_.AsNSImage()];
}
if (has_reply_) {
[notification_ setResponsePlaceholder:base::SysUTF16ToNSString(reply_placeholder_)];
[notification_ setHasReplyButton:true];
}
if (silent_) {
[notification_ setSoundName:nil];
} else {
[notification_ setSoundName:NSUserNotificationDefaultSoundName];
}
} }
} // namespace api } // namespace api

View file

@ -20,6 +20,9 @@ void AtomNotificationDelegateAdapter::NotificationClosed() {}
void AtomNotificationDelegateAdapter::NotificationClick() { void AtomNotificationDelegateAdapter::NotificationClick() {
observer_->OnClicked(); observer_->OnClicked();
} }
void AtomNotificationDelegateAdapter::NotificationReplied(std::string reply) {
observer_->OnReplied(reply);
}
void AtomNotificationDelegateAdapter::NotificationDestroyed() {} void AtomNotificationDelegateAdapter::NotificationDestroyed() {}
void AtomNotificationDelegateAdapter::NotificationFailed() {} void AtomNotificationDelegateAdapter::NotificationFailed() {}

View file

@ -21,6 +21,7 @@ class AtomNotificationDelegateAdapter : public brightray::NotificationDelegate {
void NotificationClick(); void NotificationClick();
void NotificationDestroyed(); void NotificationDestroyed();
void NotificationFailed(); void NotificationFailed();
void NotificationReplied(std::string reply);
}; };
} // namespace atom } // namespace atom

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) { const bool silent,
const 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(),

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; const bool silent,
const 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; const bool silent,
const bool hasReply,
const base::string16 replyPlaceholder) override;
void Dismiss() override; void Dismiss() override;
void NotificationDisplayed(); void NotificationDisplayed();
void NotificationReplied(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) { const bool silent,
const 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_];
} }
@ -61,4 +68,8 @@ void CocoaNotification::NotificationDisplayed() {
delegate()->NotificationDisplayed(); delegate()->NotificationDisplayed();
} }
void CocoaNotification::NotificationReplied(const std::string reply) {
delegate()->NotificationReplied(reply);
}
} // namespace brightray } // namespace brightray

View file

@ -21,15 +21,21 @@
- (void)userNotificationCenter:(NSUserNotificationCenter*)center - (void)userNotificationCenter:(NSUserNotificationCenter*)center
didDeliverNotification:(NSUserNotification*)notif { didDeliverNotification:(NSUserNotification*)notif {
auto notification = presenter_->GetNotification(notif); auto notification = presenter_->GetNotification(notif);
if (notification) if (notification)
notification->NotificationDisplayed(); notification->NotificationDisplayed();
} }
- (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(); 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

@ -26,7 +26,9 @@ class 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) = 0; const bool silent,
const bool hasReply,
const base::string16 replyPlaceholder) = 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;

View file

@ -6,6 +6,7 @@
#define BRIGHTRAY_BROWSER_NOTIFICATION_DELEGATE_H_ #define BRIGHTRAY_BROWSER_NOTIFICATION_DELEGATE_H_
#include "content/public/browser/desktop_notification_delegate.h" #include "content/public/browser/desktop_notification_delegate.h"
#include <string>
namespace brightray { namespace brightray {
@ -16,6 +17,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(std::string reply) {}
}; };
} // namespace brightray } // namespace brightray

View file

@ -30,4 +30,8 @@ void NotificationDelegateAdapter::NotificationClick() {
delegate_->NotificationClick(); delegate_->NotificationClick();
} }
// void NotificationDelegateAdapter::NotificationReplied(std::string reply) {
// delegate_->NotificationReplied(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,7 @@ 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, const bool silent,
const 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, const bool silent,
const 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) { const bool silent,
const bool hasReply,
const base::string16 replyPlaceholder) {
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);

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; const bool silent,
const bool has_reply,
const base::string16 reply_placeholder) override;
void Dismiss() override; void Dismiss() override;
private: private:

View file

@ -1,4 +1,4 @@
const {app, BrowserWindow} = require('electron') const {app, BrowserWindow, Notification} = require('electron')
const path = require('path') const path = require('path')
let mainWindow = null let mainWindow = null
@ -27,5 +27,14 @@ exports.load = (appUrl) => {
mainWindow = new BrowserWindow(options) mainWindow = new BrowserWindow(options)
mainWindow.loadURL(appUrl) mainWindow.loadURL(appUrl)
mainWindow.focus() mainWindow.focus()
const n = new Notification({
title: 'Foo',
body: 'Bar',
hasReply: true,
replyPlaceholder: 'foo'
});
n.on('reply', (...args) => console.log(args));
n.show();
}) })
} }