mirror of
https://github.com/ElectronNET/Electron.NET.git
synced 2026-08-10 01:59:28 +00:00
implement full Notification-API
This commit is contained in:
15
ElectronNET.API/Entities/NotificationAction.cs
Normal file
15
ElectronNET.API/Entities/NotificationAction.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace ElectronNET.API.Entities
|
||||
{
|
||||
public class NotificationAction
|
||||
{
|
||||
/// <summary>
|
||||
/// The label for the given action.
|
||||
/// </summary>
|
||||
public string Text { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The type of action, can be button.
|
||||
/// </summary>
|
||||
public string Type { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
namespace ElectronNET.API.Entities
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
|
||||
namespace ElectronNET.API.Entities
|
||||
{
|
||||
public class NotificationOptions
|
||||
{
|
||||
@@ -44,6 +47,63 @@
|
||||
/// </summary>
|
||||
public string Sound { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Actions to add to the notification. Please read the available actions and
|
||||
/// limitations in the NotificationAction documentation
|
||||
/// </summary>
|
||||
public NotificationAction Actions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Action OnShow { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
internal string ShowID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Emitted when the notification is clicked by the user.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Action OnClick { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
internal string ClickID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Action OnClose { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
internal string CloseID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// macOS only: Emitted when the user clicks the “Reply” button on a notification with hasReply: true.
|
||||
///
|
||||
/// The string the user entered into the inline reply field
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Action<string> OnReply { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
internal string ReplyID { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// macOS only - The index of the action that was activated
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public Action<string> OnAction { get; set; }
|
||||
|
||||
[JsonProperty]
|
||||
internal string ActionID { get; set; }
|
||||
|
||||
public NotificationOptions(string title, string body)
|
||||
{
|
||||
Title = title;
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ElectronNET.API
|
||||
{
|
||||
@@ -24,11 +28,105 @@ namespace ElectronNET.API
|
||||
}
|
||||
}
|
||||
|
||||
private static List<NotificationOptions> _notificationOptions = new List<NotificationOptions>();
|
||||
|
||||
/// <summary>
|
||||
/// Create OS desktop notifications
|
||||
/// </summary>
|
||||
/// <param name="notificationOptions"></param>
|
||||
public void Show(NotificationOptions notificationOptions)
|
||||
{
|
||||
GenerateIDsForDefinedActions(notificationOptions);
|
||||
|
||||
BridgeConnector.Socket.Emit("createNotification", JObject.FromObject(notificationOptions, _jsonSerializer));
|
||||
}
|
||||
|
||||
private static void GenerateIDsForDefinedActions(NotificationOptions notificationOptions)
|
||||
{
|
||||
bool isActionDefined = false;
|
||||
|
||||
if (notificationOptions.OnShow != null)
|
||||
{
|
||||
notificationOptions.ShowID = Guid.NewGuid().ToString();
|
||||
isActionDefined = true;
|
||||
|
||||
BridgeConnector.Socket.Off("NotificationEventShow");
|
||||
BridgeConnector.Socket.On("NotificationEventShow", (id) => {
|
||||
_notificationOptions.Single(x => x.ShowID == id.ToString()).OnShow();
|
||||
});
|
||||
}
|
||||
|
||||
if (notificationOptions.OnClick != null)
|
||||
{
|
||||
notificationOptions.ClickID = Guid.NewGuid().ToString();
|
||||
isActionDefined = true;
|
||||
|
||||
BridgeConnector.Socket.Off("NotificationEventClick");
|
||||
BridgeConnector.Socket.On("NotificationEventClick", (id) => {
|
||||
_notificationOptions.Single(x => x.ClickID == id.ToString()).OnClick();
|
||||
});
|
||||
}
|
||||
|
||||
if (notificationOptions.OnClose != null)
|
||||
{
|
||||
notificationOptions.CloseID = Guid.NewGuid().ToString();
|
||||
isActionDefined = true;
|
||||
|
||||
BridgeConnector.Socket.Off("NotificationEventClose");
|
||||
BridgeConnector.Socket.On("NotificationEventClose", (id) => {
|
||||
_notificationOptions.Single(x => x.CloseID == id.ToString()).OnClose();
|
||||
});
|
||||
}
|
||||
|
||||
if (notificationOptions.OnReply != null)
|
||||
{
|
||||
notificationOptions.ReplyID = Guid.NewGuid().ToString();
|
||||
isActionDefined = true;
|
||||
|
||||
BridgeConnector.Socket.Off("NotificationEventReply");
|
||||
BridgeConnector.Socket.On("NotificationEventReply", (args) => {
|
||||
var arguments = ((JArray)args).ToObject<string[]>();
|
||||
_notificationOptions.Single(x => x.ReplyID == arguments[0].ToString()).OnReply(arguments[1].ToString());
|
||||
});
|
||||
}
|
||||
|
||||
if (notificationOptions.OnAction != null)
|
||||
{
|
||||
notificationOptions.ActionID = Guid.NewGuid().ToString();
|
||||
isActionDefined = true;
|
||||
|
||||
BridgeConnector.Socket.Off("NotificationEventAction");
|
||||
BridgeConnector.Socket.On("NotificationEventAction", (args) => {
|
||||
var arguments = ((JArray)args).ToObject<string[]>();
|
||||
_notificationOptions.Single(x => x.ReplyID == arguments[0].ToString()).OnAction(arguments[1].ToString());
|
||||
});
|
||||
}
|
||||
|
||||
if (isActionDefined)
|
||||
{
|
||||
_notificationOptions.Add(notificationOptions);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not desktop notifications are supported on the current system.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Task<bool> IsSupportedAsync()
|
||||
{
|
||||
var taskCompletionSource = new TaskCompletionSource<bool>();
|
||||
|
||||
BridgeConnector.Socket.On("notificationIsSupportedComplete", (isSupported) =>
|
||||
{
|
||||
BridgeConnector.Socket.Off("notificationIsSupportedComplete");
|
||||
taskCompletionSource.SetResult((bool)isSupported);
|
||||
});
|
||||
|
||||
BridgeConnector.Socket.Emit("notificationIsSupported");
|
||||
|
||||
return taskCompletionSource.Task;
|
||||
}
|
||||
|
||||
private JsonSerializer _jsonSerializer = new JsonSerializer()
|
||||
{
|
||||
ContractResolver = new CamelCasePropertyNamesContractResolver(),
|
||||
|
||||
@@ -1,10 +1,49 @@
|
||||
"use strict";
|
||||
exports.__esModule = true;
|
||||
var electron_1 = require("electron");
|
||||
var notifications = [];
|
||||
module.exports = function (socket) {
|
||||
socket.on('createNotification', function (options) {
|
||||
var notification = new electron_1.Notification(options);
|
||||
var haveEvent = false;
|
||||
if (options.showID) {
|
||||
haveEvent = true;
|
||||
notification.on('show', function () {
|
||||
socket.emit('NotificationEventShow', options.showID);
|
||||
});
|
||||
}
|
||||
if (options.clickID) {
|
||||
haveEvent = true;
|
||||
notification.on('click', function () {
|
||||
socket.emit('NotificationEventClick', options.clickID);
|
||||
});
|
||||
}
|
||||
if (options.closeID) {
|
||||
haveEvent = true;
|
||||
notification.on('close', function () {
|
||||
socket.emit('NotificationEventClose', options.closeID);
|
||||
});
|
||||
}
|
||||
if (options.replyID) {
|
||||
haveEvent = true;
|
||||
notification.on('reply', function (event, value) {
|
||||
socket.emit('NotificationEventReply', [options.replyID, value]);
|
||||
});
|
||||
}
|
||||
if (options.actionID) {
|
||||
haveEvent = true;
|
||||
notification.on('action', function (event, value) {
|
||||
socket.emit('NotificationEventAction', [options.actionID, value]);
|
||||
});
|
||||
}
|
||||
if (haveEvent) {
|
||||
notifications.push(notification);
|
||||
}
|
||||
notification.show();
|
||||
});
|
||||
socket.on('notificationIsSupported', function (options) {
|
||||
var isSupported = electron_1.Notification.isSupported;
|
||||
socket.emit('notificationIsSupportedComplete', isSupported);
|
||||
});
|
||||
};
|
||||
//# sourceMappingURL=notification.js.map
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"notification.js","sourceRoot":"","sources":["notification.ts"],"names":[],"mappings":";;AAAA,qCAAwC;AAExC,MAAM,CAAC,OAAO,GAAG,UAAC,MAAuB;IACrC,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,UAAC,OAAO;QACpC,IAAM,YAAY,GAAG,IAAI,uBAAY,CAAC,OAAO,CAAC,CAAC;QAC/C,YAAY,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;AACP,CAAC,CAAA"}
|
||||
{"version":3,"file":"notification.js","sourceRoot":"","sources":["notification.ts"],"names":[],"mappings":";;AAAA,qCAAwC;AACxC,IAAM,aAAa,GAA4B,EAAE,CAAC;AAElD,MAAM,CAAC,OAAO,GAAG,UAAC,MAAuB;IACrC,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,UAAC,OAAO;QACpC,IAAM,YAAY,GAAG,IAAI,uBAAY,CAAC,OAAO,CAAC,CAAC;QAC/C,IAAI,SAAS,GAAG,KAAK,CAAC;QAEtB,EAAE,CAAA,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;YAChB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE;gBACpB,MAAM,CAAC,IAAI,CAAC,uBAAuB,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YACzD,CAAC,CAAC,CAAC;QACP,CAAC;QAED,EAAE,CAAA,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;YACjB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;gBACrB,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAC3D,CAAC,CAAC,CAAC;QACP,CAAC;QAED,EAAE,CAAA,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;YACjB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE;gBACrB,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YAC3D,CAAC,CAAC,CAAC;QACP,CAAC;QAED,EAAE,CAAA,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;YACjB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,UAAC,KAAK,EAAE,KAAK;gBAClC,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;YACpE,CAAC,CAAC,CAAC;QACP,CAAC;QAED,EAAE,CAAA,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;YAClB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAC,KAAK,EAAE,KAAK;gBACnC,MAAM,CAAC,IAAI,CAAC,yBAAyB,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;YACtE,CAAC,CAAC,CAAC;QACP,CAAC;QAED,EAAE,CAAA,CAAC,SAAS,CAAC,CAAC,CAAC;YACX,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACrC,CAAC;QAED,YAAY,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,UAAC,OAAO;QACzC,IAAM,WAAW,GAAG,uBAAY,CAAC,WAAW,CAAC;QAC7C,MAAM,CAAC,IAAI,CAAC,iCAAiC,EAAE,WAAW,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;AACP,CAAC,CAAA"}
|
||||
@@ -1,8 +1,55 @@
|
||||
import { Notification } from "electron";
|
||||
const notifications: Electron.Notification[] = [];
|
||||
|
||||
module.exports = (socket: SocketIO.Server) => {
|
||||
socket.on('createNotification', (options) => {
|
||||
const notification = new Notification(options);
|
||||
let haveEvent = false;
|
||||
|
||||
if(options.showID) {
|
||||
haveEvent = true;
|
||||
notification.on('show', () => {
|
||||
socket.emit('NotificationEventShow', options.showID);
|
||||
});
|
||||
}
|
||||
|
||||
if(options.clickID) {
|
||||
haveEvent = true;
|
||||
notification.on('click', () => {
|
||||
socket.emit('NotificationEventClick', options.clickID);
|
||||
});
|
||||
}
|
||||
|
||||
if(options.closeID) {
|
||||
haveEvent = true;
|
||||
notification.on('close', () => {
|
||||
socket.emit('NotificationEventClose', options.closeID);
|
||||
});
|
||||
}
|
||||
|
||||
if(options.replyID) {
|
||||
haveEvent = true;
|
||||
notification.on('reply', (event, value) => {
|
||||
socket.emit('NotificationEventReply', [options.replyID, value]);
|
||||
});
|
||||
}
|
||||
|
||||
if(options.actionID) {
|
||||
haveEvent = true;
|
||||
notification.on('action', (event, value) => {
|
||||
socket.emit('NotificationEventAction', [options.actionID, value]);
|
||||
});
|
||||
}
|
||||
|
||||
if(haveEvent) {
|
||||
notifications.push(notification);
|
||||
}
|
||||
|
||||
notification.show();
|
||||
});
|
||||
|
||||
socket.on('notificationIsSupported', (options) => {
|
||||
const isSupported = Notification.isSupported;
|
||||
socket.emit('notificationIsSupportedComplete', isSupported);
|
||||
});
|
||||
}
|
||||
@@ -11,7 +11,13 @@ namespace ElectronNET.WebApp.Controllers
|
||||
{
|
||||
Electron.IpcMain.On("SayHello", async (args) =>
|
||||
{
|
||||
Electron.Notification.Show(new NotificationOptions("Hallo Robert", "Nachricht von ASP.NET Core App"));
|
||||
Electron.Notification.Show(new NotificationOptions("Hallo Robert", "Nachricht von ASP.NET Core App") {
|
||||
OnClick = async () => { await Electron.Dialog.ShowMessageBoxAsync(new MessageBoxOptions("Notification clicked")); },
|
||||
OnShow = async () => { await Electron.Dialog.ShowMessageBoxAsync(new MessageBoxOptions("Notification show")); },
|
||||
OnClose = async () => { await Electron.Dialog.ShowMessageBoxAsync(new MessageBoxOptions("Notification closed")); },
|
||||
OnAction = async (value) => { await Electron.Dialog.ShowMessageBoxAsync(new MessageBoxOptions("Notification Action")); },
|
||||
OnReply = async (value) => { await Electron.Dialog.ShowMessageBoxAsync(new MessageBoxOptions("Notification Reply")); }
|
||||
});
|
||||
Electron.IpcMain.Send(Electron.WindowManager.BrowserWindows.First(), "Goodbye", "Elephant!");
|
||||
|
||||
var currentBrowserWindow = Electron.WindowManager.BrowserWindows.First();
|
||||
@@ -28,6 +34,8 @@ namespace ElectronNET.WebApp.Controllers
|
||||
|
||||
Electron.IpcMain.On("GetPath", async (args) =>
|
||||
{
|
||||
Electron.Notification.Show(new NotificationOptions("test", "test2"));
|
||||
|
||||
var currentBrowserWindow = Electron.WindowManager.BrowserWindows.First();
|
||||
|
||||
string pathName = await Electron.App.GetPathAsync(PathName.pictures);
|
||||
|
||||
Reference in New Issue
Block a user