From 08b88e3adf8d26da42b9941f923b34b43b2cb2e8 Mon Sep 17 00:00:00 2001 From: Gregor Biswanger Date: Sun, 15 Oct 2017 17:03:07 +0200 Subject: [PATCH] implement first dialog-, notification-, tray- and menu-api functions --- ElectronNET.API/App.cs | 6 -- ElectronNET.API/Dialog.cs | 89 ++++++++++++++++++ ElectronNET.API/Electron.cs | 15 +++ ElectronNET.API/Entities/MessageBoxOptions.cs | 84 +++++++++++++++++ ElectronNET.API/Entities/MessageBoxResult.cs | 9 ++ .../Entities/NotificationOptions.cs | 45 +++++++++ ElectronNET.API/Notification.cs | 39 ++++++++ ElectronNET.API/Tray.cs | 39 ++++++++ ElectronNET.CLI/Commands/BuildCommand.cs | 4 + .../Commands/StartElectronCommand.cs | 4 + ElectronNET.CLI/ElectronNET.CLI.csproj | 7 ++ ElectronNET.Host/api/browserWindows.js | 1 + ElectronNET.Host/api/browserWindows.js.map | 2 +- ElectronNET.Host/api/dialog.js | 19 ++++ ElectronNET.Host/api/dialog.js.map | 1 + ElectronNET.Host/api/dialog.ts | 17 ++++ ElectronNET.Host/api/menu.js | 23 +++++ ElectronNET.Host/api/menu.js.map | 1 + ElectronNET.Host/api/menu.ts | 25 +++++ ElectronNET.Host/api/notification.js | 10 ++ ElectronNET.Host/api/notification.js.map | 1 + ElectronNET.Host/api/notification.ts | 8 ++ ElectronNET.Host/api/tray.js | 14 +++ ElectronNET.Host/api/tray.js.map | 1 + ElectronNET.Host/api/tray.ts | 14 +++ ElectronNET.Host/main.js | 37 ++------ ElectronNET.WebApp/Assets/electron.ico | Bin 0 -> 279958 bytes ElectronNET.WebApp/Assets/electron_32x32.png | Bin 0 -> 1281 bytes .../Controllers/HomeController.cs | 6 +- ElectronNET.WebApp/ElectronNET.WebApp.csproj | 10 ++ ElectronNET.WebApp/Startup.cs | 24 ++++- ElectronNET.WebApp/Views/Home/Index.cshtml | 1 - 32 files changed, 511 insertions(+), 45 deletions(-) create mode 100644 ElectronNET.API/Dialog.cs create mode 100644 ElectronNET.API/Entities/MessageBoxOptions.cs create mode 100644 ElectronNET.API/Entities/MessageBoxResult.cs create mode 100644 ElectronNET.API/Notification.cs create mode 100644 ElectronNET.API/Tray.cs create mode 100644 ElectronNET.Host/api/dialog.js create mode 100644 ElectronNET.Host/api/dialog.js.map create mode 100644 ElectronNET.Host/api/dialog.ts create mode 100644 ElectronNET.Host/api/menu.js create mode 100644 ElectronNET.Host/api/menu.js.map create mode 100644 ElectronNET.Host/api/menu.ts create mode 100644 ElectronNET.Host/api/notification.js create mode 100644 ElectronNET.Host/api/notification.js.map create mode 100644 ElectronNET.Host/api/notification.ts create mode 100644 ElectronNET.Host/api/tray.js create mode 100644 ElectronNET.Host/api/tray.js.map create mode 100644 ElectronNET.Host/api/tray.ts create mode 100644 ElectronNET.WebApp/Assets/electron.ico create mode 100644 ElectronNET.WebApp/Assets/electron_32x32.png diff --git a/ElectronNET.API/App.cs b/ElectronNET.API/App.cs index 4d4c86a..e4849ad 100644 --- a/ElectronNET.API/App.cs +++ b/ElectronNET.API/App.cs @@ -280,12 +280,6 @@ namespace ElectronNET.API ContractResolver = new CamelCasePropertyNamesContractResolver() }; - // TODO: Auslagern in eigenes Notification-API - public void CreateNotification(NotificationOptions notificationOptions) - { - BridgeConnector.Socket.Emit("createNotification", JObject.FromObject(notificationOptions, _jsonSerializer)); - } - /// /// Try to close all windows. The before-quit event will be emitted first. If all /// windows are successfully closed, the will-quit event will be emitted and by diff --git a/ElectronNET.API/Dialog.cs b/ElectronNET.API/Dialog.cs new file mode 100644 index 0000000..f47afac --- /dev/null +++ b/ElectronNET.API/Dialog.cs @@ -0,0 +1,89 @@ +using ElectronNET.API.Entities; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Serialization; +using System; +using System.Threading.Tasks; + +namespace ElectronNET.API +{ + public sealed class Dialog + { + private static Dialog _dialog; + + internal Dialog() { } + + internal static Dialog Instance + { + get + { + if (_dialog == null) + { + _dialog = new Dialog(); + } + + return _dialog; + } + } + + /// + /// Shows a message box, it will block the process until the message box is closed. + /// It returns the index of the clicked button. The browserWindow argument allows + /// the dialog to attach itself to a parent window, making it modal. If a callback + /// is passed, the dialog will not block the process.The API call will be + /// asynchronous and the result will be passed via callback(response). + /// + /// + /// The API call will be asynchronous and the result will be passed via MessageBoxResult. + public async Task ShowMessageBoxAsync(MessageBoxOptions messageBoxOptions) + { + return await ShowMessageBoxAsync(null, messageBoxOptions); + } + + /// + /// Shows a message box, it will block the process until the message box is closed. + /// It returns the index of the clicked button. If a callback + /// is passed, the dialog will not block the process. + /// + /// The browserWindow argument allows the dialog to attach itself to a parent window, making it modal. + /// + /// The API call will be asynchronous and the result will be passed via MessageBoxResult. + public Task ShowMessageBoxAsync(BrowserWindow browserWindow, MessageBoxOptions messageBoxOptions) + { + var taskCompletionSource = new TaskCompletionSource(); + + BridgeConnector.Socket.On("showMessageBoxComplete", (args) => + { + BridgeConnector.Socket.Off("showMessageBoxComplete"); + + var result = ((JArray)args); + + taskCompletionSource.SetResult(new MessageBoxResult + { + Response = (int)result.First, + CheckboxChecked = (bool)result.Last + }); + + }); + + if (browserWindow == null) + { + BridgeConnector.Socket.Emit("showMessageBox", JObject.FromObject(messageBoxOptions, _jsonSerializer)); + } else + { + BridgeConnector.Socket.Emit("showMessageBox", + JObject.FromObject(browserWindow, _jsonSerializer), + JObject.FromObject(messageBoxOptions, _jsonSerializer)); + } + + return taskCompletionSource.Task; + } + + private JsonSerializer _jsonSerializer = new JsonSerializer() + { + ContractResolver = new CamelCasePropertyNamesContractResolver(), + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore + }; + } +} diff --git a/ElectronNET.API/Electron.cs b/ElectronNET.API/Electron.cs index 0a551b0..6002677 100644 --- a/ElectronNET.API/Electron.cs +++ b/ElectronNET.API/Electron.cs @@ -21,5 +21,20 @@ /// Create native application menus and context menus. /// public static Menu Menu { get { return Menu.Instance; } } + + /// + /// Display native system dialogs for opening and saving files, alerting, etc. + /// + public static Dialog Dialog { get { return Dialog.Instance; } } + + /// + /// Create OS desktop notifications + /// + public static Notification Notification { get { return Notification.Instance; } } + + /// + /// Add icons and context menus to the system’s notification area. + /// + public static Tray Tray { get { return Tray.Instance; } } } } diff --git a/ElectronNET.API/Entities/MessageBoxOptions.cs b/ElectronNET.API/Entities/MessageBoxOptions.cs new file mode 100644 index 0000000..960471c --- /dev/null +++ b/ElectronNET.API/Entities/MessageBoxOptions.cs @@ -0,0 +1,84 @@ +namespace ElectronNET.API.Entities +{ + public class MessageBoxOptions + { + /// + /// Can be "none", "info", "error", "question" or "warning". On Windows, "question" + /// displays the same icon as "info", unless you set an icon using the "icon" + /// option.On macOS, both "warning" and "error" display the same warning icon. + /// + public string Type { get; set; } + + /// + /// Array of texts for buttons. On Windows, an empty array will result in one button + /// labeled "OK". + /// + public string[] Buttons { get; set; } + + /// + /// Index of the button in the buttons array which will be selected by default when + /// the message box opens. + /// + public int DefaultId { get; set; } + + /// + /// Title of the message box, some platforms will not show it. + /// + public string Title { get; set; } + + /// + /// Content of the message box. + /// + public string Message { get; set; } + + /// + /// Extra information of the message. + /// + public string Detail { get; set; } + + /// + /// If provided, the message box will include a checkbox with the given label. The + /// checkbox state can be inspected only when using callback. + /// + public string CheckboxLabel { get; set; } + + /// + /// Initial checked state of the checkbox. false by default. + /// + public bool CheckboxChecked { get; set; } + + public string Icon { get; set; } + + /// + /// The index of the button to be used to cancel the dialog, via the Esc key. By + /// default this is assigned to the first button with "cancel" or "no" as the label. + /// If no such labeled buttons exist and this option is not set, 0 will be used as + /// the return value or callback response. This option is ignored on Windows. + /// + public int CancelId { get; set; } + + /// + /// On Windows Electron will try to figure out which one of the buttons are common + /// buttons(like "Cancel" or "Yes"), and show the others as command links in the + /// dialog.This can make the dialog appear in the style of modern Windows apps. If + /// you don't like this behavior, you can set noLink to true. + /// + public bool NoLink { get; set; } + + /// + /// Normalize the keyboard access keys across platforms. Default is false. Enabling + /// this assumes & is used in the button labels for the placement of the keyboard + /// shortcut access key and labels will be converted so they work correctly on each + /// platform, & characters are removed on macOS, converted to _ on Linux, and left + /// untouched on Windows.For example, a button label of Vie&w will be converted to + /// Vie_w on Linux and View on macOS and can be selected via Alt-W on Windows and + /// Linux. + /// + public bool NormalizeAccessKeys { get; set; } + + public MessageBoxOptions(string message) + { + Message = message; + } + } +} diff --git a/ElectronNET.API/Entities/MessageBoxResult.cs b/ElectronNET.API/Entities/MessageBoxResult.cs new file mode 100644 index 0000000..20a19b6 --- /dev/null +++ b/ElectronNET.API/Entities/MessageBoxResult.cs @@ -0,0 +1,9 @@ +namespace ElectronNET.API.Entities +{ + public class MessageBoxResult + { + public int Response { get; set; } + + public bool CheckboxChecked { get; set; } + } +} diff --git a/ElectronNET.API/Entities/NotificationOptions.cs b/ElectronNET.API/Entities/NotificationOptions.cs index b58e954..efa127f 100644 --- a/ElectronNET.API/Entities/NotificationOptions.cs +++ b/ElectronNET.API/Entities/NotificationOptions.cs @@ -2,7 +2,52 @@ { public class NotificationOptions { + /// + /// A title for the notification, which will be shown at the top of the notification + /// window when it is shown + /// public string Title { get; set; } + + /// + /// The body text of the notification, which will be displayed below the title or + /// subtitle + /// public string Body { get; set; } + + /// + /// A subtitle for the notification, which will be displayed below the title. + /// + public string Subtitle { get; set; } + + /// + /// Whether or not to emit an OS notification noise when showing the notification + /// + public bool Silent { get; set; } + + /// + /// An icon to use in the notification + /// + public string Icon { get; set; } + + /// + /// Whether or not to add an inline reply option to the notification. + /// + public bool HasReply { get; set; } + + /// + /// The placeholder to write in the inline reply input field. + /// + public string ReplyPlaceholder { get; set; } + + /// + /// The name of the sound file to play when the notification is shown. + /// + public string Sound { get; set; } + + public NotificationOptions(string title, string body) + { + Title = title; + Body = body; + } } } diff --git a/ElectronNET.API/Notification.cs b/ElectronNET.API/Notification.cs new file mode 100644 index 0000000..ad396d0 --- /dev/null +++ b/ElectronNET.API/Notification.cs @@ -0,0 +1,39 @@ +using ElectronNET.API.Entities; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Serialization; + +namespace ElectronNET.API +{ + public sealed class Notification + { + private static Notification _notification; + + internal Notification() { } + + internal static Notification Instance + { + get + { + if (_notification == null) + { + _notification = new Notification(); + } + + return _notification; + } + } + + public void Show(NotificationOptions notificationOptions) + { + BridgeConnector.Socket.Emit("createNotification", JObject.FromObject(notificationOptions, _jsonSerializer)); + } + + private JsonSerializer _jsonSerializer = new JsonSerializer() + { + ContractResolver = new CamelCasePropertyNamesContractResolver(), + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore + }; + } +} diff --git a/ElectronNET.API/Tray.cs b/ElectronNET.API/Tray.cs new file mode 100644 index 0000000..417812e --- /dev/null +++ b/ElectronNET.API/Tray.cs @@ -0,0 +1,39 @@ +using ElectronNET.API.Entities; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Newtonsoft.Json.Serialization; + +namespace ElectronNET.API +{ + public sealed class Tray + { + private static Tray _tray; + + internal Tray() { } + + internal static Tray Instance + { + get + { + if (_tray == null) + { + _tray = new Tray(); + } + + return _tray; + } + } + + public void Show(string image, MenuItem[] menuItems) + { + BridgeConnector.Socket.Emit("create-tray", image, JArray.FromObject(menuItems, _jsonSerializer)); + } + + private JsonSerializer _jsonSerializer = new JsonSerializer() + { + ContractResolver = new CamelCasePropertyNamesContractResolver(), + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore + }; + } +} diff --git a/ElectronNET.CLI/Commands/BuildCommand.cs b/ElectronNET.CLI/Commands/BuildCommand.cs index 7e3b366..66503b9 100644 --- a/ElectronNET.CLI/Commands/BuildCommand.cs +++ b/ElectronNET.CLI/Commands/BuildCommand.cs @@ -42,6 +42,10 @@ namespace ElectronNET.CLI.Commands EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "ipc.js", "api."); EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "app.js", "api."); EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "browserWindows.js", "api."); + EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "dialog.js", "api."); + EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "menu.js", "api."); + EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "notification.js", "api."); + EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "tray.js", "api."); Console.WriteLine("Start npm install..."); ProcessHelper.CmdExecute("npm install", tempPath); diff --git a/ElectronNET.CLI/Commands/StartElectronCommand.cs b/ElectronNET.CLI/Commands/StartElectronCommand.cs index 8dd5159..474e1da 100644 --- a/ElectronNET.CLI/Commands/StartElectronCommand.cs +++ b/ElectronNET.CLI/Commands/StartElectronCommand.cs @@ -61,6 +61,10 @@ namespace ElectronNET.CLI.Commands EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "ipc.js", "api."); EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "app.js", "api."); EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "browserWindows.js", "api."); + EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "dialog.js", "api."); + EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "menu.js", "api."); + EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "notification.js", "api."); + EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "tray.js", "api."); Console.WriteLine("Start npm install..."); ProcessHelper.CmdExecute("npm install", tempPath); diff --git a/ElectronNET.CLI/ElectronNET.CLI.csproj b/ElectronNET.CLI/ElectronNET.CLI.csproj index b530400..994d6f5 100644 --- a/ElectronNET.CLI/ElectronNET.CLI.csproj +++ b/ElectronNET.CLI/ElectronNET.CLI.csproj @@ -39,4 +39,11 @@ + + + + + + + diff --git a/ElectronNET.Host/api/browserWindows.js b/ElectronNET.Host/api/browserWindows.js index 85b812c..39efbb2 100644 --- a/ElectronNET.Host/api/browserWindows.js +++ b/ElectronNET.Host/api/browserWindows.js @@ -19,6 +19,7 @@ module.exports = function (socket) { } } }); + // TODO: IPC Lösung für mehrere Fenster finden if (ipc == undefined) { ipc = require('./ipc')(socket, window); } diff --git a/ElectronNET.Host/api/browserWindows.js.map b/ElectronNET.Host/api/browserWindows.js.map index f1c28ff..3e67861 100644 --- a/ElectronNET.Host/api/browserWindows.js.map +++ b/ElectronNET.Host/api/browserWindows.js.map @@ -1 +1 @@ -{"version":3,"file":"browserWindows.js","sourceRoot":"","sources":["browserWindows.ts"],"names":[],"mappings":";;AAAA,qCAAyC;AACzC,IAAI,OAAO,GAA6B,EAAE,CAAA;AAC1C,IAAI,GAAG,CAAC;AAER,MAAM,CAAC,OAAO,GAAG,UAAC,MAAuB;IACrC,MAAM,CAAC,EAAE,CAAC,qBAAqB,EAAE,UAAC,OAAO,EAAE,OAAO;QAC9C,IAAI,MAAM,GAAG,IAAI,wBAAa,CAAC,OAAO,CAAC,CAAC;QAExC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAC,MAAM;YACvB,GAAG,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;gBAClD,IAAI,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;gBAChC,IAAI,CAAC;oBACD,UAAU,CAAC,EAAE,CAAC;gBAClB,CAAC;gBAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;oBACb,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,KAAK,2BAA2B,CAAC,CAAC,CAAC;wBAChD,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;oBAC7B,CAAC;gBACL,CAAC;YACL,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,CAAC,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC;YACnB,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3C,CAAC;QAED,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YACV,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,wBAAwB,EAAE,UAAC,EAAE;QACnC,aAAa,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,uBAAuB,EAAU;QAC7B,GAAG,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;YAClD,IAAI,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;YAC7B,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;gBACnB,MAAM,CAAC,OAAO,CAAC;YACnB,CAAC;QACL,CAAC;IACL,CAAC;AACL,CAAC,CAAA"} \ No newline at end of file +{"version":3,"file":"browserWindows.js","sourceRoot":"","sources":["browserWindows.ts"],"names":[],"mappings":";;AAAA,qCAAyC;AACzC,IAAI,OAAO,GAA6B,EAAE,CAAA;AAC1C,IAAI,GAAG,CAAC;AAER,MAAM,CAAC,OAAO,GAAG,UAAC,MAAuB;IACrC,MAAM,CAAC,EAAE,CAAC,qBAAqB,EAAE,UAAC,OAAO,EAAE,OAAO;QAC9C,IAAI,MAAM,GAAG,IAAI,wBAAa,CAAC,OAAO,CAAC,CAAC;QAExC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,UAAC,MAAM;YACvB,GAAG,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;gBAClD,IAAI,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;gBAChC,IAAI,CAAC;oBACD,UAAU,CAAC,EAAE,CAAC;gBAClB,CAAC;gBAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;oBACb,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,KAAK,2BAA2B,CAAC,CAAC,CAAC;wBAChD,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;oBAC7B,CAAC;gBACL,CAAC;YACL,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,+CAA+C;QAC/C,EAAE,CAAC,CAAC,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC;YACnB,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAC3C,CAAC;QAED,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YACV,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrB,MAAM,CAAC,IAAI,CAAC,sBAAsB,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,wBAAwB,EAAE,UAAC,EAAE;QACnC,aAAa,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC;IACjC,CAAC,CAAC,CAAC;IAEH,uBAAuB,EAAU;QAC7B,GAAG,CAAC,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;YAClD,IAAI,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;YAC7B,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;gBACnB,MAAM,CAAC,OAAO,CAAC;YACnB,CAAC;QACL,CAAC;IACL,CAAC;AACL,CAAC,CAAA"} \ No newline at end of file diff --git a/ElectronNET.Host/api/dialog.js b/ElectronNET.Host/api/dialog.js new file mode 100644 index 0000000..e3f106e --- /dev/null +++ b/ElectronNET.Host/api/dialog.js @@ -0,0 +1,19 @@ +"use strict"; +exports.__esModule = true; +var electron_1 = require("electron"); +module.exports = function (socket) { + socket.on('showMessageBox', function (browserWindow, options) { + if ("id" in browserWindow) { + var window = electron_1.BrowserWindow.fromId(browserWindow.id); + electron_1.dialog.showMessageBox(window, options, function (response, checkboxChecked) { + socket.emit('showMessageBoxComplete', response, checkboxChecked); + }); + } + else { + electron_1.dialog.showMessageBox(browserWindow, function (response, checkboxChecked) { + socket.emit('showMessageBoxComplete', response, checkboxChecked); + }); + } + }); +}; +//# sourceMappingURL=dialog.js.map \ No newline at end of file diff --git a/ElectronNET.Host/api/dialog.js.map b/ElectronNET.Host/api/dialog.js.map new file mode 100644 index 0000000..f7a9d8d --- /dev/null +++ b/ElectronNET.Host/api/dialog.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dialog.js","sourceRoot":"","sources":["dialog.ts"],"names":[],"mappings":";;AAAA,qCAAiD;AAEjD,MAAM,CAAC,OAAO,GAAG,UAAC,MAAuB;IACrC,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,UAAC,aAAa,EAAE,OAAO;QAC/C,EAAE,CAAA,CAAC,IAAI,IAAI,aAAa,CAAC,CAAC,CAAC;YACvB,IAAI,MAAM,GAAG,wBAAa,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;YAEpD,iBAAM,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,EAAE,UAAC,QAAQ,EAAE,eAAe;gBAC7D,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;YACrE,CAAC,CAAC,CAAC;QACP,CAAC;QAAC,IAAI,CAAC,CAAC;YACJ,iBAAM,CAAC,cAAc,CAAC,aAAa,EAAE,UAAC,QAAQ,EAAE,eAAe;gBAC3D,MAAM,CAAC,IAAI,CAAC,wBAAwB,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;YACrE,CAAC,CAAC,CAAC;QACP,CAAC;IACL,CAAC,CAAC,CAAC;AACP,CAAC,CAAA"} \ No newline at end of file diff --git a/ElectronNET.Host/api/dialog.ts b/ElectronNET.Host/api/dialog.ts new file mode 100644 index 0000000..c445e51 --- /dev/null +++ b/ElectronNET.Host/api/dialog.ts @@ -0,0 +1,17 @@ +import { BrowserWindow, dialog } from "electron"; + +module.exports = (socket: SocketIO.Server) => { + socket.on('showMessageBox', (browserWindow, options) => { + if("id" in browserWindow) { + var window = BrowserWindow.fromId(browserWindow.id); + + dialog.showMessageBox(window, options, (response, checkboxChecked) => { + socket.emit('showMessageBoxComplete', response, checkboxChecked); + }); + } else { + dialog.showMessageBox(browserWindow, (response, checkboxChecked) => { + socket.emit('showMessageBoxComplete', response, checkboxChecked); + }); + } + }); +} \ No newline at end of file diff --git a/ElectronNET.Host/api/menu.js b/ElectronNET.Host/api/menu.js new file mode 100644 index 0000000..4eb7eb3 --- /dev/null +++ b/ElectronNET.Host/api/menu.js @@ -0,0 +1,23 @@ +"use strict"; +exports.__esModule = true; +var electron_1 = require("electron"); +module.exports = function (socket) { + socket.on('menu-setApplicationMenu', function (menuItems) { + var menu = electron_1.Menu.buildFromTemplate(menuItems); + addMenuItemClickConnector(menu.items, function (id) { + socket.emit("menuItemClicked", id); + }); + electron_1.Menu.setApplicationMenu(menu); + }); + function addMenuItemClickConnector(menuItems, callback) { + menuItems.forEach(function (item) { + if (item.submenu && item.submenu.items.length > 0) { + addMenuItemClickConnector(item.submenu.items, callback); + } + if ("id" in item && item.id) { + item.click = function () { callback(item.id); }; + } + }); + } +}; +//# sourceMappingURL=menu.js.map \ No newline at end of file diff --git a/ElectronNET.Host/api/menu.js.map b/ElectronNET.Host/api/menu.js.map new file mode 100644 index 0000000..94adcce --- /dev/null +++ b/ElectronNET.Host/api/menu.js.map @@ -0,0 +1 @@ +{"version":3,"file":"menu.js","sourceRoot":"","sources":["menu.ts"],"names":[],"mappings":";;AAAA,qCAAgC;AAEhC,MAAM,CAAC,OAAO,GAAG,UAAC,MAAuB;IACrC,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,UAAC,SAAS;QAC3C,IAAM,IAAI,GAAG,eAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAE/C,yBAAyB,CAAC,IAAI,CAAC,KAAK,EAAE,UAAC,EAAE;YACrC,MAAM,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;QAEH,eAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,mCAAmC,SAAS,EAAE,QAAQ;QAClD,SAAS,CAAC,OAAO,CAAC,UAAC,IAAI;YACnB,EAAE,CAAA,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;gBAC/C,yBAAyB,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAC5D,CAAC;YAED,EAAE,CAAA,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;gBACzB,IAAI,CAAC,KAAK,GAAG,cAAQ,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9C,CAAC;QACL,CAAC,CAAC,CAAC;IACP,CAAC;AACL,CAAC,CAAA"} \ No newline at end of file diff --git a/ElectronNET.Host/api/menu.ts b/ElectronNET.Host/api/menu.ts new file mode 100644 index 0000000..1d96344 --- /dev/null +++ b/ElectronNET.Host/api/menu.ts @@ -0,0 +1,25 @@ +import { Menu } from "electron"; + +module.exports = (socket: SocketIO.Server) => { + socket.on('menu-setApplicationMenu', (menuItems) => { + const menu = Menu.buildFromTemplate(menuItems); + + addMenuItemClickConnector(menu.items, (id) => { + socket.emit("menuItemClicked", id); + }); + + Menu.setApplicationMenu(menu); + }); + + function addMenuItemClickConnector(menuItems, callback) { + menuItems.forEach((item) => { + if(item.submenu && item.submenu.items.length > 0) { + addMenuItemClickConnector(item.submenu.items, callback); + } + + if("id" in item && item.id) { + item.click = () => { callback(item.id); }; + } + }); + } +} \ No newline at end of file diff --git a/ElectronNET.Host/api/notification.js b/ElectronNET.Host/api/notification.js new file mode 100644 index 0000000..8ce83a7 --- /dev/null +++ b/ElectronNET.Host/api/notification.js @@ -0,0 +1,10 @@ +"use strict"; +exports.__esModule = true; +var electron_1 = require("electron"); +module.exports = function (socket) { + socket.on('createNotification', function (options) { + var notification = new electron_1.Notification(options); + notification.show(); + }); +}; +//# sourceMappingURL=notification.js.map \ No newline at end of file diff --git a/ElectronNET.Host/api/notification.js.map b/ElectronNET.Host/api/notification.js.map new file mode 100644 index 0000000..b7d3ab1 --- /dev/null +++ b/ElectronNET.Host/api/notification.js.map @@ -0,0 +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"} \ No newline at end of file diff --git a/ElectronNET.Host/api/notification.ts b/ElectronNET.Host/api/notification.ts new file mode 100644 index 0000000..2264373 --- /dev/null +++ b/ElectronNET.Host/api/notification.ts @@ -0,0 +1,8 @@ +import { Notification } from "electron"; + +module.exports = (socket: SocketIO.Server) => { + socket.on('createNotification', (options) => { + const notification = new Notification(options); + notification.show(); + }); +} \ No newline at end of file diff --git a/ElectronNET.Host/api/tray.js b/ElectronNET.Host/api/tray.js new file mode 100644 index 0000000..8cc6e97 --- /dev/null +++ b/ElectronNET.Host/api/tray.js @@ -0,0 +1,14 @@ +"use strict"; +exports.__esModule = true; +var electron_1 = require("electron"); +var path = require('path'); +var tray; +module.exports = function (socket) { + socket.on('create-tray', function (image, menuItems) { + var menu = electron_1.Menu.buildFromTemplate(menuItems); + var imagePath = path.join(__dirname.replace('api', ''), 'bin', image); + tray = new electron_1.Tray(imagePath); + tray.setContextMenu(menu); + }); +}; +//# sourceMappingURL=tray.js.map \ No newline at end of file diff --git a/ElectronNET.Host/api/tray.js.map b/ElectronNET.Host/api/tray.js.map new file mode 100644 index 0000000..6ceee68 --- /dev/null +++ b/ElectronNET.Host/api/tray.js.map @@ -0,0 +1 @@ +{"version":3,"file":"tray.js","sourceRoot":"","sources":["tray.ts"],"names":[],"mappings":";;AAAA,qCAAsC;AACtC,IAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;AAC7B,IAAI,IAAI,CAAC;AAET,MAAM,CAAC,OAAO,GAAG,UAAC,MAAuB;IACrC,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,UAAC,KAAK,EAAE,SAAS;QACtC,IAAM,IAAI,GAAG,eAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAE/C,IAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QAExE,IAAI,GAAG,IAAI,eAAI,CAAC,SAAS,CAAC,CAAC;QAC3B,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;AACP,CAAC,CAAA"} \ No newline at end of file diff --git a/ElectronNET.Host/api/tray.ts b/ElectronNET.Host/api/tray.ts new file mode 100644 index 0000000..a0ec1c8 --- /dev/null +++ b/ElectronNET.Host/api/tray.ts @@ -0,0 +1,14 @@ +import { Menu, Tray } from "electron"; +const path = require('path'); +let tray; + +module.exports = (socket: SocketIO.Server) => { + socket.on('create-tray', (image, menuItems) => { + const menu = Menu.buildFromTemplate(menuItems); + + const imagePath = path.join(__dirname.replace('api', ''), 'bin', image); + + tray = new Tray(imagePath); + tray.setContextMenu(menu); + }); +} \ No newline at end of file diff --git a/ElectronNET.Host/main.js b/ElectronNET.Host/main.js index 0fcca2e..4c01f71 100644 --- a/ElectronNET.Host/main.js +++ b/ElectronNET.Host/main.js @@ -1,9 +1,9 @@ -const { app, Notification, Menu } = require('electron'); +const { app } = require('electron'); const fs = require('fs'); const path = require('path'); const process = require('child_process').spawn; const portfinder = require('detect-port'); -let io, browserWindows, apiProcess, loadURL, appApi; +let io, browserWindows, apiProcess, loadURL, appApi, menu, dialog, notification, tray; app.on('ready', () => { portfinder(8000, (error, port) => { @@ -17,36 +17,13 @@ function startSocketApiBridge(port) { io.on('connection', (socket) => { console.log('ASP.NET Core Application connected...'); + appApi = require('./api/app')(socket, app); browserWindows = require('./api/browserWindows')(socket); - - socket.on('menu-setApplicationMenu', (menuItems) => { - const menu = Menu.buildFromTemplate(menuItems); - - addMenuItemClickConnector(menu.items, (id) => { - socket.emit("menuItemClicked", id); - }); - - Menu.setApplicationMenu(menu); - }); - - socket.on('createNotification', (options) => { - const notification = new Notification(options); - notification.show(); - }); - - }); -} - -function addMenuItemClickConnector(menuItems, callback) { - menuItems.forEach((item) => { - if(item.submenu && item.submenu.items.length > 0) { - addMenuItemClickConnector(item.submenu.items, callback); - } - - if("id" in item && item.id) { - item.click = () => { callback(item.id); }; - } + menu = require('./api/menu')(socket); + dialog = require('./api/dialog')(socket); + notification = require('./api/notification')(socket); + tray = require('./api/tray')(socket); }); } diff --git a/ElectronNET.WebApp/Assets/electron.ico b/ElectronNET.WebApp/Assets/electron.ico new file mode 100644 index 0000000000000000000000000000000000000000..3a104492d2e1a089e2e03b0eba36a53c94ccd009 GIT binary patch literal 279958 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

$l2Jy*;pUMHU)8=jPxN2sA%J;QIHUT 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 literal 0 HcmV?d00001 diff --git a/ElectronNET.WebApp/Assets/electron_32x32.png b/ElectronNET.WebApp/Assets/electron_32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..125dde6e575ca5da10d077cbd7b6bd394dc0b053 GIT binary patch literal 1281 zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4rT@h2A3sW#~2uxrU&?hxau1@=@~j27(445 zJ8NoKXsDZOX<2zE6!@o?Y3tY+n79OFlvl0UU9oaUaBi)#yuP8Co2s&LLeqrY=}Y43 zdS*R%>);osXXL17;HYQdkTr2Z_LRl$k(u4cui1J=YH3@mshAj=x*D0e>FC<(=-H_% z8A-N@fJ?s&kt)XFI?HU?i-yh#Fp?vw~xVql* z72D$K`*aN)G&L=Y7pyN`vf0r;-qgm&%+}Y^IoLHktzqktoT*C!GRjI8t<%+aa0*N; zoVT`O#SU#Lj>UFynWpq>&4bANQ%9d`a-+U-Avr=8v)Wq7mZu0?oNzKwFn?eif zRF#Yq8vE2#OpVOlqbk}v4_^u^Y%nl&tysC;B_u^h*G@ytJffsIy?2&@sf&S$v%0ET zPQGZQF|zPz-Fwp5(ldY7N?koWZEb5^efy-=De?7v z&AX0Sxdb}}B~`E8o8C9KYR#UeohM>zx>LJm$_T4uPhOlgX`xqqUi0o#*6v~bXYb6o z^E$SsC!uMgg+oBYwxi8Ek2(g#N0zlI$?7IFPl|8oH@5WfNh~Osvr17$H@$aG=EMcz z#ZBsJW-5wCG1cvLoA(yYTWjwVt)gI1x_F~UbXI6Vy_IW-v4uzFs+~TGg{^zf46Sf63yF=JtNgyN`Rt<+kiOZeZ-<7Lji06x6u=SZHB`rE^eBO?Tg^OWyH$ zjoS|gW>wW~KI9gWp`mUOlvPo^W`}P|ap~esm8*8-&0G;t($cW?kb6|7wOeRH;{+S` zFbDrQ6Du#5kmSxIm)j1U4@fT$%&h1*bTP4cQe0hM`+@V3Wvy1Op-HV%Q#xn3S37TD zU|>@9ba4!+xV3lE^>ATFiKENktb51dwP9Uu`5jq9CaD~i1f7j;od;b_gsR^+O*o?W zt?!1kR>Hxiz2R^6e*bn{B7W0s;io4b*UsL#-}3&>a=Q=fSp}Ikn8_F0v~3WJUlAOx zQqRs2udlbSuDQit=!1EJXU>fkg~EL%tOm!_R?KW+%(=HHb@eqP2Nfw!d6B+tfu?6R zZ}WU>aVqlg^fdXdx08c|tV>e1ZSkACyX5V(IqPnoWhqNZDJ%c>V&&IUZ{B*ny1YI9 zKO^(q0|JlOdCyI1Oz$wS)<~&3XQ1?iPky1W^1S?%qfu_v$0z4L=pSlu@* zSn0r(%**L#MADZ2&~15C5OF=nZ>F*Ndte?5|y6QN*J($q3=_j{D+zt=Za2>t4 zO;?%?E=&_up0dB@=&8`vl8tN)KTNZ)e-v@}{foD5LC&2mJ6*co8Esi=QvKS@X^Ycx zx7yp~C#+Rd)*alI{e9k?M|&%snnV~{-rmk_3SaYDE2sjBEyE!7bFnwI76 z{j9uBtE}SYEnK)pSlvHVdsj^9ubxL%v#az3Bo{85yT9P$q?(^y6Y8#3zpeVpyY#`c zwYQfV^|c7RyK<-W{_g(=jbP0l+XkKRa7vc literal 0 HcmV?d00001 diff --git a/ElectronNET.WebApp/Controllers/HomeController.cs b/ElectronNET.WebApp/Controllers/HomeController.cs index 3dea985..5f2146c 100644 --- a/ElectronNET.WebApp/Controllers/HomeController.cs +++ b/ElectronNET.WebApp/Controllers/HomeController.cs @@ -10,11 +10,7 @@ namespace ElectronNET.WebApp.Controllers public IActionResult Index() { Electron.IpcMain.On("SayHello", (args) => { - Electron.App.CreateNotification(new NotificationOptions - { - Title = "Hallo Robert", - Body = "Nachricht von ASP.NET Core App" - }); + Electron.Notification.Show(new NotificationOptions("Hallo Robert","Nachricht von ASP.NET Core App")); Electron.IpcMain.Send("Goodbye", "Elephant!"); }); diff --git a/ElectronNET.WebApp/ElectronNET.WebApp.csproj b/ElectronNET.WebApp/ElectronNET.WebApp.csproj index 33d154c..afa9da2 100644 --- a/ElectronNET.WebApp/ElectronNET.WebApp.csproj +++ b/ElectronNET.WebApp/ElectronNET.WebApp.csproj @@ -6,6 +6,7 @@ + @@ -24,4 +25,13 @@ + + + + PreserveNewest + + + PreserveNewest + + diff --git a/ElectronNET.WebApp/Startup.cs b/ElectronNET.WebApp/Startup.cs index a1648ec..8ad87aa 100644 --- a/ElectronNET.WebApp/Startup.cs +++ b/ElectronNET.WebApp/Startup.cs @@ -45,20 +45,40 @@ namespace ElectronNET.WebApp { Electron.Menu.SetApplicationMenu(new MenuItem[] { new MenuItem { - Label = "Datei", + Label = "File", Submenu = new MenuItem[] { new MenuItem { - Label = "Beenden", + Label = "Exit", Click = () => { Electron.App.Exit(); } } } + }, + new MenuItem + { + Label = "About", + Click = async () => { + await Electron.Dialog.ShowMessageBoxAsync(new MessageBoxOptions("(c) 2017 Gregor Biswanger & Robert Muehsig") { + Title = "About us...", + Type = "info" + }); + } } }); var browserWindow = await Electron.WindowManager.CreateWindowAsync(); + + Electron.Tray.Show("/Assets/electron_32x32.png", new MenuItem[] { + new MenuItem { + Label = "Exit", + Click = () => + { + Electron.App.Exit(); + } + } + }); } } } diff --git a/ElectronNET.WebApp/Views/Home/Index.cshtml b/ElectronNET.WebApp/Views/Home/Index.cshtml index 22197ef..75b5ee5 100644 --- a/ElectronNET.WebApp/Views/Home/Index.cshtml +++ b/ElectronNET.WebApp/Views/Home/Index.cshtml @@ -3,7 +3,6 @@ - Home

Hello from ASP.NET Core MVC!