Use NotificationPresenter - macOS
This commit is contained in:
parent
193c561815
commit
058bdfbced
17 changed files with 93 additions and 80 deletions
|
@ -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
|
||||||
|
|
|
@ -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() {}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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_; }
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -30,4 +30,8 @@ void NotificationDelegateAdapter::NotificationClick() {
|
||||||
delegate_->NotificationClick();
|
delegate_->NotificationClick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// void NotificationDelegateAdapter::NotificationReplied(std::string reply) {
|
||||||
|
// delegate_->NotificationReplied(reply);
|
||||||
|
// }
|
||||||
|
|
||||||
} // namespace brightray
|
} // namespace brightray
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue