diff --git a/.devops/build-nuget.yaml b/.devops/build-nuget.yaml index d28e7267..b5591865 100644 --- a/.devops/build-nuget.yaml +++ b/.devops/build-nuget.yaml @@ -1,5 +1,5 @@ variables: - PackageVersion: 13.5.1.$(Build.BuildId) + PackageVersion: 19.0.9.$(Build.BuildId) projectAPI: './ElectronNET.API/ElectronNET.API.csproj' projectCLI: './ElectronNET.CLI/ElectronNET.CLI.csproj' @@ -20,7 +20,7 @@ steps: displayName: 'Use .NET Core sdk' inputs: packageType: sdk - version: 5.0.203 + version: 6.0.100 installationPath: $(Agent.ToolsDirectory)/dotnet - task: DotNetCoreCLI@2 @@ -55,6 +55,7 @@ steps: configuration: 'Release' versioningScheme: 'off' buildProperties: 'Version=$(PackageVersion)' + arguments: -IncludeReferencedProjects - task: DotNetCoreCLI@2 inputs: diff --git a/ElectronNET.API/App.cs b/ElectronNET.API/App.cs index 274786c5..4aa0568d 100644 --- a/ElectronNET.API/App.cs +++ b/ElectronNET.API/App.cs @@ -7,6 +7,11 @@ using System.Threading; using System.Threading.Tasks; using ElectronNET.API.Extensions; +using System.Runtime.Versioning; + +//TODO: Implement app.showEmojiPanel and app.isEmojiPanelSupported: https://www.electronjs.org/docs/api/app#appshowemojipanel-macos-windows +//TODO: Implement app.moveToApplicationsFolder: https://www.electronjs.org/docs/api/app#appmovetoapplicationsfolderoptions-macos +//TODO: Implement apprunningUnderRosettaTranslation: https://www.electronjs.org/docs/api/app#apprunningunderrosettatranslation-macos-readonly namespace ElectronNET.API { @@ -20,6 +25,90 @@ public sealed class App /// public static bool SocketDebug { get; set; } + /// + /// Handle hard fails of connecting to the socket. The application must exit when this event is raised. + /// The default behavior is to exit with code 0xDEAD + /// + public static event Action OnSocketConnectFail; + + internal static bool TryRaiseOnSocketConnectFail() + { + if (OnSocketConnectFail is object) + { + OnSocketConnectFail(); + return true; + } + else + { + return false; + } + } + + /// + /// Emitted when the user clicks on the dock on Mac + /// + /// + [SupportedOSPlatform("macos")] + public event Action Activate + { + add + { + if (_appActivate == null) + { + BridgeConnector.On("app-activate", () => + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + _appActivate(); + } + }); + } + _appActivate += value; + } + remove + { + _appActivate -= value; + + if (_appActivate == null) + { + BridgeConnector.Off("app-activate"); + } + } + } + + private event Action _appActivate; + + /// + /// Emitted on the first instance when the user opens a second instance of the app, and the app is single instance + /// + /// + public event Action ActivateFromSecondInstance + { + add + { + if (_appActivateFromSecondInstance == null) + { + BridgeConnector.On("app-activate-from-second-instance", (args) => + { + _appActivateFromSecondInstance(args); + }); + } + _appActivateFromSecondInstance += value; + } + remove + { + _appActivateFromSecondInstance -= value; + + if (_appActivateFromSecondInstance == null) + { + BridgeConnector.Off("app-activate-from-second-instance"); + } + } + } + + private event Action _appActivateFromSecondInstance; + + /// /// Emitted when all windows have been closed. /// @@ -337,6 +426,8 @@ public event Action WebContentsCreated /// screen readers, are enabled or disabled. See https://www.chromium.org/developers/design-documents/accessibility for more details. /// /// when Chrome's accessibility support is enabled, otherwise. + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public event Action AccessibilitySupportChanged { add @@ -411,6 +502,7 @@ internal set /// /// On Windows, you have to parse the arguments using App.CommandLine to get the filepath. /// + [SupportedOSPlatform("macos")] public event Action OpenFile { add @@ -439,8 +531,7 @@ public event Action OpenFile /// - /// Emitted when a MacOS user wants to open a URL with the application. Your application's Info.plist file must - /// define the URL scheme within the CFBundleURLTypes key, and set NSPrincipalClass to AtomApplication. + /// Emitted when a user wants to open a URL with the application. See https://www.electronjs.org/docs/latest/tutorial/launch-app-from-url-in-another-app for more information. /// public event Action OpenUrl { @@ -495,9 +586,13 @@ public string Name public Task GetNameAsync() => BridgeConnector.OnResult("appGetName", "appGetNameCompleted"); - internal App() + private App() { - CommandLine = new CommandLine(); + if (OperatingSystem.IsMacOS() || OperatingSystem.IsLinux()) + { + AppContext.SetSwitch("System.Drawing.EnableUnixSupport", true); + } + CommandLine = CommandLine.Instance; } internal static App Instance @@ -528,7 +623,7 @@ public static void ManuallySetIsReady() } private static App _app; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); /// /// Try to close all windows. The event will be emitted first. If all windows are successfully @@ -599,6 +694,7 @@ public void Focus() /// /// You should seek to use the option as sparingly as possible. /// + [SupportedOSPlatform("macos")] public void Focus(FocusOptions focusOptions) { BridgeConnector.Emit("appFocus", JObject.FromObject(focusOptions, _jsonSerializer)); @@ -607,6 +703,7 @@ public void Focus(FocusOptions focusOptions) /// /// Hides all application windows without minimizing them. /// + [SupportedOSPlatform("macos")] public void Hide() { BridgeConnector.Emit("appHide"); @@ -615,6 +712,7 @@ public void Hide() /// /// Shows application windows after they were hidden. Does not automatically focus them. /// + [SupportedOSPlatform("macos")] public void Show() { BridgeConnector.Emit("appShow"); @@ -688,6 +786,8 @@ public void SetPath(PathName name, string path) /// list from the task bar, and on macOS you can visit it from dock menu. /// /// Path to add. + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public void AddRecentDocument(string path) { BridgeConnector.Emit("appAddRecentDocument", path); @@ -696,6 +796,8 @@ public void AddRecentDocument(string path) /// /// Clears the recent documents list. /// + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public void ClearRecentDocuments() { BridgeConnector.Emit("appClearRecentDocuments"); @@ -726,6 +828,8 @@ public void ClearRecentDocuments() /// call this method with electron as the parameter. /// The cancellation token. /// Whether the call succeeded. + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public async Task SetAsDefaultProtocolClientAsync(string protocol, CancellationToken cancellationToken = default) { return await SetAsDefaultProtocolClientAsync(protocol, null, null, cancellationToken); @@ -757,6 +861,8 @@ public async Task SetAsDefaultProtocolClientAsync(string protocol, Cancell /// The path to the Electron executable. Defaults to process.execPath /// The cancellation token. /// Whether the call succeeded. + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public async Task SetAsDefaultProtocolClientAsync(string protocol, string path, CancellationToken cancellationToken = default) { return await SetAsDefaultProtocolClientAsync(protocol, path, null, cancellationToken); @@ -789,6 +895,8 @@ public async Task SetAsDefaultProtocolClientAsync(string protocol, string /// Arguments passed to the executable. Defaults to an empty array. /// The cancellation token. /// Whether the call succeeded. + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public Task SetAsDefaultProtocolClientAsync(string protocol, string path, string[] args, CancellationToken cancellationToken = default) => BridgeConnector.OnResult("appSetAsDefaultProtocolClient", "appSetAsDefaultProtocolClientCompleted", cancellationToken, protocol, path, args); /// @@ -798,6 +906,8 @@ public async Task SetAsDefaultProtocolClientAsync(string protocol, string /// The name of your protocol, without ://. /// The cancellation token. /// Whether the call succeeded. + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public async Task RemoveAsDefaultProtocolClientAsync(string protocol, CancellationToken cancellationToken = default) { return await RemoveAsDefaultProtocolClientAsync(protocol, null, null, cancellationToken); @@ -811,6 +921,8 @@ public async Task RemoveAsDefaultProtocolClientAsync(string protocol, Canc /// Defaults to process.execPath. /// The cancellation token. /// Whether the call succeeded. + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public async Task RemoveAsDefaultProtocolClientAsync(string protocol, string path, CancellationToken cancellationToken = default) { return await RemoveAsDefaultProtocolClientAsync(protocol, path, null, cancellationToken); @@ -825,6 +937,8 @@ public async Task RemoveAsDefaultProtocolClientAsync(string protocol, stri /// Defaults to an empty array. /// The cancellation token. /// Whether the call succeeded. + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public Task RemoveAsDefaultProtocolClientAsync(string protocol, string path, string[] args, CancellationToken cancellationToken = default) => BridgeConnector.OnResult("appRemoveAsDefaultProtocolClient", "appRemoveAsDefaultProtocolClientCompleted", cancellationToken, protocol, path, args); @@ -841,6 +955,8 @@ public async Task RemoveAsDefaultProtocolClientAsync(string protocol, stri /// The name of your protocol, without ://. /// The cancellation token. /// Whether the current executable is the default handler for a protocol (aka URI scheme). + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public async Task IsDefaultProtocolClientAsync(string protocol, CancellationToken cancellationToken = default) { return await IsDefaultProtocolClientAsync(protocol, null, null, cancellationToken); @@ -860,6 +976,8 @@ public async Task IsDefaultProtocolClientAsync(string protocol, Cancellati /// Defaults to process.execPath. /// The cancellation token. /// Whether the current executable is the default handler for a protocol (aka URI scheme). + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public async Task IsDefaultProtocolClientAsync(string protocol, string path, CancellationToken cancellationToken = default) { return await IsDefaultProtocolClientAsync(protocol, path, null, cancellationToken); @@ -880,6 +998,8 @@ public async Task IsDefaultProtocolClientAsync(string protocol, string pat /// Defaults to an empty array. /// The cancellation token. /// Whether the current executable is the default handler for a protocol (aka URI scheme). + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public Task IsDefaultProtocolClientAsync(string protocol, string path, string[] args, CancellationToken cancellationToken = default) => BridgeConnector.OnResult("appIsDefaultProtocolClient", "appIsDefaultProtocolClientCompleted", cancellationToken, protocol, path, args); @@ -891,6 +1011,7 @@ public async Task IsDefaultProtocolClientAsync(string protocol, string pat /// Array of objects. /// The cancellation token. /// Whether the call succeeded. + [SupportedOSPlatform("windows")] public Task SetUserTasksAsync(UserTask[] userTasks, CancellationToken cancellationToken = default) => BridgeConnector.OnResult("appSetUserTasks", "appSetUserTasksCompleted", cancellationToken, JArray.FromObject(userTasks, _jsonSerializer)); /// @@ -898,6 +1019,7 @@ public async Task IsDefaultProtocolClientAsync(string protocol, string pat /// /// The cancellation token. /// Jump List settings. + [SupportedOSPlatform("windows")] public Task GetJumpListSettingsAsync(CancellationToken cancellationToken = default) => BridgeConnector.OnResult("appGetJumpListSettings", "appGetJumpListSettingsCompleted", cancellationToken); /// @@ -916,6 +1038,7 @@ public async Task IsDefaultProtocolClientAsync(string protocol, string pat /// omitted from the Jump List. The list of removed items can be obtained using . /// /// Array of objects. + [SupportedOSPlatform("windows")] public void SetJumpList(JumpListCategory[] categories) { BridgeConnector.Emit("appSetJumpList", JArray.FromObject(categories, _jsonSerializer)); @@ -991,6 +1114,7 @@ public void ReleaseSingleInstanceLock() /// /// Uniquely identifies the activity. Maps to NSUserActivity.activityType. /// App-specific state to store for use by another device. + [SupportedOSPlatform("macos")] public void SetUserActivity(string type, object userInfo) { SetUserActivity(type, userInfo, null); @@ -1008,6 +1132,7 @@ public void SetUserActivity(string type, object userInfo) /// /// The webpage to load in a browser if no suitable app is installed on the resuming device. The scheme must be http or https. /// + [SupportedOSPlatform("macos")] public void SetUserActivity(string type, object userInfo, string webpageUrl) { BridgeConnector.Emit("appSetUserActivity", type, userInfo, webpageUrl); @@ -1017,12 +1142,14 @@ public void SetUserActivity(string type, object userInfo, string webpageUrl) /// The type of the currently running activity. /// /// The cancellation token. + [SupportedOSPlatform("macos")] public Task GetCurrentActivityTypeAsync(CancellationToken cancellationToken = default) => BridgeConnector.OnResult("appGetCurrentActivityType", "appGetCurrentActivityTypeCompleted", cancellationToken); /// /// Invalidates the current Handoff user activity. /// + [SupportedOSPlatform("macos")] public void InvalidateCurrentActivity() { BridgeConnector.Emit("appInvalidateCurrentActivity"); @@ -1031,6 +1158,7 @@ public void InvalidateCurrentActivity() /// /// Marks the current Handoff user activity as inactive without invalidating it. /// + [SupportedOSPlatform("macos")] public void ResignCurrentActivity() { BridgeConnector.Emit("appResignCurrentActivity"); @@ -1040,6 +1168,7 @@ public void ResignCurrentActivity() /// Changes the Application User Model ID to id. /// /// Model Id. + [SupportedOSPlatform("windows")] public void SetAppUserModelId(string id) { BridgeConnector.Emit("appSetAppUserModelId", id); @@ -1054,6 +1183,7 @@ public void SetAppUserModelId(string id) /// /// The cancellation token. /// Result of import. Value of 0 indicates success. + [SupportedOSPlatform("linux")] public Task ImportCertificateAsync(ImportCertificateOptions options, CancellationToken cancellationToken = default) => BridgeConnector.OnResult("appImportCertificate", "appImportCertificateCompleted", cancellationToken, JObject.FromObject(options, _jsonSerializer)); /// @@ -1084,12 +1214,16 @@ public void SetAppUserModelId(string id) /// Counter badge. /// The cancellation token. /// Whether the call succeeded. + [SupportedOSPlatform("linux")] + [SupportedOSPlatform("macos")] public Task SetBadgeCountAsync(int count, CancellationToken cancellationToken = default) => BridgeConnector.OnResult("appSetBadgeCount", "appSetBadgeCountCompleted", cancellationToken, count); /// /// The current value displayed in the counter badge. /// /// The cancellation token. + [SupportedOSPlatform("linux")] + [SupportedOSPlatform("macos")] public Task GetBadgeCountAsync(CancellationToken cancellationToken = default) => BridgeConnector.OnResult("appGetBadgeCount", "appGetBadgeCountCompleted", cancellationToken); /// @@ -1101,12 +1235,15 @@ public void SetAppUserModelId(string id) /// Whether the current desktop environment is Unity launcher. /// /// The cancellation token. + [SupportedOSPlatform("linux")] public Task IsUnityRunningAsync(CancellationToken cancellationToken = default) => BridgeConnector.OnResult("appIsUnityRunning", "appIsUnityRunningCompleted", cancellationToken); /// /// If you provided path and args options to then you need to pass the same /// arguments here for to be set correctly. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public async Task GetLoginItemSettingsAsync(CancellationToken cancellationToken = default) { return await GetLoginItemSettingsAsync(null, cancellationToken); @@ -1118,6 +1255,8 @@ public async Task GetLoginItemSettingsAsync(CancellationToken /// /// /// The cancellation token. + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public Task GetLoginItemSettingsAsync(LoginItemSettingsOptions options, CancellationToken cancellationToken = default) => options is null ? BridgeConnector.OnResult("appGetLoginItemSettings", "appGetLoginItemSettingsCompleted", cancellationToken) : BridgeConnector.OnResult("appGetLoginItemSettings", "appGetLoginItemSettingsCompleted", cancellationToken, JObject.FromObject(options, _jsonSerializer)); @@ -1128,6 +1267,8 @@ public Task GetLoginItemSettingsAsync(LoginItemSettingsOption /// you'll want to set the launch path to Update.exe, and pass arguments that specify your application name. /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public void SetLoginItemSettings(LoginSettings loginSettings) { BridgeConnector.Emit("appSetLoginItemSettings", JObject.FromObject(loginSettings, _jsonSerializer)); @@ -1139,6 +1280,8 @@ public void SetLoginItemSettings(LoginSettings loginSettings) /// See Chromium's accessibility docs for more details. /// /// if Chrome’s accessibility support is enabled, otherwise. + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public Task IsAccessibilitySupportEnabledAsync(CancellationToken cancellationToken = default) => BridgeConnector.OnResult("appIsAccessibilitySupportEnabled", "appIsAccessibilitySupportEnabledCompleted", cancellationToken); @@ -1152,6 +1295,8 @@ public void SetLoginItemSettings(LoginSettings loginSettings) /// Note: Rendering accessibility tree can significantly affect the performance of your app. It should not be enabled by default. /// /// Enable or disable accessibility tree rendering. + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public void SetAccessibilitySupportEnabled(bool enabled) { BridgeConnector.Emit("appSetAboutPanelOptions", enabled); @@ -1182,6 +1327,13 @@ public void SetAboutPanelOptions(AboutPanelOptions options) BridgeConnector.Emit("appSetAboutPanelOptions", JObject.FromObject(options, _jsonSerializer)); } + /// + /// Fetches a path's associated icon. + /// + /// + /// + public Task GetFileIcon(string path) => BridgeConnector.OnResult("appGetFileIcon", "appGetFileIconCompleted", path); + /// /// A which is the user agent string Electron will use as a global fallback. /// @@ -1244,7 +1396,14 @@ internal void PreventQuit() /// The handler public void Once(string eventName, Action fn) => Events.Instance.Once(ModuleName, eventName, fn); - private readonly JsonSerializer _jsonSerializer = new JsonSerializer() + + /// + /// If you're using a splashscreen in the electron.manifest.json, the window will ony be fully destroyed once you call this method once. + /// You should only do this after creating another window, to avoid a bug where the Electron renderer process frezees till any window interaction. + /// + public void DestroySplashScreen() => BridgeConnector.Emit("splashscreen-destroy"); + + private readonly JsonSerializer _jsonSerializer = new() { ContractResolver = new CamelCasePropertyNamesContractResolver() }; diff --git a/ElectronNET.API/AutoUpdater.cs b/ElectronNET.API/AutoUpdater.cs index d21ed041..2053d8d0 100644 --- a/ElectronNET.API/AutoUpdater.cs +++ b/ElectronNET.API/AutoUpdater.cs @@ -313,7 +313,7 @@ public event Action OnUpdateDownloaded private event Action _updateDownloaded; private static AutoUpdater _autoUpdater; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal AutoUpdater() { } @@ -426,6 +426,7 @@ public Task CheckForUpdatesAndNotifyAsync() /// Run the app after finish even on silent install. Not applicable for macOS. Ignored if `isSilent` is set to `false`. public void QuitAndInstall(bool isSilent = false, bool isForceRunAfter = false) { + BridgeConnector.EmitSync("prepare-for-update"); BridgeConnector.EmitSync("autoUpdaterQuitAndInstall", isSilent, isForceRunAfter); } diff --git a/ElectronNET.API/BridgeConnector.cs b/ElectronNET.API/BridgeConnector.cs index 1088f9e1..66df3cde 100644 --- a/ElectronNET.API/BridgeConnector.cs +++ b/ElectronNET.API/BridgeConnector.cs @@ -4,8 +4,10 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; using Newtonsoft.Json.Serialization; +using Nito.AsyncEx; using SocketIOClient; using SocketIOClient.JsonSerializer; using SocketIOClient.Newtonsoft.Json; @@ -85,26 +87,63 @@ internal static void DoneWith(string key, string eventKey, TaskCompletionSource< private static SocketIO _socket; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); + + private static readonly SemaphoreSlim _socketSemaphoreEmit = new(1, 1); + private static readonly SemaphoreSlim _socketSemaphoreHandlers = new(1, 1); + + private static AsyncManualResetEvent _connectedSocketEvent = new AsyncManualResetEvent(); + + private static Dictionary> _eventHandlers = new (); + + private static Task _waitForConnection + { + get + { + EnsureSocketTaskIsCreated(); + return GetSocket(); + } + } + + private static async Task GetSocket() + { + await _connectedSocketEvent.WaitAsync(); + return _socket; + } + + public static bool IsConnected => _waitForConnection is Task task && task.IsCompletedSuccessfully; public static void Emit(string eventString, params object[] args) { //We don't care about waiting for the event to be emitted, so this doesn't need to be async + + Task.Run(() => EmitAsync(eventString, args)); + } - Task.Run(async () => + private static async Task EmitAsync(string eventString, object[] args) + { + if (App.SocketDebug) { - if (App.SocketDebug) - { - Console.WriteLine($"Sending event {eventString}"); - } + Log("Sending event {0}", eventString); + } - await Socket.EmitAsync(eventString, args); + var socket = await _waitForConnection; - if (App.SocketDebug) - { - Console.WriteLine($"Sent event {eventString}"); - } - }); + await _socketSemaphoreEmit.WaitAsync(); + + try + { + await socket.EmitAsync(eventString, args); + } + finally + { + _socketSemaphoreEmit.Release(); + } + + if (App.SocketDebug) + { + Log($"Sent event {eventString}"); + } } /// @@ -116,30 +155,128 @@ internal static void EmitSync(string eventString, params object[] args) { if (App.SocketDebug) { - Console.WriteLine($"Sending event {eventString}"); + Log("Sending event {0}", eventString); } - Socket.EmitAsync(eventString, args).Wait(); + Task.Run(async () => + { + var socket = await _waitForConnection; + try + { + await _socketSemaphoreEmit.WaitAsync(); + await socket.EmitAsync(eventString, args); + } + finally + { + _socketSemaphoreEmit.Release(); + } + }).Wait(); + if (App.SocketDebug) { - Console.WriteLine($"Sent event {eventString}"); + Log("Sent event {0}", eventString); } } public static void Off(string eventString) { - Socket.Off(eventString); + EnsureSocketTaskIsCreated(); + + _socketSemaphoreHandlers.Wait(); + try + { + if (_eventHandlers.ContainsKey(eventString)) + { + _eventHandlers.Remove(eventString); + } + + _socket.Off(eventString); + } + finally + { + _socketSemaphoreHandlers.Release(); + } } public static void On(string eventString, Action fn) { - Socket.On(eventString, _ => fn()); + EnsureSocketTaskIsCreated(); + + _socketSemaphoreHandlers.Wait(); + try + { + if (_eventHandlers.ContainsKey(eventString)) + { + _eventHandlers.Remove(eventString); + } + + _eventHandlers.Add(eventString, _ => + { + try + { + fn(); + } + catch (Exception E) + { + LogError(E, "Error running handler for event {0}", eventString); + } + }); + + _socket.On(eventString, _eventHandlers[eventString]); + } + finally + { + _socketSemaphoreHandlers.Release(); + } } public static void On(string eventString, Action fn) { - Socket.On(eventString, (o) => fn(o.GetValue(0))); + EnsureSocketTaskIsCreated(); + + _socketSemaphoreHandlers.Wait(); + try + { + if (_eventHandlers.ContainsKey(eventString)) + { + _eventHandlers.Remove(eventString); + } + + _eventHandlers.Add(eventString, o => + { + try + { + fn(o.GetValue(0)); + } + catch (Exception E) + { + LogError(E, "Error running handler for event {0}", eventString); + } + }); + + _socket.On(eventString, _eventHandlers[eventString]); + } + finally + { + _socketSemaphoreHandlers.Release(); + } + } + + private static void RehookHandlers(SocketIO newSocket) + { + _socketSemaphoreHandlers.Wait(); + try + { + foreach (var kv in _eventHandlers) + { + newSocket.On(kv.Key, kv.Value); + } + } + finally + { + _socketSemaphoreHandlers.Release(); + } } public static void Once(string eventString, Action fn) @@ -195,7 +332,7 @@ public static async Task OnResult(string triggerEvent, string completedEve EventTasks.DoneWith(completedEvent, eventKey, taskCompletionSource); }); - Emit(triggerEvent, args); + await EmitAsync(triggerEvent, args); } } @@ -256,61 +393,160 @@ public static async Task OnResult(string triggerEvent, string completedEve return await taskCompletionSource.Task; } - private static SocketIO Socket + + internal static void Log(string formatString, params object[] args) { - get + if (Logger is object) { - if (_socket is null) + Logger.LogInformation(formatString, args); + } + else + { + Console.WriteLine(formatString, args); + } + } + + internal static void LogError(Exception E, string formatString, params object[] args) + { + if (Logger is object) + { + Logger.LogError(E, formatString, args); + } + else + { + Console.WriteLine(formatString, args); + Console.WriteLine(E.ToString()); + } + } + + private static Thread _backgroundMonitorThread; + + private static void EnsureSocketTaskIsCreated() + { + if (_socket is null) + { + if(string.IsNullOrWhiteSpace(AuthKey)) { - if (HybridSupport.IsElectronActive) - { + throw new Exception("You must call Electron.ReadAuth() first thing on your main entry point."); + } - lock (_syncRoot) + if (HybridSupport.IsElectronActive) + { + lock (_syncRoot) + { + if (_socket is null) { - if (_socket is null && HybridSupport.IsElectronActive) + if (HybridSupport.IsElectronActive) { var socket = new SocketIO($"http://localhost:{BridgeSettings.SocketPort}", new SocketIOOptions() { - EIO = 3 + EIO = 4, + Reconnection = true, + ReconnectionAttempts = int.MaxValue, + ReconnectionDelay = 500, + ReconnectionDelayMax = 2000, + RandomizationFactor = 0.5, + ConnectionTimeout = TimeSpan.FromSeconds(10), + Transport = SocketIOClient.Transport.TransportProtocol.WebSocket }); - socket.JsonSerializer = new CamelCaseNewtonsoftJsonSerializer(socket.Options.EIO); + socket.JsonSerializer = new CamelCaseNewtonsoftJsonSerializer(); + _connectedSocketEvent.Reset(); socket.OnConnected += (_, __) => { - Console.WriteLine("BridgeConnector connected!"); + Task.Run(async () => + { + await socket.EmitAsync("auth", AuthKey); + _connectedSocketEvent.Set(); + Log("ElectronNET socket {1} connected on port {0}!", BridgeSettings.SocketPort, socket.Id); + }); + }; + + socket.OnReconnectAttempt += (_, __) => + { + _connectedSocketEvent.Reset(); + Log("ElectronNET socket {1} is trying to reconnect on port {0}...", BridgeSettings.SocketPort, socket.Id); + }; + + socket.OnReconnectError += (_, ex) => + { + _connectedSocketEvent.Reset(); + Log("ElectronNET socket {1} failed to connect {0}", ex, socket.Id); + }; + + + socket.OnReconnectFailed += (_, ex) => + { + _connectedSocketEvent.Reset(); + Log("ElectronNET socket {1} failed to reconnect {0}", ex, socket.Id); }; - socket.ConnectAsync().Wait(); + socket.OnReconnected += (_, __) => + { + _connectedSocketEvent.Set(); + Log("ElectronNET socket {1} reconnected on port {0}...", BridgeSettings.SocketPort, socket.Id); + }; + + socket.OnDisconnected += (_, reason) => + { + _connectedSocketEvent.Reset(); + Log("ElectronNET socket {2} disconnected with reason {0}, trying to reconnect on port {1}!", reason, BridgeSettings.SocketPort, socket.Id); + }; + + socket.OnError += (_, msg) => + { + //_connectedSocketEvent.Reset(); + Log("ElectronNET socket {1} error: {0}...", msg, socket.Id); + }; _socket = socket; + + Task.Run(async () => + { + try + { + await socket.ConnectAsync(); + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + + if (!App.TryRaiseOnSocketConnectFail()) + { + Environment.Exit(0xDEAD); + } + } + }); + + RehookHandlers(socket); + } + else + { + throw new Exception("Missing Socket Port"); } } } - else - { - throw new Exception("Missing Socket Port"); - } } - - return _socket; + else + { + throw new Exception("Missing Socket Port"); + } } } + internal static ILogger Logger { private get; set; } + internal static string AuthKey { get; set; } = null; + private class CamelCaseNewtonsoftJsonSerializer : NewtonsoftJsonSerializer { - public CamelCaseNewtonsoftJsonSerializer(int eio) : base(eio) - { - } - - public override JsonSerializerSettings CreateOptions() + public CamelCaseNewtonsoftJsonSerializer() : base() { - return new JsonSerializerSettings() + OptionsProvider = () => new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver(), NullValueHandling = NullValueHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore }; } } diff --git a/ElectronNET.API/BrowserView.cs b/ElectronNET.API/BrowserView.cs index 09a44cbd..cd29dfe3 100644 --- a/ElectronNET.API/BrowserView.cs +++ b/ElectronNET.API/BrowserView.cs @@ -33,6 +33,10 @@ public class BrowserView /// public Task GetBoundsAsync() => BridgeConnector.OnResult("browserView-getBounds", "browserView-getBounds-reply" + Id, Id); + /// + /// Set the bounds of the current view inside the window + /// + /// public void SetBounds(Rectangle value) { BridgeConnector.Emit("browserView-setBounds", Id, value); diff --git a/ElectronNET.API/BrowserWindow.cs b/ElectronNET.API/BrowserWindow.cs index 0b8222c5..a39e26bd 100644 --- a/ElectronNET.API/BrowserWindow.cs +++ b/ElectronNET.API/BrowserWindow.cs @@ -7,8 +7,11 @@ using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; +using System.Runtime.Versioning; using System.Threading.Tasks; +//TODO: Add setTrafficLightPosition and getTrafficLightPosition: https://www.electronjs.org/docs/api/browser-window#winsettrafficlightpositionposition-macos + namespace ElectronNET.API { /// @@ -146,6 +149,7 @@ public event Action OnClosed /// /// Emitted when window session is going to end due to force shutdown or machine restart or session log off. /// + [SupportedOSPlatform("windows")] public event Action OnSessionEnd { add @@ -465,6 +469,8 @@ public event Action OnRestore /// /// Emitted when the window is being resized. /// + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public event Action OnResize { add @@ -496,6 +502,8 @@ public event Action OnResize /// /// Note: On macOS this event is just an alias of moved. /// + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public event Action OnMove { add @@ -523,8 +531,10 @@ public event Action OnMove private event Action _move; /// - /// macOS: Emitted once when the window is moved to a new position. + /// Emitted once when the window is moved to a new position. /// + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public event Action OnMoved { add @@ -676,6 +686,8 @@ public event Action OnLeaveHtmlFullScreen /// and the APPCOMMAND_ prefix is stripped off.e.g.APPCOMMAND_BROWSER_BACKWARD /// is emitted as browser-backward. /// + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public event Action OnAppCommand { add @@ -705,6 +717,7 @@ public event Action OnAppCommand /// /// Emitted when scroll wheel event phase has begun. /// + [SupportedOSPlatform("macos")] public event Action OnScrollTouchBegin { add @@ -734,6 +747,7 @@ public event Action OnScrollTouchBegin /// /// Emitted when scroll wheel event phase has ended. /// + [SupportedOSPlatform("macos")] public event Action OnScrollTouchEnd { add @@ -763,6 +777,7 @@ public event Action OnScrollTouchEnd /// /// Emitted when scroll wheel event phase filed upon reaching the edge of element. /// + [SupportedOSPlatform("macos")] public event Action OnScrollTouchEdge { add @@ -792,6 +807,7 @@ public event Action OnScrollTouchEdge /// /// Emitted on 3-finger swipe. Possible directions are up, right, down, left. /// + [SupportedOSPlatform("macos")] public event Action OnSwipe { add @@ -821,6 +837,7 @@ public event Action OnSwipe /// /// Emitted when the window opens a sheet. /// + [SupportedOSPlatform("macos")] public event Action OnSheetBegin { add @@ -850,6 +867,7 @@ public event Action OnSheetBegin /// /// Emitted when the window has closed a sheet. /// + [SupportedOSPlatform("macos")] public event Action OnSheetEnd { add @@ -879,6 +897,7 @@ public event Action OnSheetEnd /// /// Emitted when the native new tab button is clicked. /// + [SupportedOSPlatform("macos")] public event Action OnNewWindowForTab { add @@ -1056,6 +1075,14 @@ public void SetFullScreen(bool flag) { BridgeConnector.Emit("browserWindowSetFullScreen", Id, flag); } + + /// + /// Sets whether the background color of the window + /// + public void SetBackgroundColor(string color) + { + BridgeConnector.Emit("browserWindowSetBackgroundColor", Id, color); + } /// /// Whether the window is in fullscreen mode. @@ -1066,6 +1093,24 @@ public Task IsFullScreenAsync() return BridgeConnector.OnResult("browserWindowIsFullScreen", "browserWindow-isFullScreen-completed" + Id, Id); } + /// + /// This will make a window maintain an aspect ratio. The extra size allows a developer to have space, + /// specified in pixels, not included within the aspect ratio calculations. This API already takes into + /// account the difference between a window’s size and its content size. + /// + /// Consider a normal window with an HD video player and associated controls.Perhaps there are 15 pixels + /// of controls on the left edge, 25 pixels of controls on the right edge and 50 pixels of controls below + /// the player. In order to maintain a 16:9 aspect ratio (standard aspect ratio for HD @1920x1080) within + /// the player itself we would call this function with arguments of 16/9 and[40, 50]. The second argument + /// doesn’t care where the extra width and height are within the content view–only that they exist. Just + /// sum any extra width and height areas you have within the overall content view. + /// + /// The aspect ratio to maintain for some portion of the content view. + public void SetAspectRatio(int aspectRatio) + { + BridgeConnector.Emit("browserWindowSetAspectRatio", Id, aspectRatio, new Size() { Height = 0, Width = 0 }); + } + /// /// This will make a window maintain an aspect ratio. The extra size allows a developer to have space, /// specified in pixels, not included within the aspect ratio calculations. This API already takes into @@ -1080,17 +1125,22 @@ public Task IsFullScreenAsync() /// /// The aspect ratio to maintain for some portion of the content view. /// The extra size not to be included while maintaining the aspect ratio. + [SupportedOSPlatform("macos")] public void SetAspectRatio(int aspectRatio, Size extraSize) { BridgeConnector.Emit("browserWindowSetAspectRatio", Id, aspectRatio, extraSize); } + + + /// /// Uses Quick Look to preview a file at a given path. /// /// The absolute path to the file to preview with QuickLook. This is important as /// Quick Look uses the file name and file extension on the path to determine the content type of the /// file to open. + [SupportedOSPlatform("macos")] public void PreviewFile(string path) { BridgeConnector.Emit("browserWindowPreviewFile", Id, path); @@ -1104,6 +1154,7 @@ public void PreviewFile(string path) /// file to open. /// The name of the file to display on the Quick Look modal view. This is /// purely visual and does not affect the content type of the file. Defaults to path. + [SupportedOSPlatform("macos")] public void PreviewFile(string path, string displayname) { BridgeConnector.Emit("browserWindowPreviewFile", Id, path, displayname); @@ -1112,6 +1163,7 @@ public void PreviewFile(string path, string displayname) /// /// Closes the currently open Quick Look panel. /// + [SupportedOSPlatform("macos")] public void CloseFilePreview() { BridgeConnector.Emit("browserWindowCloseFilePreview", Id); @@ -1131,6 +1183,7 @@ public void SetBounds(Rectangle bounds) /// /// /// + [SupportedOSPlatform("macos")] public void SetBounds(Rectangle bounds, bool animate) { BridgeConnector.Emit("browserWindowSetBounds", Id, bounds, animate); @@ -1159,6 +1212,7 @@ public void SetContentBounds(Rectangle bounds) /// /// /// + [SupportedOSPlatform("macos")] public void SetContentBounds(Rectangle bounds, bool animate) { BridgeConnector.Emit("browserWindowSetContentBounds", Id, bounds, animate); @@ -1189,6 +1243,7 @@ public void SetSize(int width, int height) /// /// /// + [SupportedOSPlatform("macos")] public void SetSize(int width, int height, bool animate) { BridgeConnector.Emit("browserWindowSetSize", Id, width, height, animate); @@ -1219,6 +1274,7 @@ public void SetContentSize(int width, int height) /// /// /// + [SupportedOSPlatform("macos")] public void SetContentSize(int width, int height, bool animate) { BridgeConnector.Emit("browserWindowSetContentSize", Id, width, height, animate); @@ -1293,6 +1349,8 @@ public Task IsResizableAsync() /// Sets whether the window can be moved by user. On Linux does nothing. /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public void SetMovable(bool movable) { BridgeConnector.Emit("browserWindowSetMovable", Id, movable); @@ -1300,10 +1358,10 @@ public void SetMovable(bool movable) /// /// Whether the window can be moved by user. - /// - /// On Linux always returns true. /// /// On Linux always returns true. + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public Task IsMovableAsync() { return BridgeConnector.OnResult("browserWindowIsMovable", "browserWindow-isMovable-completed" + Id, Id); @@ -1313,6 +1371,8 @@ public Task IsMovableAsync() /// Sets whether the window can be manually minimized by user. On Linux does nothing. /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public void SetMinimizable(bool minimizable) { BridgeConnector.Emit("browserWindowSetMinimizable", Id, minimizable); @@ -1320,10 +1380,10 @@ public void SetMinimizable(bool minimizable) /// /// Whether the window can be manually minimized by user. - /// - /// On Linux always returns true. /// /// On Linux always returns true. + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public Task IsMinimizableAsync() { return BridgeConnector.OnResult("browserWindowIsMinimizable", "browserWindow-isMinimizable-completed" + Id, Id); @@ -1333,6 +1393,8 @@ public Task IsMinimizableAsync() /// Sets whether the window can be manually maximized by user. On Linux does nothing. /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public void SetMaximizable(bool maximizable) { BridgeConnector.Emit("browserWindowSetMaximizable", Id, maximizable); @@ -1340,10 +1402,10 @@ public void SetMaximizable(bool maximizable) /// /// Whether the window can be manually maximized by user. - /// - /// On Linux always returns true. /// /// On Linux always returns true. + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public Task IsMaximizableAsync() { return BridgeConnector.OnResult("browserWindowIsMaximizable", "browserWindow-isMaximizable-completed" + Id, Id); @@ -1371,6 +1433,8 @@ public Task IsFullScreenableAsync() /// Sets whether the window can be manually closed by user. On Linux does nothing. /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public void SetClosable(bool closable) { BridgeConnector.Emit("browserWindowSetClosable", Id, closable); @@ -1378,10 +1442,10 @@ public void SetClosable(bool closable) /// /// Whether the window can be manually closed by user. - /// - /// On Linux always returns true. /// /// On Linux always returns true. + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public Task IsClosableAsync() { return BridgeConnector.OnResult("browserWindowIsClosable", "browserWindow-isClosable-completed" + Id, Id); @@ -1407,6 +1471,8 @@ public void SetAlwaysOnTop(bool flag) /// Values include normal, floating, torn-off-menu, modal-panel, main-menu, /// status, pop-up-menu and screen-saver. The default is floating. /// See the macOS docs + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public void SetAlwaysOnTop(bool flag, OnTopLevel level) { BridgeConnector.Emit("browserWindowSetAlwaysOnTop", Id, flag, level.GetDescription()); @@ -1423,6 +1489,7 @@ public void SetAlwaysOnTop(bool flag, OnTopLevel level) /// See the macOS docs /// The number of layers higher to set this window relative to the given level. /// The default is 0. Note that Apple discourages setting levels higher than 1 above screen-saver. + [SupportedOSPlatform("macos")] public void SetAlwaysOnTop(bool flag, OnTopLevel level, int relativeLevel) { BridgeConnector.Emit("browserWindowSetAlwaysOnTop", Id, flag, level.GetDescription(), relativeLevel); @@ -1456,7 +1523,7 @@ public void SetPosition(int x, int y) // https://github.com/electron/electron/issues/4045 if (isWindows10()) { - x = x - 7; + x -= 7; } BridgeConnector.Emit("browserWindowSetPosition", Id, x, y); @@ -1468,13 +1535,14 @@ public void SetPosition(int x, int y) /// /// /// + [SupportedOSPlatform("macos")] public void SetPosition(int x, int y, bool animate) { // Workaround Windows 10 / Electron Bug // https://github.com/electron/electron/issues/4045 if (isWindows10()) { - x = x - 7; + x -= 7; } BridgeConnector.Emit("browserWindowSetPosition", Id, x, y, animate); @@ -1482,7 +1550,7 @@ public void SetPosition(int x, int y, bool animate) private bool isWindows10() { - return RuntimeInformation.OSDescription.Contains("Windows 10"); + return OperatingSystem.IsWindowsVersionAtLeast(10); } /// @@ -1520,6 +1588,7 @@ public Task GetTitleAsync() /// but you may want to display them beneath a HTML-rendered toolbar. /// /// + [SupportedOSPlatform("macos")] public void SetSheetOffset(float offsetY) { BridgeConnector.Emit("browserWindowSetSheetOffset", Id, offsetY); @@ -1532,6 +1601,7 @@ public void SetSheetOffset(float offsetY) /// /// /// + [SupportedOSPlatform("macos")] public void SetSheetOffset(float offsetY, float offsetX) { BridgeConnector.Emit("browserWindowSetSheetOffset", Id, offsetY, offsetX); @@ -1587,6 +1657,7 @@ public Task GetNativeWindowHandle() /// and the icon of the file will show in window’s title bar. /// /// + [SupportedOSPlatform("macos")] public void SetRepresentedFilename(string filename) { BridgeConnector.Emit("browserWindowSetRepresentedFilename", Id, filename); @@ -1596,6 +1667,7 @@ public void SetRepresentedFilename(string filename) /// The pathname of the file the window represents. /// /// + [SupportedOSPlatform("macos")] public Task GetRepresentedFilenameAsync() { return BridgeConnector.OnResult("browserWindowGetRepresentedFilename", "browserWindow-getRepresentedFilename-completed" + Id, Id); @@ -1606,6 +1678,7 @@ public Task GetRepresentedFilenameAsync() /// and the icon in title bar will become gray when set to true. /// /// + [SupportedOSPlatform("macos")] public void SetDocumentEdited(bool edited) { BridgeConnector.Emit("browserWindowSetDocumentEdited", Id, edited); @@ -1615,6 +1688,7 @@ public void SetDocumentEdited(bool edited) /// Whether the window’s document has been edited. /// /// + [SupportedOSPlatform("macos")] public Task IsDocumentEditedAsync() { return BridgeConnector.OnResult("browserWindowIsDocumentEdited", "browserWindow-isDocumentEdited-completed" + Id, Id); @@ -1672,13 +1746,15 @@ public void Reload() /// The menu items. /// public IReadOnlyCollection MenuItems { get { return _items.AsReadOnly(); } } - private List _items = new List(); + private readonly List _items = new(); /// /// Sets the menu as the window’s menu bar, /// setting it to null will remove the menu bar. /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("linux")] public void SetMenu(MenuItem[] menuItems) { menuItems.AddMenuItemsId(); @@ -1696,6 +1772,8 @@ public void SetMenu(MenuItem[] menuItems) /// /// Remove the window's menu bar. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("linux")] public void RemoveMenu() { BridgeConnector.Emit("browserWindowRemoveMenu", Id); @@ -1729,6 +1807,7 @@ public void SetProgressBar(double progress) /// /// /// + [SupportedOSPlatform("windows")] public void SetProgressBar(double progress, ProgressBarOptions progressBarOptions) { BridgeConnector.Emit("browserWindowSetProgressBar", Id, progress, progressBarOptions); @@ -1738,6 +1817,8 @@ public void SetProgressBar(double progress, ProgressBarOptions progressBarOption /// Sets whether the window should have a shadow. On Windows and Linux does nothing. /// /// + + [SupportedOSPlatform("macos")] public void SetHasShadow(bool hasShadow) { BridgeConnector.Emit("browserWindowSetHasShadow", Id, hasShadow); @@ -1762,7 +1843,7 @@ public Task HasShadowAsync() /// public IReadOnlyCollection ThumbarButtons { get { return _thumbarButtons.AsReadOnly(); } } - private List _thumbarButtons = new List(); + private readonly List _thumbarButtons = new(); /// /// Add a thumbnail toolbar with a specified set of buttons to the thumbnail @@ -1776,6 +1857,7 @@ public Task HasShadowAsync() /// /// /// Whether the buttons were added successfully. + [SupportedOSPlatform("windows")] public Task SetThumbarButtonsAsync(ThumbarButton[] thumbarButtons) { var taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); @@ -1808,6 +1890,7 @@ public Task SetThumbarButtonsAsync(ThumbarButton[] thumbarButtons) /// an empty region: {x: 0, y: 0, width: 0, height: 0}. /// /// + [SupportedOSPlatform("windows")] public void SetThumbnailClip(Rectangle rectangle) { BridgeConnector.Emit("browserWindowSetThumbnailClip", Id, rectangle); @@ -1817,6 +1900,7 @@ public void SetThumbnailClip(Rectangle rectangle) /// Sets the toolTip that is displayed when hovering over the window thumbnail in the taskbar. /// /// + [SupportedOSPlatform("windows")] public void SetThumbnailToolTip(string tooltip) { BridgeConnector.Emit("browserWindowSetThumbnailToolTip", Id, tooltip); @@ -1829,14 +1913,29 @@ public void SetThumbnailToolTip(string tooltip) /// If one of those properties is not set, then neither will be used. /// /// + [SupportedOSPlatform("windows")] public void SetAppDetails(AppDetailsOptions options) { BridgeConnector.Emit("browserWindowSetAppDetails", Id, options); } + /// + ///On a Window with Window Controls Overlay already enabled, this method updates + /// the style of the title bar overlay. It should not be called unless you enabled WCO + /// when creating the window. + /// + /// + [SupportedOSPlatform("win")] + [SupportedOSPlatform("macos")] + public void SetTitleBarOverlay(TitleBarOverlayConfig options) + { + BridgeConnector.Emit("browserWindowSetTitleBarOverlay", Id, options); + } + /// /// Same as webContents.showDefinitionForSelection(). /// + [SupportedOSPlatform("macos")] public void ShowDefinitionForSelection() { BridgeConnector.Emit("browserWindowShowDefinitionForSelection", Id); @@ -1868,6 +1967,8 @@ public Task IsMenuBarAutoHideAsync() /// users can still bring up the menu bar by pressing the single Alt key. /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("linux")] public void SetMenuBarVisibility(bool visible) { BridgeConnector.Emit("browserWindowSetMenuBarVisibility", Id, visible); @@ -1877,6 +1978,8 @@ public void SetMenuBarVisibility(bool visible) /// Whether the menu bar is visible. /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("linux")] public Task IsMenuBarVisibleAsync() { return BridgeConnector.OnResult("browserWindowIsMenuBarVisible", "browserWindow-isMenuBarVisible-completed" + Id, Id); @@ -1923,6 +2026,8 @@ public void SetIgnoreMouseEvents(bool ignore) /// On Windows it calls SetWindowDisplayAffinity with WDA_MONITOR. /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public void SetContentProtection(bool enable) { BridgeConnector.Emit("browserWindowSetContentProtection", Id, enable); @@ -1932,6 +2037,8 @@ public void SetContentProtection(bool enable) /// Changes whether the window can be focused. /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public void SetFocusable(bool focusable) { BridgeConnector.Emit("browserWindowSetFocusable", Id, focusable); @@ -1971,6 +2078,7 @@ public async Task> GetChildWindowsAsync() /// Controls whether to hide cursor when typing. /// /// + [SupportedOSPlatform("macos")] public void SetAutoHideCursor(bool autoHide) { BridgeConnector.Emit("browserWindowSetAutoHideCursor", Id, autoHide); @@ -1983,11 +2091,25 @@ public void SetAutoHideCursor(bool autoHide) /// Can be appearance-based, light, dark, titlebar, selection, /// menu, popover, sidebar, medium-light or ultra-dark. /// See the macOS documentation for more details. + [SupportedOSPlatform("macos")] public void SetVibrancy(Vibrancy type) { BridgeConnector.Emit("browserWindowSetVibrancy", Id, type.GetDescription()); } + /// + /// Adds a vibrancy effect to the browser window. + /// Passing null or an empty string will remove the vibrancy effect on the window. + /// + /// Can be appearance-based, light, dark, titlebar, selection, + /// menu, popover, sidebar, medium-light or ultra-dark. + /// See the macOS documentation for more details. + [SupportedOSPlatform("macos")] + public void ExcludeFromShownWindowsMenu() + { + BridgeConnector.Emit("browserWindowSetExcludedFromShownWindowsMenu", Id); + } + /// /// Render and control web pages. /// @@ -2004,7 +2126,7 @@ public void SetBrowserView(BrowserView browserView) BridgeConnector.Emit("browserWindow-setBrowserView", Id, browserView.Id); } - private static readonly JsonSerializer _jsonSerializer = new JsonSerializer() + private static readonly JsonSerializer _jsonSerializer = new() { ContractResolver = new CamelCasePropertyNamesContractResolver(), NullValueHandling = NullValueHandling.Ignore diff --git a/ElectronNET.API/Clipboard.cs b/ElectronNET.API/Clipboard.cs index b757bb0d..3583c33e 100644 --- a/ElectronNET.API/Clipboard.cs +++ b/ElectronNET.API/Clipboard.cs @@ -2,6 +2,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; +using System.Runtime.Versioning; using System.Threading.Tasks; namespace ElectronNET.API @@ -12,7 +13,7 @@ namespace ElectronNET.API public sealed class Clipboard { private static Clipboard _clipboard; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Clipboard() { } @@ -93,6 +94,8 @@ public void WriteRTF(string text, string type = "") /// be empty strings when the bookmark is unavailable. /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public Task ReadBookmarkAsync() => BridgeConnector.OnResult("clipboard-readBookmark", "clipboard-readBookmark-Completed"); /// @@ -105,6 +108,8 @@ public void WriteRTF(string text, string type = "") /// /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public void WriteBookmark(string title, string url, string type = "") { BridgeConnector.Emit("clipboard-writeBookmark", title, url, type); @@ -116,6 +121,7 @@ public void WriteBookmark(string title, string url, string type = "") /// find pasteboard whenever the application is activated. /// /// + [SupportedOSPlatform("macos")] public Task ReadFindTextAsync() => BridgeConnector.OnResult("clipboard-readFindText", "clipboard-readFindText-Completed"); /// @@ -123,6 +129,7 @@ public void WriteBookmark(string title, string url, string type = "") /// synchronous IPC when called from the renderer process. /// /// + [SupportedOSPlatform("macos")] public void WriteFindText(string text) { BridgeConnector.Emit("clipboard-writeFindText", text); @@ -151,7 +158,7 @@ public void Clear(string type = "") /// public void Write(Data data, string type = "") { - BridgeConnector.Emit("clipboard-write", data, type); + BridgeConnector.Emit("clipboard-write", JObject.FromObject(data, _jsonSerializer), type); } /// @@ -170,5 +177,12 @@ public void WriteImage(NativeImage image, string type = "") { BridgeConnector.Emit("clipboard-writeImage", JsonConvert.SerializeObject(image), type); } + + private static readonly JsonSerializer _jsonSerializer = new() + { + ContractResolver = new CamelCasePropertyNamesContractResolver(), + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore + }; } } \ No newline at end of file diff --git a/ElectronNET.API/CommandLine.cs b/ElectronNET.API/CommandLine.cs index 26a116cd..6aa1e502 100644 --- a/ElectronNET.API/CommandLine.cs +++ b/ElectronNET.API/CommandLine.cs @@ -8,7 +8,7 @@ namespace ElectronNET.API /// public sealed class CommandLine { - internal CommandLine() { } + private CommandLine() { } internal static CommandLine Instance { @@ -31,7 +31,7 @@ internal static CommandLine Instance private static CommandLine _commandLine; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); /// /// Append a switch (with optional value) to Chromium's command line. diff --git a/ElectronNET.API/Cookies.cs b/ElectronNET.API/Cookies.cs index 67f16b0c..f5de8700 100644 --- a/ElectronNET.API/Cookies.cs +++ b/ElectronNET.API/Cookies.cs @@ -71,7 +71,7 @@ public Task GetAsync(CookieFilter filter) taskCompletionSource.SetResult(cookies); }); - BridgeConnector.Emit("webContents-session-cookies-get", Id, filter, guid); + BridgeConnector.Emit("webContents-session-cookies-get", Id, JObject.FromObject(filter, _jsonSerializer), guid); return taskCompletionSource.Task; } @@ -92,7 +92,7 @@ public Task SetAsync(CookieDetails details) taskCompletionSource.SetResult(null); }); - BridgeConnector.Emit("webContents-session-cookies-set", Id, details, guid); + BridgeConnector.Emit("webContents-session-cookies-set", Id, JObject.FromObject(details, _jsonSerializer), guid); return taskCompletionSource.Task; } @@ -138,5 +138,13 @@ public Task FlushStoreAsync() return taskCompletionSource.Task; } + + private static readonly JsonSerializer _jsonSerializer = new() + { + ContractResolver = new CamelCasePropertyNamesContractResolver(), + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore + }; + } } \ No newline at end of file diff --git a/ElectronNET.API/DesktopCapturer.cs b/ElectronNET.API/DesktopCapturer.cs new file mode 100644 index 00000000..358b513d --- /dev/null +++ b/ElectronNET.API/DesktopCapturer.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using ElectronNET.API.Entities; +using Newtonsoft.Json; + +namespace ElectronNET.API +{ + public sealed class DesktopCapturer + { + private static readonly object _syncRoot = new(); + private static DesktopCapturer _desktopCapturer; + + internal DesktopCapturer() { } + + internal static DesktopCapturer Instance + { + get + { + if (_desktopCapturer == null) + { + lock (_syncRoot) + { + if (_desktopCapturer == null) + { + _desktopCapturer = new DesktopCapturer(); + } + } + } + + return _desktopCapturer; + } + } + + public async Task GetSourcesAsync(SourcesOption option) + { + return await BridgeConnector.OnResult("desktop-capturer-get-sources", "desktop-capturer-get-sources-result", option); + } + } +} \ No newline at end of file diff --git a/ElectronNET.API/Dialog.cs b/ElectronNET.API/Dialog.cs index a8ecb824..02d22aa2 100644 --- a/ElectronNET.API/Dialog.cs +++ b/ElectronNET.API/Dialog.cs @@ -4,6 +4,7 @@ using Newtonsoft.Json.Serialization; using System; using System.Collections.Generic; +using System.Runtime.Versioning; using System.Threading.Tasks; using System.Web; @@ -15,7 +16,7 @@ namespace ElectronNET.API public sealed class Dialog { private static Dialog _dialog; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Dialog() { } @@ -158,12 +159,12 @@ public Task ShowMessageBoxAsync(BrowserWindow browserWindow, M }); - if (browserWindow == null) + if (browserWindow is null) { - BridgeConnector.Emit("showMessageBox", messageBoxOptions, guid); + BridgeConnector.Emit("showMessageBox", JObject.FromObject(messageBoxOptions, _jsonSerializer), guid); } else { - BridgeConnector.Emit("showMessageBox", browserWindow , messageBoxOptions, guid); + BridgeConnector.Emit("showMessageBox", JObject.FromObject(messageBoxOptions, _jsonSerializer), JObject.FromObject(messageBoxOptions, _jsonSerializer), guid); } return taskCompletionSource.Task; @@ -191,6 +192,8 @@ public void ShowErrorBox(string title, string content) /// /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public Task ShowCertificateTrustDialogAsync(CertificateTrustDialogOptions options) { return ShowCertificateTrustDialogAsync(null, options); @@ -204,6 +207,8 @@ public Task ShowCertificateTrustDialogAsync(CertificateTrustDialogOptions option /// /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public Task ShowCertificateTrustDialogAsync(BrowserWindow browserWindow, CertificateTrustDialogOptions options) { var taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); @@ -219,5 +224,12 @@ public Task ShowCertificateTrustDialogAsync(BrowserWindow browserWindow, Certifi return taskCompletionSource.Task; } + + private static readonly JsonSerializer _jsonSerializer = new() + { + ContractResolver = new CamelCasePropertyNamesContractResolver(), + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore + }; } } diff --git a/ElectronNET.API/Dock.cs b/ElectronNET.API/Dock.cs index 9c00b2d3..b5ea5d49 100644 --- a/ElectronNET.API/Dock.cs +++ b/ElectronNET.API/Dock.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Runtime.Versioning; using System.Threading; using System.Threading.Tasks; using ElectronNET.API.Entities; @@ -12,10 +13,11 @@ namespace ElectronNET.API /// /// Control your app in the macOS dock. /// + [SupportedOSPlatform("macos")] public sealed class Dock { private static Dock _dock; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Dock() { @@ -130,7 +132,7 @@ public Task IsVisibleAsync(CancellationToken cancellationToken = default) /// The menu items. /// public IReadOnlyCollection MenuItems { get { return _items.AsReadOnly(); } } - private List _items = new List(); + private readonly List _items = new(); /// /// Sets the application's dock menu. @@ -163,7 +165,7 @@ public void SetIcon(string image) BridgeConnector.Emit("dock-setIcon", image); } - private static readonly JsonSerializer _jsonSerializer = new JsonSerializer() + private static readonly JsonSerializer _jsonSerializer = new() { ContractResolver = new CamelCasePropertyNamesContractResolver(), NullValueHandling = NullValueHandling.Ignore diff --git a/ElectronNET.API/Electron.Experimental.cs b/ElectronNET.API/Electron.Experimental.cs new file mode 100644 index 00000000..75d110ee --- /dev/null +++ b/ElectronNET.API/Electron.Experimental.cs @@ -0,0 +1,144 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Net.Sockets; +using System.Net; +using System.Threading.Tasks; +using System.Diagnostics; + +namespace ElectronNET.API +{ + public static partial class Electron + { + /// + /// Experimental code, use with care + /// + public static class Experimental + { + /// + /// Starts electron from C#, use during development to avoid having to fully publish / build your app on every compile cycle + /// You will need to run the CLI at least once (and once per update) to bootstrap all required files + /// + /// + /// + /// + /// + /// + /// + public static async Task StartElectronForDevelopment(int webPort, string projectPath = null, string[] extraElectronArguments = null, bool clearCache = false) + { + string aspCoreProjectPath; + + if (!string.IsNullOrEmpty(projectPath)) + { + if (Directory.Exists(projectPath)) + { + aspCoreProjectPath = projectPath; + } + else + { + throw new DirectoryNotFoundException(projectPath); + } + } + else + { + aspCoreProjectPath = Directory.GetCurrentDirectory(); + } + + string tempPath = Path.Combine(aspCoreProjectPath, "obj", "Host"); + + if (!Directory.Exists(tempPath)) + { + Directory.CreateDirectory(tempPath); + } + + var mainFileJs = Path.Combine(tempPath, "main.js"); + if (!File.Exists(mainFileJs)) + { + throw new Exception("You need to run once the electronize-h5 start command to bootstrap the necessary files"); + } + + var nodeModulesDirPath = Path.Combine(tempPath, "node_modules"); + + bool runNpmInstall = false; + + if (!Directory.Exists(nodeModulesDirPath)) + { + runNpmInstall = true; + } + + var packagesJson = Path.Combine(tempPath, "package.json"); + + var packagesPrevious = Path.Combine(tempPath, "package.json.previous"); + + if (!runNpmInstall) + { + if (File.Exists(packagesPrevious)) + { + if (File.ReadAllText(packagesPrevious) != File.ReadAllText(packagesJson)) + { + runNpmInstall = true; + } + } + else + { + runNpmInstall = true; + } + } + + if (runNpmInstall) + { + throw new Exception("You need to run once the electronize-h5 start command to bootstrap the necessary files"); + } + + string arguments = ""; + + if (extraElectronArguments is object) + { + arguments = string.Join(' ', extraElectronArguments); + } + + if (clearCache) + { + arguments += " --clear-cache=true"; + } + + BridgeConnector.AuthKey = Guid.NewGuid().ToString().Replace("-", ""); + + var socketPort = FreeTcpPort(); + + arguments += $" --development=true --devauth={BridgeConnector.AuthKey} --devport={socketPort}"; + + string path = Path.Combine(tempPath, "node_modules", ".bin"); + bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + + if (isWindows) + { + ProcessHelper.Execute(@"electron.cmd ""..\..\main.js"" " + arguments, path); + } + else + { + ProcessHelper.Execute(@"./electron ""../../main.js"" " + arguments, path); + } + + BridgeSettings.InitializePorts(socketPort, webPort); + await Task.Delay(500); + + return socketPort; + } + + /// + /// Return a free local TCP port + /// + /// + public static int FreeTcpPort() + { + TcpListener l = new TcpListener(IPAddress.Loopback, 0); + l.Start(); + int port = ((IPEndPoint)l.LocalEndpoint).Port; + l.Stop(); + return port; + } + } + } +} \ No newline at end of file diff --git a/ElectronNET.API/Electron.cs b/ElectronNET.API/Electron.cs index 23f9902d..34faf336 100644 --- a/ElectronNET.API/Electron.cs +++ b/ElectronNET.API/Electron.cs @@ -1,10 +1,51 @@ -namespace ElectronNET.API +using Microsoft.Extensions.Logging; +using System.Runtime.Versioning; +using System; +using System.Collections.Generic; + +namespace ElectronNET.API { /// /// The Electron.NET API /// - public static class Electron + public static partial class Electron { + private static ILoggerFactory loggerFactory; + + /// + /// Reads the auth key from the command line. This method must be called first thing. + /// + /// + public static void ReadAuth() + { + if (!string.IsNullOrEmpty(BridgeConnector.AuthKey)) + { + throw new Exception($"Don't call ReadAuth twice or from with {nameof(Experimental)}.{nameof(Experimental.StartElectronForDevelopment)}"); + } + + var line = Console.ReadLine(); + + if(line.StartsWith("Auth=")) + { + BridgeConnector.AuthKey = line.Substring("Auth=".Length); + } + else + { + throw new Exception("The call to Electron.ReadAuth must be the first thing your app entry point does"); + } + } + + /// + /// Sets the logger factory to be used by Electron, if any + /// + public static ILoggerFactory LoggerFactory + { + private get => loggerFactory; set + { + loggerFactory = value; + BridgeConnector.Logger = value.CreateLogger(); + } + } /// /// Communicate asynchronously from the main process to renderer processes. /// @@ -60,6 +101,11 @@ public static class Electron /// public static Screen Screen { get { return Screen.Instance; } } + /// + /// Access information about media sources that can be used to capture audio and video from the desktop using the navigator.mediaDevices.getUserMedia API. + /// + public static DesktopCapturer DesktopCapturer { get { return DesktopCapturer.Instance; } } + /// /// Perform copy and paste operations on the system clipboard. /// @@ -87,6 +133,7 @@ public static class Electron /// /// Control your app in the macOS dock. /// + [SupportedOSPlatform("macos")] public static Dock Dock { get { return Dock.Instance; } } } } \ No newline at end of file diff --git a/ElectronNET.API/ElectronNET.API.csproj b/ElectronNET.API/ElectronNET.API.csproj index 0400251e..2cb3799d 100644 --- a/ElectronNET.API/ElectronNET.API.csproj +++ b/ElectronNET.API/ElectronNET.API.csproj @@ -1,7 +1,7 @@  - net5.0 + net6.0 true ..\artifacts h5.ElectronNET.API @@ -36,14 +36,18 @@ This package contains the API to access the "native" electron API. - + + all runtime; build; native; contentfiles; analyzers - - - + + + + + diff --git a/ElectronNET.API/Entities/BrowserWindowOptions.cs b/ElectronNET.API/Entities/BrowserWindowOptions.cs index ba920e10..2a860d24 100644 --- a/ElectronNET.API/Entities/BrowserWindowOptions.cs +++ b/ElectronNET.API/Entities/BrowserWindowOptions.cs @@ -1,6 +1,7 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; using System.ComponentModel; +using System.Runtime.Versioning; namespace ElectronNET.API.Entities { @@ -36,62 +37,62 @@ public class BrowserWindowOptions /// window's size will include window frame's size and be slightly larger. Default /// is false. /// - public bool UseContentSize { get; set; } + public bool? UseContentSize { get; set; } /// /// Show window in the center of the screen. /// - public bool Center { get; set; } + public bool? Center { get; set; } /// /// Window's minimum width. Default is 0. /// - public int MinWidth { get; set; } + public int? MinWidth { get; set; } /// /// Window's minimum height. Default is 0. /// - public int MinHeight { get; set; } + public int? MinHeight { get; set; } /// /// Window's maximum width. Default is no limit. /// - public int MaxWidth { get; set; } + public int? MaxWidth { get; set; } /// /// Window's maximum height. Default is no limit. /// - public int MaxHeight { get; set; } + public int? MaxHeight { get; set; } /// /// Whether window is resizable. Default is true. /// [DefaultValue(true)] - public bool Resizable { get; set; } = true; + public bool? Resizable { get; set; } = true; /// /// Whether window is movable. This is not implemented on Linux. Default is true. /// [DefaultValue(true)] - public bool Movable { get; set; } = true; + public bool? Movable { get; set; } = true; /// /// Whether window is minimizable. This is not implemented on Linux. Default is true. /// [DefaultValue(true)] - public bool Minimizable { get; set; } = true; + public bool? Minimizable { get; set; } = true; /// /// Whether window is maximizable. This is not implemented on Linux. Default is true. /// [DefaultValue(true)] - public bool Maximizable { get; set; } = true; + public bool? Maximizable { get; set; } = true; /// /// Whether window is closable. This is not implemented on Linux. Default is true. /// [DefaultValue(true)] - public bool Closable { get; set; } = true; + public bool? Closable { get; set; } = true; /// /// Whether the window can be focused. Default is true. On Windows setting @@ -100,35 +101,35 @@ public class BrowserWindowOptions /// always stay on top in all workspaces. /// [DefaultValue(true)] - public bool Focusable { get; set; } = true; + public bool? Focusable { get; set; } = true; /// /// Whether the window should always stay on top of other windows. Default is false. /// - public bool AlwaysOnTop { get; set; } + public bool? AlwaysOnTop { get; set; } /// /// Whether the window should show in fullscreen. When explicitly set to false the /// fullscreen button will be hidden or disabled on macOS.Default is false. /// - public bool Fullscreen { get; set; } + public bool? Fullscreen { get; set; } /// /// Whether the window can be put into fullscreen mode. On macOS, also whether the /// maximize/zoom button should toggle full screen mode or maximize window.Default /// is true. /// - public bool Fullscreenable { get; set; } + public bool? Fullscreenable { get; set; } /// /// Whether to show the window in taskbar. Default is false. /// - public bool SkipTaskbar { get; set; } + public bool? SkipTaskbar { get; set; } /// /// The kiosk mode. Default is false. /// - public bool Kiosk { get; set; } + public bool? Kiosk { get; set; } /// /// Default window title. Default is "Electron.NET". @@ -145,40 +146,40 @@ public class BrowserWindowOptions /// Whether window should be shown when created. Default is true. /// [DefaultValue(true)] - public bool Show { get; set; } = true; + public bool? Show { get; set; } = true; /// /// Specify false to create a . Default is true. /// [DefaultValue(true)] - public bool Frame { get; set; } = true; + public bool? Frame { get; set; } = true; /// - /// Whether this is a modal window. This only works when the window is a child - /// window.Default is false. + /// Whether this is a modal window. This only works when is + /// also specified. Default is false. /// - public bool Modal { get; set; } + public bool? Modal { get; set; } /// /// Whether the web view accepts a single mouse-down event that simultaneously /// activates the window.Default is false. /// - public bool AcceptFirstMouse { get; set; } + public bool? AcceptFirstMouse { get; set; } /// /// Whether to hide cursor when typing. Default is false. /// - public bool DisableAutoHideCursor { get; set; } + public bool? DisableAutoHideCursor { get; set; } /// /// Auto hide the menu bar unless the Alt key is pressed. Default is false. /// - public bool AutoHideMenuBar { get; set; } + public bool? AutoHideMenuBar { get; set; } /// /// Enable the window to be resized larger than screen. Default is false. /// - public bool EnableLargerThanScreen { get; set; } + public bool? EnableLargerThanScreen { get; set; } /// /// Window's background color as Hexadecimal value, like #66CD00 or #FFF or @@ -190,18 +191,18 @@ public class BrowserWindowOptions /// Whether window should have a shadow. This is only implemented on macOS. Default /// is true. /// - public bool HasShadow { get; set; } + public bool? HasShadow { get; set; } /// /// Forces using dark theme for the window, only works on some GTK+3 desktop /// environments.Default is false. /// - public bool DarkTheme { get; set; } + public bool? DarkTheme { get; set; } /// /// Makes the window . Default is false. /// - public bool Transparent { get; set; } + public bool? Transparent { get; set; } /// /// The type of window, default is normal window. @@ -213,13 +214,21 @@ public class BrowserWindowOptions /// 'default' | 'hidden' | 'hiddenInset' | 'customButtonsOnHover' /// [JsonConverter(typeof(StringEnumConverter))] - public TitleBarStyle TitleBarStyle { get; set; } + public TitleBarStyle? TitleBarStyle { get; set; } /// /// Shows the title in the tile bar in full screen mode on macOS for all /// titleBarStyle options.Default is false. /// - public bool FullscreenWindowTitle { get; set; } + public bool? FullscreenWindowTitle { get; set; } + + /// + /// Activate the Window Controls Overlay on Windows, when combined with = + /// + [SupportedOSPlatform("win")] + [SupportedOSPlatform("macos")] + [DefaultValue(null)] + public TitleBarOverlayConfig TitleBarOverlay { get; set; } /// /// Use WS_THICKFRAME style for frameless windows on Windows, which adds standard @@ -227,7 +236,7 @@ public class BrowserWindowOptions /// animations. Default is true. /// [DefaultValue(true)] - public bool ThickFrame { get; set; } = true; + public bool? ThickFrame { get; set; } = true; /// /// Add a type of vibrancy effect to the window, only on macOS. Can be @@ -235,7 +244,7 @@ public class BrowserWindowOptions /// medium-light or ultra-dark. /// [JsonConverter(typeof(StringEnumConverter))] - public Vibrancy Vibrancy { get; set; } + public Vibrancy? Vibrancy { get; set; } /// /// Controls the behavior on macOS when option-clicking the green stoplight button @@ -244,7 +253,7 @@ public class BrowserWindowOptions /// it to zoom to the width of the screen.This will also affect the behavior when /// calling maximize() directly.Default is false. /// - public bool ZoomToPageWidth { get; set; } + public bool? ZoomToPageWidth { get; set; } /// /// Tab group name, allows opening the window as a native tab on macOS 10.12+. @@ -270,5 +279,20 @@ public class BrowserWindowOptions /// These will only be used if the Proxy field is also set. /// public string ProxyCredentials { get; set; } + + + /// + /// The window to use as the created window's parent. + /// + [DefaultValue(null)] + public BrowserWindow Parent { get; set; } + + /// + /// Set a custom position for the traffic light buttons in frameless windows. + /// + + [DefaultValue(null)] + [SupportedOSPlatform("macos")] + public Point TrafficLightPosition { get; set; } } } diff --git a/ElectronNET.API/Entities/Data.cs b/ElectronNET.API/Entities/Data.cs index 2dcca894..893c55c1 100644 --- a/ElectronNET.API/Entities/Data.cs +++ b/ElectronNET.API/Entities/Data.cs @@ -34,5 +34,7 @@ public class Data /// The title of the url at text. /// public string Bookmark { get; set; } + + public NativeImage? Image { get; set; } } -} \ No newline at end of file +} diff --git a/ElectronNET.API/Entities/DesktopCapturerSource.cs b/ElectronNET.API/Entities/DesktopCapturerSource.cs new file mode 100644 index 00000000..c08dbb90 --- /dev/null +++ b/ElectronNET.API/Entities/DesktopCapturerSource.cs @@ -0,0 +1,15 @@ +using Newtonsoft.Json; + +namespace ElectronNET.API.Entities +{ + public sealed class DesktopCapturerSource + { + public string Id { get; set; } + public string Name { get; set; } + public NativeImage Thumbnail { get; set; } + + [JsonProperty("display_id")] + public string DisplayId { get; set; } + public NativeImage AppIcon { get; set; } + } +} \ No newline at end of file diff --git a/ElectronNET.API/Entities/Display.cs b/ElectronNET.API/Entities/Display.cs index 4d44f32e..4d8cceb4 100644 --- a/ElectronNET.API/Entities/Display.cs +++ b/ElectronNET.API/Entities/Display.cs @@ -26,12 +26,12 @@ public class Display /// /// Can be 0, 90, 180, 270, represents screen rotation in clock-wise degrees. /// - public int Rotation { get; set; } + public float Rotation { get; set; } /// /// Output device's pixel scale factor. /// - public int ScaleFactor { get; set; } + public float ScaleFactor { get; set; } /// /// Gets or sets the size. diff --git a/ElectronNET.API/Entities/JumpListSettings.cs b/ElectronNET.API/Entities/JumpListSettings.cs index 150d0b78..dbd657a1 100644 --- a/ElectronNET.API/Entities/JumpListSettings.cs +++ b/ElectronNET.API/Entities/JumpListSettings.cs @@ -1,4 +1,6 @@ -namespace ElectronNET.API.Entities +using System; + +namespace ElectronNET.API.Entities { public class JumpListSettings { @@ -13,6 +15,6 @@ public class JumpListSettings /// in the Jump List. These items must not be re-added to the Jump List in the next call to , Windows will /// not display any custom category that contains any of the removed items. /// - public JumpListItem[] RemovedItems { get; set; } = new JumpListItem[0]; + public JumpListItem[] RemovedItems { get; set; } = Array.Empty(); } } \ No newline at end of file diff --git a/ElectronNET.API/Entities/NativeImage.cs b/ElectronNET.API/Entities/NativeImage.cs index e1066bed..f6e6395d 100644 --- a/ElectronNET.API/Entities/NativeImage.cs +++ b/ElectronNET.API/Entities/NativeImage.cs @@ -1,8 +1,8 @@ using System; using System.Collections.Generic; -using System.Drawing; -using System.Drawing.Drawing2D; -using System.Drawing.Imaging; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.Processing; using System.IO; using System.Linq; using System.Text.RegularExpressions; @@ -16,10 +16,10 @@ namespace ElectronNET.API.Entities [JsonConverter(typeof(NativeImageJsonConverter))] public class NativeImage { - private readonly Dictionary _images = new Dictionary(); + private readonly Dictionary _images = new(); private bool _isTemplateImage; - private static readonly Dictionary ScaleFactorPairs = new Dictionary + private static readonly Dictionary ScaleFactorPairs = new() { {"@2x", 2.0f}, {"@3x", 3.0f}, {"@1x", 1.0f}, {"@4x", 4.0f}, {"@5x", 5.0f}, {"@1.25x", 1.25f}, {"@1.33x", 1.33f}, {"@1.4x", 1.4f}, @@ -36,8 +36,7 @@ public class NativeImage } private static Image BytesToImage(byte[] bytes) { - var ms = new MemoryStream(bytes); - return Image.FromStream(ms); + return Image.Load(new MemoryStream(bytes)); } /// @@ -51,14 +50,14 @@ public static NativeImage CreateEmpty() /// /// /// - public static NativeImage CreateFromBitmap(Bitmap bitmap, CreateFromBitmapOptions options = null) + public static NativeImage CreateFromImage(Image image, CreateFromBitmapOptions options = null) { if (options is null) { options = new CreateFromBitmapOptions(); } - return new NativeImage(bitmap, options.ScaleFactor); + return new NativeImage(image, options.ScaleFactor); } /// @@ -71,8 +70,7 @@ public static NativeImage CreateFromBuffer(byte[] buffer, CreateFromBufferOption options = new CreateFromBufferOptions(); } - var ms = new MemoryStream(buffer); - var image = Image.FromStream(ms); + var image = Image.Load(new MemoryStream(buffer)); return new NativeImage(image, options.ScaleFactor); } @@ -110,14 +108,14 @@ public static NativeImage CreateFromPath(string path) throw new Exception($"Invalid scaling factor for '{path}'."); } - images[dpi.Value] = Image.FromFile(path); + images[dpi.Value] = Image.Load(path); } else { var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path); var extension = Path.GetExtension(path); // Load as 1x dpi - images[1.0f] = Image.FromFile(path); + images[1.0f] = Image.Load(path); foreach (var scale in ScaleFactorPairs) { @@ -127,7 +125,7 @@ public static NativeImage CreateFromPath(string path) var dpi = ExtractDpiFromFilePath(fileName); if (dpi != null) { - images[dpi.Value] = Image.FromFile(fileName); + images[dpi.Value] = Image.Load(fileName); } } } @@ -164,7 +162,7 @@ public NativeImage(Dictionary imageDictionary) /// public NativeImage Crop(Rectangle rect) { - var images = new Dictionary(); + var images = new Dictionary(); foreach (var image in _images) { images.Add(image.Key, Crop(rect.X, rect.Y, rect.Width, rect.Height, image.Key)); @@ -214,28 +212,12 @@ public float GetAspectRatio(float scaleFactor = 1.0f) var image = GetScale(scaleFactor); if (image != null) { - return image.Width / image.Height; + return (float)image.Width / image.Height; } return 0f; } - - /// - /// Returns a byte array that contains the image's raw bitmap pixel data. - /// - public byte[] GetBitmap(BitmapOptions options) - { - return ToBitmap(new ToBitmapOptions{ ScaleFactor = options.ScaleFactor }); - } - - /// - /// Returns a byte array that contains the image's raw bitmap pixel data. - /// - public byte[] GetNativeHandle() - { - return ToBitmap(new ToBitmapOptions()); - } - + /// /// Gets the size of the specified image based on scale factor /// @@ -278,148 +260,91 @@ public void SetTemplateImage(bool option) /// /// Outputs a bitmap based on the scale factor /// - public byte[] ToBitmap(ToBitmapOptions options) + public MemoryStream ToBitmap(float scaleFactor = 1.0f) { - return ImageToBytes(ImageFormat.Bmp, options.ScaleFactor); + var ms = new MemoryStream(); + _images[scaleFactor].SaveAsBmp(ms); + return ms; } /// - /// Outputs a data URL based on the scale factor + /// Outputs a PNG based on the scale factor /// - public string ToDataURL(ToDataUrlOptions options) + public MemoryStream ToPng(float scaleFactor = 1.0f) { - if (!_images.ContainsKey(options.ScaleFactor)) - { - return null; - } - - var image = _images[options.ScaleFactor]; - var mimeType = ImageCodecInfo.GetImageEncoders().FirstOrDefault(x => x.FormatID == image.RawFormat.Guid)?.MimeType; - if (mimeType is null) - { - mimeType = "image/png"; - } - - var bytes = ImageToBytes(image.RawFormat, options.ScaleFactor); - var base64 = Convert.ToBase64String(bytes); - - return $"data:{mimeType};base64,{base64}"; + var ms = new MemoryStream(); + _images[scaleFactor].SaveAsPng(ms); + return ms; } /// /// Outputs a JPEG for the default scale factor /// - public byte[] ToJPEG(int quality) + public MemoryStream ToJpeg(int quality, float scaleFactor = 1.0f) { - return ImageToBytes(ImageFormat.Jpeg, 1.0f, quality); + var ms = new MemoryStream(); + _images[scaleFactor].SaveAsJpeg(ms, new SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder() { Quality = quality }); + return ms; } /// - /// Outputs a PNG for the specified scale factor + /// Outputs a data URL based on the scale factor /// - public byte[] ToPNG(ToPNGOptions options) - { - return ImageToBytes(ImageFormat.Png, options.ScaleFactor); - } - - private byte[] ImageToBytes(ImageFormat imageFormat = null, float scaleFactor = 1.0f, int quality = 100) + public string ToDataURL(float scaleFactor = 1.0f) { - using var ms = new MemoryStream(); - - if (_images.ContainsKey(scaleFactor)) + if (!_images.TryGetValue(scaleFactor, out var image)) { - var image = _images[scaleFactor]; - var encoderCodecInfo = GetEncoder(imageFormat ?? image.RawFormat); - var encoder = Encoder.Quality; - - var encoderParameters = new EncoderParameters(1) - { - Param = new[] - { - new EncoderParameter(encoder, quality) - } - }; - - image.Save(ms, encoderCodecInfo, encoderParameters); - - return ms.ToArray(); + throw new KeyNotFoundException($"Missing scaleFactor = {scaleFactor}"); } - return null; + return image.ToBase64String(PngFormat.Instance); } + private Image Resize(int? width, int? height, float scaleFactor = 1.0f) { - if (!_images.ContainsKey(scaleFactor) || (width is null && height is null)) + if (!_images.TryGetValue(scaleFactor, out var image)) { - return null; + throw new KeyNotFoundException($"Missing scaleFactor = {scaleFactor}"); } - - var image = _images[scaleFactor]; - using (var g = Graphics.FromImage(image)) + if (width is null && height is null) { - g.CompositingQuality = CompositingQuality.HighQuality; - - var aspect = GetAspectRatio(scaleFactor); - - width ??= Convert.ToInt32(image.Width * aspect); - height ??= Convert.ToInt32(image.Height * aspect); - - width = Convert.ToInt32(width * scaleFactor); - height = Convert.ToInt32(height * scaleFactor); + throw new ArgumentNullException("Missing width or height"); + } - var bmp = new Bitmap(width.Value, height.Value); - g.DrawImage(bmp, - new System.Drawing.Rectangle(0, 0, image.Width, image.Height), - new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height), - GraphicsUnit.Pixel); + var aspect = GetAspectRatio(scaleFactor); + width ??= Convert.ToInt32(image.Width * aspect); + height ??= Convert.ToInt32(image.Height * aspect); + width = Convert.ToInt32(width * scaleFactor); + height = Convert.ToInt32(height * scaleFactor); - return bmp; - } + return image.Clone(c => c.Resize(new SixLabors.ImageSharp.Processing.ResizeOptions + { + Size = new(width.Value, height.Value), + Sampler = KnownResamplers.Triangle, + })); } private Image Crop(int? x, int? y, int? width, int? height, float scaleFactor = 1.0f) { - if (!_images.ContainsKey(scaleFactor)) + if (!_images.TryGetValue(scaleFactor, out var image)) { - return null; + throw new KeyNotFoundException($"Missing scaleFactor = {scaleFactor}"); } - var image = _images[scaleFactor]; - using (var g = Graphics.FromImage(image)) - { - g.CompositingQuality = CompositingQuality.HighQuality; - - x ??= 0; - y ??= 0; - - x = Convert.ToInt32(x * scaleFactor); - y = Convert.ToInt32(y * scaleFactor); + x ??= 0; + y ??= 0; - width ??= image.Width; - height ??= image.Height; + x = Convert.ToInt32(x * scaleFactor); + y = Convert.ToInt32(y * scaleFactor); - width = Convert.ToInt32(width * scaleFactor); - height = Convert.ToInt32(height * scaleFactor); + width ??= image.Width; + height ??= image.Height; - var bmp = new Bitmap(width.Value, height.Value); - g.DrawImage(bmp, new System.Drawing.Rectangle(0, 0, image.Width, image.Height), new System.Drawing.Rectangle(x.Value, y.Value, width.Value, height.Value), GraphicsUnit.Pixel); - - return bmp; - } - } + width = Convert.ToInt32(width * scaleFactor); + height = Convert.ToInt32(height * scaleFactor); - private ImageCodecInfo GetEncoder(ImageFormat format) - { - var codecs = ImageCodecInfo.GetImageDecoders(); - foreach (ImageCodecInfo codec in codecs) - { - if (codec.FormatID == format.Guid) - { - return codec; - } - } - return null; + return image.Clone(c => c.Crop(new SixLabors.ImageSharp.Rectangle(x.Value, y.Value, width.Value, height.Value))); } internal Dictionary GetAllScaledImages() @@ -429,12 +354,12 @@ internal Dictionary GetAllScaledImages() { foreach (var (scale, image) in _images) { - dict.Add(scale, Convert.ToBase64String(ImageToBytes(null, scale))); + dict.Add(scale, image.ToBase64String(PngFormat.Instance)); } } catch (Exception ex) { - Console.WriteLine(ex); + BridgeConnector.LogError(ex, "Error getting scaled images"); } return dict; @@ -442,9 +367,9 @@ internal Dictionary GetAllScaledImages() internal Image GetScale(float scaleFactor) { - if (_images.ContainsKey(scaleFactor)) + if (_images.TryGetValue(scaleFactor, out var image)) { - return _images[scaleFactor]; + return image; } return null; diff --git a/ElectronNET.API/Entities/NativeImageJsonConverter.cs b/ElectronNET.API/Entities/NativeImageJsonConverter.cs index a82c38ec..c15210d7 100644 --- a/ElectronNET.API/Entities/NativeImageJsonConverter.cs +++ b/ElectronNET.API/Entities/NativeImageJsonConverter.cs @@ -1,6 +1,8 @@ using System; using System.Collections.Generic; -using System.Drawing; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.Processing; using System.IO; using Newtonsoft.Json; @@ -19,12 +21,15 @@ public override void WriteJson(JsonWriter writer, object value, JsonSerializer s public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { - var dict = serializer.Deserialize>(reader); + var dict = serializer.Deserialize>(reader); var newDictionary = new Dictionary(); foreach (var item in dict) { - var bytes = Convert.FromBase64String(item.Value); - newDictionary.Add(item.Key, Image.FromStream(new MemoryStream(bytes))); + if (float.TryParse(item.Key, out var size)) + { + var bytes = Convert.FromBase64String(item.Value); + newDictionary.Add(size, Image.Load(new MemoryStream(bytes))); + } } return new NativeImage(newDictionary); } diff --git a/ElectronNET.API/Entities/NotificationAction.cs b/ElectronNET.API/Entities/NotificationAction.cs index c7194cd0..6dd4fa97 100644 --- a/ElectronNET.API/Entities/NotificationAction.cs +++ b/ElectronNET.API/Entities/NotificationAction.cs @@ -1,8 +1,11 @@ -namespace ElectronNET.API.Entities +using System.Runtime.Versioning; + +namespace ElectronNET.API.Entities { /// /// /// + [SupportedOSPlatform("macos")] public class NotificationAction { /// diff --git a/ElectronNET.API/Entities/NotificationOptions.cs b/ElectronNET.API/Entities/NotificationOptions.cs index d1913798..53478220 100644 --- a/ElectronNET.API/Entities/NotificationOptions.cs +++ b/ElectronNET.API/Entities/NotificationOptions.cs @@ -1,5 +1,6 @@ using Newtonsoft.Json; using System; +using System.Runtime.Versioning; namespace ElectronNET.API.Entities { @@ -17,6 +18,8 @@ public class NotificationOptions /// /// A subtitle for the notification, which will be displayed below the title. /// + [SupportedOSPlatform("macos")] + public string SubTitle { get; set; } /// @@ -38,38 +41,46 @@ public class NotificationOptions /// /// Whether or not to add an inline reply option to the notification. /// + [SupportedOSPlatform("macos")] public bool HasReply { get; set; } /// /// The timeout duration of the notification. Can be 'default' or 'never'. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("linux")] public string TimeoutType { get; set; } /// /// The placeholder to write in the inline reply input field. /// + [SupportedOSPlatform("macos")] public string ReplyPlaceholder { get; set; } /// /// The name of the sound file to play when the notification is shown. /// + [SupportedOSPlatform("macos")] public string Sound { get; set; } /// /// The urgency level of the notification. Can be 'normal', 'critical', or 'low'. /// + [SupportedOSPlatform("linux")] public string Urgency { get; set; } /// /// Actions to add to the notification. Please read the available actions and /// limitations in the NotificationAction documentation. /// + [SupportedOSPlatform("macos")] public NotificationAction Actions { get; set; } /// /// A custom title for the close button of an alert. An empty string will cause the /// default localized text to be used. /// + [SupportedOSPlatform("macos")] public string CloseButtonText { get; set; } /// @@ -127,6 +138,7 @@ public class NotificationOptions /// The string the user entered into the inline reply field /// [JsonIgnore] + [SupportedOSPlatform("macos")] public Action OnReply { get; set; } /// @@ -142,6 +154,7 @@ public class NotificationOptions /// macOS only - The index of the action that was activated /// [JsonIgnore] + [SupportedOSPlatform("macos")] public Action OnAction { get; set; } /// diff --git a/ElectronNET.API/Entities/OpenDialogOptions.cs b/ElectronNET.API/Entities/OpenDialogOptions.cs index 3f18dffd..76b58a81 100644 --- a/ElectronNET.API/Entities/OpenDialogOptions.cs +++ b/ElectronNET.API/Entities/OpenDialogOptions.cs @@ -1,5 +1,6 @@ using Newtonsoft.Json; using Newtonsoft.Json.Converters; +using System.Runtime.Versioning; namespace ElectronNET.API.Entities { @@ -39,6 +40,7 @@ public class OpenDialogOptions /// /// Message to display above input boxes. /// + [SupportedOSPlatform("macos")] public string Message { get; set; } /// diff --git a/ElectronNET.API/Entities/OpenDialogProperty.cs b/ElectronNET.API/Entities/OpenDialogProperty.cs index 44a16b15..ec47dad0 100644 --- a/ElectronNET.API/Entities/OpenDialogProperty.cs +++ b/ElectronNET.API/Entities/OpenDialogProperty.cs @@ -1,4 +1,6 @@ -namespace ElectronNET.API.Entities +using System.Runtime.Versioning; + +namespace ElectronNET.API.Entities { /// /// @@ -28,21 +30,66 @@ public enum OpenDialogProperty /// /// The create directory /// + [SupportedOSPlatform("macos")] createDirectory, /// /// The prompt to create /// + [SupportedOSPlatform("windows")] promptToCreate, /// /// The no resolve aliases /// + [SupportedOSPlatform("macos")] noResolveAliases, /// - /// The treat package as directory + /// Treat packages, such as .app folders, as a directory instead of a file. + /// + [SupportedOSPlatform("macos")] + treatPackageAsDirectory, + + /// + /// Don't add the item being opened to recent documents list + /// + [SupportedOSPlatform("windows")] + dontAddToRecent + } + + /// + /// + /// + public enum SaveDialogProperty + { + /// + /// The show hidden files + /// + showHiddenFiles, + + /// + /// The create directory + /// + [SupportedOSPlatform("macos")] + createDirectory, + + /// + /// Treat packages, such as .app folders, as a directory instead of a file. + /// + [SupportedOSPlatform("macos")] + treatPackageAsDirectory, + + /// + /// Sets whether the user will be presented a confirmation dialog if the user types a file name that already exists. + /// + [SupportedOSPlatform("linux")] + showOverwriteConfirmation, + + /// + /// Don't add the item being opened to recent documents list /// - treatPackageAsDirectory + [SupportedOSPlatform("windows")] + dontAddToRecent } } \ No newline at end of file diff --git a/ElectronNET.API/Entities/OpenExternalOptions.cs b/ElectronNET.API/Entities/OpenExternalOptions.cs index dba51ca4..d913593f 100644 --- a/ElectronNET.API/Entities/OpenExternalOptions.cs +++ b/ElectronNET.API/Entities/OpenExternalOptions.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using System.Runtime.Versioning; namespace ElectronNET.API.Entities { @@ -12,11 +13,13 @@ public class OpenExternalOptions /// to bring the opened application to the foreground. The default is . /// [DefaultValue(true)] + [SupportedOSPlatform("macos")] public bool Activate { get; set; } = true; /// /// The working directory. /// + [SupportedOSPlatform("windows")] public string WorkingDirectory { get; set; } } } \ No newline at end of file diff --git a/ElectronNET.API/Entities/SaveDialogOptions.cs b/ElectronNET.API/Entities/SaveDialogOptions.cs index 16811d70..2e7ed4ea 100644 --- a/ElectronNET.API/Entities/SaveDialogOptions.cs +++ b/ElectronNET.API/Entities/SaveDialogOptions.cs @@ -1,4 +1,7 @@ using ElectronNET.API.Entities; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System.Runtime.Versioning; namespace ElectronNET.API { @@ -46,16 +49,26 @@ public class SaveDialogOptions /// /// Message to display above text fields. /// + [SupportedOSPlatform("macos")] public string Message { get; set; } /// /// Custom label for the text displayed in front of the filename text field. /// + [SupportedOSPlatform("macos")] public string NameFieldLabel { get; set; } /// /// Show the tags input box, defaults to true. /// + [SupportedOSPlatform("macos")] public bool ShowsTagField { get; set; } + + /// + /// Contains which features the dialog should use. The following values are supported: + /// 'openFile' | 'openDirectory' | 'multiSelections' | 'showHiddenFiles' | 'createDirectory' | 'promptToCreate' | 'noResolveAliases' | 'treatPackageAsDirectory' + /// + [JsonProperty("properties", ItemConverterType = typeof(StringEnumConverter))] + public SaveDialogProperty[] Properties { get; set; } } } \ No newline at end of file diff --git a/ElectronNET.API/Entities/SourcesOption.cs b/ElectronNET.API/Entities/SourcesOption.cs new file mode 100644 index 00000000..f6bcac4f --- /dev/null +++ b/ElectronNET.API/Entities/SourcesOption.cs @@ -0,0 +1,9 @@ +namespace ElectronNET.API.Entities +{ + public sealed class SourcesOption + { + public string[] Types { get; set; } + public Size ThumbnailSize { get; set; } + public bool FetchWindowIcons { get; set; } + } +} \ No newline at end of file diff --git a/ElectronNET.API/Entities/TitleBarStyle.cs b/ElectronNET.API/Entities/TitleBarStyle.cs index 8fb108ec..a166b994 100644 --- a/ElectronNET.API/Entities/TitleBarStyle.cs +++ b/ElectronNET.API/Entities/TitleBarStyle.cs @@ -28,4 +28,11 @@ public enum TitleBarStyle /// customButtonsOnHover } + + public class TitleBarOverlayConfig + { + public string color { get; set; } + public string symbolColor { get; set; } + public int height { get; set; } + } } \ No newline at end of file diff --git a/ElectronNET.API/Entities/ToBitmapOptions.cs b/ElectronNET.API/Entities/ToBitmapOptions.cs deleted file mode 100644 index 1a08c3bf..00000000 --- a/ElectronNET.API/Entities/ToBitmapOptions.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace ElectronNET.API.Entities -{ - /// - /// - /// - public class ToBitmapOptions - { - /// - /// Gets or sets the scalefactor - /// - public float ScaleFactor { get; set; } = 1.0f; - } -} diff --git a/ElectronNET.API/Entities/ToDataUrlOptions.cs b/ElectronNET.API/Entities/ToDataUrlOptions.cs deleted file mode 100644 index 0df4aa99..00000000 --- a/ElectronNET.API/Entities/ToDataUrlOptions.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace ElectronNET.API.Entities -{ - /// - /// - /// - public class ToDataUrlOptions - { - /// - /// Gets or sets the scalefactor - /// - public float ScaleFactor { get; set; } = 1.0f; - } -} diff --git a/ElectronNET.API/Entities/ToPNGOptions.cs b/ElectronNET.API/Entities/ToPNGOptions.cs deleted file mode 100644 index f4e36b10..00000000 --- a/ElectronNET.API/Entities/ToPNGOptions.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace ElectronNET.API.Entities -{ - /// - /// - /// - public class ToPNGOptions - { - /// - /// Gets or sets the scalefactor - /// - public float ScaleFactor { get; set; } = 1.0f; - } -} diff --git a/ElectronNET.API/Entities/UpdateInfo.cs b/ElectronNET.API/Entities/UpdateInfo.cs index 01dc54bc..8acc0bc0 100644 --- a/ElectronNET.API/Entities/UpdateInfo.cs +++ b/ElectronNET.API/Entities/UpdateInfo.cs @@ -1,4 +1,6 @@ -namespace ElectronNET.API.Entities +using System; + +namespace ElectronNET.API.Entities { /// /// @@ -13,7 +15,7 @@ public class UpdateInfo /// /// /// - public UpdateFileInfo[] Files { get; set; } = new UpdateFileInfo[0]; + public UpdateFileInfo[] Files { get; set; } = Array.Empty(); /// /// The release name. diff --git a/ElectronNET.API/Entities/Vibrancy.cs b/ElectronNET.API/Entities/Vibrancy.cs index 2e8bec85..b496abc8 100644 --- a/ElectronNET.API/Entities/Vibrancy.cs +++ b/ElectronNET.API/Entities/Vibrancy.cs @@ -1,4 +1,5 @@ -using System.Runtime.Serialization; +using System.Runtime.Serialization; +using System; namespace ElectronNET.API.Entities { @@ -11,16 +12,19 @@ public enum Vibrancy /// The appearance based /// [EnumMember(Value = "appearance-based")] + [Obsolete("Removed in macOS Catalina (10.15).")] appearanceBased, /// /// The light /// + [Obsolete("Removed in macOS Catalina (10.15).")] light, /// /// The dark /// + [Obsolete("Removed in macOS Catalina (10.15).")] dark, /// @@ -52,12 +56,38 @@ public enum Vibrancy /// The medium light /// [EnumMember(Value = "medium-light")] + [Obsolete("Removed in macOS Catalina (10.15).")] mediumLight, /// /// The ultra dark /// [EnumMember(Value = "ultra-dark")] - ultraDark + [Obsolete("Removed in macOS Catalina (10.15).")] + ultraDark, + + header, + + sheet, + + window, + + hud, + + [EnumMember(Value = "fullscreen-ui")] + fullscreenUI, + + tooltip, + + content, + + [EnumMember(Value = "under-window")] + underWindow, + + [EnumMember(Value = "under-page")] + underPage + + + } -} \ No newline at end of file +} diff --git a/ElectronNET.API/Entities/WebPreferences.cs b/ElectronNET.API/Entities/WebPreferences.cs index ca5e24e0..1ecee13a 100644 --- a/ElectronNET.API/Entities/WebPreferences.cs +++ b/ElectronNET.API/Entities/WebPreferences.cs @@ -171,6 +171,12 @@ public class WebPreferences /// public bool Offscreen { get; set; } + /// + /// Whether to enable built-in spellcheck + /// + [DefaultValue(true)] + public bool Spellcheck { get; set; } = true; + /// /// Whether to run Electron APIs and the specified preload script in a separate /// JavaScript context. Defaults to false. The context that the preload script runs @@ -189,11 +195,6 @@ public class WebPreferences [DefaultValue(true)] public bool ContextIsolation { get; set; } = true; - /// - /// Whether to use native window.open(). Defaults to false. This option is currently experimental. - /// - public bool NativeWindowOpen { get; set; } - /// /// Whether to enable the Webview. Defaults to the value of the nodeIntegration option. The /// preload script configured for the Webview will have node integration enabled @@ -209,9 +210,9 @@ public class WebPreferences public bool WebviewTag { get; set; } = false; /// - /// Whether to enable the remote module. Defaults to false. + /// Make the web view transparent /// [DefaultValue(false)] - public bool EnableRemoteModule { get; set; } = false; + public bool Transparent { get; set; } = false; } } \ No newline at end of file diff --git a/ElectronNET.API/Events.cs b/ElectronNET.API/Events.cs index 6c01cdc2..2eb65d8b 100644 --- a/ElectronNET.API/Events.cs +++ b/ElectronNET.API/Events.cs @@ -9,8 +9,8 @@ namespace ElectronNET.API internal class Events { private static Events _events; - private static object _syncRoot = new object(); - private TextInfo _ti = new CultureInfo("en-US", false).TextInfo; + private static readonly object _syncRoot = new(); + private readonly TextInfo _ti = new CultureInfo("en-US", false).TextInfo; private Events() { diff --git a/ElectronNET.API/Extensions/EnumExtensions.cs b/ElectronNET.API/Extensions/EnumExtensions.cs index 4424310e..949c1fcd 100644 --- a/ElectronNET.API/Extensions/EnumExtensions.cs +++ b/ElectronNET.API/Extensions/EnumExtensions.cs @@ -11,7 +11,7 @@ public static string GetDescription(this T enumerationValue) where T : struct Type type = enumerationValue.GetType(); if (!type.IsEnum) { - throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue"); + throw new ArgumentException("EnumerationValue must be of Enum type", nameof(enumerationValue)); } //Tries to find a DescriptionAttribute for a potential friendly name diff --git a/ElectronNET.API/Extensions/MenuItemExtensions.cs b/ElectronNET.API/Extensions/MenuItemExtensions.cs index 37a5b9cb..44678a29 100644 --- a/ElectronNET.API/Extensions/MenuItemExtensions.cs +++ b/ElectronNET.API/Extensions/MenuItemExtensions.cs @@ -28,7 +28,7 @@ public static MenuItem[] AddMenuItemsId(this MenuItem[] menuItems) public static MenuItem GetMenuItem(this List menuItems, string id) { - MenuItem result = new MenuItem(); + MenuItem result = new(); foreach (var item in menuItems) { diff --git a/ElectronNET.API/Extensions/ThumbarButtonExtensions.cs b/ElectronNET.API/Extensions/ThumbarButtonExtensions.cs index 3b155546..4d510053 100644 --- a/ElectronNET.API/Extensions/ThumbarButtonExtensions.cs +++ b/ElectronNET.API/Extensions/ThumbarButtonExtensions.cs @@ -23,7 +23,7 @@ public static ThumbarButton[] AddThumbarButtonsId(this ThumbarButton[] thumbarBu public static ThumbarButton GetThumbarButton(this List thumbarButtons, string id) { - ThumbarButton result = new ThumbarButton(""); + ThumbarButton result = new(""); foreach (var item in thumbarButtons) { diff --git a/ElectronNET.API/GlobalShortcut.cs b/ElectronNET.API/GlobalShortcut.cs index 9efbdf27..9d356b28 100644 --- a/ElectronNET.API/GlobalShortcut.cs +++ b/ElectronNET.API/GlobalShortcut.cs @@ -10,7 +10,7 @@ namespace ElectronNET.API public sealed class GlobalShortcut { private static GlobalShortcut _globalShortcut; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal GlobalShortcut() { } @@ -33,7 +33,7 @@ internal static GlobalShortcut Instance } } - private Dictionary _shortcuts = new Dictionary(); + private readonly Dictionary _shortcuts = new(); /// /// Registers a global shortcut of accelerator. diff --git a/ElectronNET.API/HostHook.cs b/ElectronNET.API/HostHook.cs index a5c4e9a9..3fcd7910 100644 --- a/ElectronNET.API/HostHook.cs +++ b/ElectronNET.API/HostHook.cs @@ -16,8 +16,8 @@ namespace ElectronNET.API public sealed class HostHook { private static HostHook _electronHostHook; - private static object _syncRoot = new object(); - string oneCallguid = Guid.NewGuid().ToString(); + private static readonly object _syncRoot = new(); + readonly string oneCallguid = Guid.NewGuid().ToString(); internal HostHook() { } diff --git a/ElectronNET.API/IpcMain.cs b/ElectronNET.API/IpcMain.cs index eae3f3cf..6efb051e 100644 --- a/ElectronNET.API/IpcMain.cs +++ b/ElectronNET.API/IpcMain.cs @@ -14,7 +14,7 @@ namespace ElectronNET.API public sealed class IpcMain { private static IpcMain _ipcMain; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal IpcMain() { } @@ -37,6 +37,8 @@ internal static IpcMain Instance } } + public static bool IsConnected => BridgeConnector.IsConnected; + /// /// Listens to channel, when a new message arrives listener would be called with /// listener(event, args...). @@ -47,11 +49,11 @@ public void On(string channel, Action listener) { BridgeConnector.Emit("registerIpcMainChannel", channel); BridgeConnector.Off(channel); - BridgeConnector.On(channel, (args) => + BridgeConnector.On(channel, (args) => { var objectArray = FormatArguments(args); - if(objectArray.Count == 1) + if (objectArray.Count == 1) { listener(objectArray.First()); } @@ -62,6 +64,38 @@ public void On(string channel, Action listener) }); } + /// + /// Listens to channel, when a new message arrives listener would be called with + /// listener(event, args...). This listner will keep the window event sender id + /// + /// Channelname. + /// Callback Method. + public void OnWithId(string channel, Action<(int browserId, int webContentId, object arguments)> listener) + { + BridgeConnector.Emit("registerIpcMainChannelWithId", channel); + BridgeConnector.Off(channel); + BridgeConnector.On(channel, (data) => + { + var objectArray = FormatArguments(data.args); + + if (objectArray.Count == 1) + { + listener((data.id, data.wcId, objectArray.First())); + } + else + { + listener((data.id, data.wcId, objectArray)); + } + }); + } + + private class ArgsAndIds + { + public int id { get; set; } + public int wcId { get; set; } + public object[] args { get; set; } + } + private List FormatArguments(object[] objectArray) { return objectArray.Where(o => o is object).ToList(); @@ -105,7 +139,7 @@ public void OnSync(string channel, Func listener) public void Once(string channel, Action listener) { BridgeConnector.Emit("registerOnceIpcMainChannel", channel); - BridgeConnector.On(channel, (args) => + BridgeConnector.Once(channel, (args) => { var objectArray = FormatArguments(args); @@ -140,32 +174,29 @@ public void RemoveAllListeners(string channel) /// Arguments data. public void Send(BrowserWindow browserWindow, string channel, params object[] data) { - List jobjects = new List(); - List jarrays = new List(); - List objects = new List(); + var objectsWithCorrectSerialization = new List + { + browserWindow.Id, + channel + }; foreach (var parameterObject in data) { if(parameterObject.GetType().IsArray || parameterObject.GetType().IsGenericType && parameterObject is IEnumerable) { - jarrays.Add(JArray.FromObject(parameterObject, _jsonSerializer)); - } else if(parameterObject.GetType().IsClass && !parameterObject.GetType().IsPrimitive && !(parameterObject is string)) + objectsWithCorrectSerialization.Add(JArray.FromObject(parameterObject, _jsonSerializer)); + } + else if(parameterObject.GetType().IsClass && !parameterObject.GetType().IsPrimitive && !(parameterObject is string)) { - jobjects.Add(JObject.FromObject(parameterObject, _jsonSerializer)); - } else if(parameterObject.GetType().IsPrimitive || (parameterObject is string)) + objectsWithCorrectSerialization.Add(JObject.FromObject(parameterObject, _jsonSerializer)); + } + else if(parameterObject.GetType().IsPrimitive || (parameterObject is string)) { - objects.Add(parameterObject); + objectsWithCorrectSerialization.Add(parameterObject); } } - if(jobjects.Count > 0 || jarrays.Count > 0) - { - BridgeConnector.Emit("sendToIpcRenderer", JObject.FromObject(browserWindow, _jsonSerializer), channel, jarrays.ToArray(), jobjects.ToArray(), objects.ToArray()); - } - else - { - BridgeConnector.Emit("sendToIpcRenderer", JObject.FromObject(browserWindow, _jsonSerializer), channel, data); - } + BridgeConnector.Emit("sendToIpcRenderer", objectsWithCorrectSerialization.ToArray()); } /// @@ -179,9 +210,9 @@ public void Send(BrowserWindow browserWindow, string channel, params object[] da /// Arguments data. public void Send(BrowserView browserView, string channel, params object[] data) { - List jobjects = new List(); - List jarrays = new List(); - List objects = new List(); + List jobjects = new(); + List jarrays = new(); + List objects = new(); foreach (var parameterObject in data) { @@ -228,7 +259,7 @@ public static void ConsoleError(string text) BridgeConnector.Emit("console-stderr", text); } - private JsonSerializer _jsonSerializer = new JsonSerializer() + private readonly JsonSerializer _jsonSerializer = new() { ContractResolver = new CamelCasePropertyNamesContractResolver(), NullValueHandling = NullValueHandling.Ignore, diff --git a/ElectronNET.API/LifetimeServiceHost.cs b/ElectronNET.API/LifetimeServiceHost.cs index cb58eb1b..d6685c2c 100644 --- a/ElectronNET.API/LifetimeServiceHost.cs +++ b/ElectronNET.API/LifetimeServiceHost.cs @@ -16,7 +16,7 @@ public LifetimeServiceHost(IHostApplicationLifetime lifetime) { App.Instance.IsReady = true; - Console.WriteLine("ASP.NET Core host has fully started."); + BridgeConnector.Log("ASP.NET Core host has fully started."); }); } diff --git a/ElectronNET.API/Menu.cs b/ElectronNET.API/Menu.cs index aa98613a..b5b68d24 100644 --- a/ElectronNET.API/Menu.cs +++ b/ElectronNET.API/Menu.cs @@ -15,7 +15,7 @@ namespace ElectronNET.API public sealed class Menu { private static Menu _menu; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Menu() { } @@ -45,7 +45,7 @@ internal static Menu Instance /// The menu items. /// public IReadOnlyCollection MenuItems { get { return _menuItems.AsReadOnly(); } } - private List _menuItems = new List(); + private readonly List _menuItems = new(); /// /// Sets the application menu. @@ -75,7 +75,7 @@ public void SetApplicationMenu(MenuItem[] menuItems) /// The context menu items. /// public IReadOnlyDictionary> ContextMenuItems { get; internal set; } - private Dictionary> _contextMenuItems = new Dictionary>(); + private readonly Dictionary> _contextMenuItems = new(); /// /// Sets the context menu. @@ -113,7 +113,7 @@ public void ContextMenuPopup(BrowserWindow browserWindow) BridgeConnector.Emit("menu-contextMenuPopup", browserWindow.Id); } - private JsonSerializer _jsonSerializer = new JsonSerializer() + private readonly JsonSerializer _jsonSerializer = new() { ContractResolver = new CamelCasePropertyNamesContractResolver(), NullValueHandling = NullValueHandling.Ignore diff --git a/ElectronNET.API/NativeTheme.cs b/ElectronNET.API/NativeTheme.cs index 12bce45a..421db083 100644 --- a/ElectronNET.API/NativeTheme.cs +++ b/ElectronNET.API/NativeTheme.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.Versioning; using System.Threading.Tasks; using ElectronNET.API.Entities; using ElectronNET.API.Extensions; @@ -11,7 +12,7 @@ namespace ElectronNET.API public sealed class NativeTheme { private static NativeTheme _nativeTheme; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal NativeTheme() { } @@ -114,12 +115,16 @@ public void SetThemeSource(ThemeSourceMode themeSourceMode) /// A for if the OS / Chromium currently has high-contrast mode enabled or is /// being instructed to show a high-contrast UI. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public Task ShouldUseHighContrastColorsAsync() => BridgeConnector.OnResult("nativeTheme-shouldUseHighContrastColors", "nativeTheme-shouldUseHighContrastColors-completed"); /// /// A for if the OS / Chromium currently has an inverted color scheme or is /// being instructed to use an inverted color scheme. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public Task ShouldUseInvertedColorSchemeAsync() => BridgeConnector.OnResult("nativeTheme-shouldUseInvertedColorScheme", "nativeTheme-shouldUseInvertedColorScheme-completed"); /// diff --git a/ElectronNET.API/Notification.cs b/ElectronNET.API/Notification.cs index 7f93f96f..54172ca0 100644 --- a/ElectronNET.API/Notification.cs +++ b/ElectronNET.API/Notification.cs @@ -15,7 +15,7 @@ namespace ElectronNET.API public sealed class Notification { private static Notification _notification; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Notification() { } @@ -38,7 +38,7 @@ internal static Notification Instance } } - private static List _notificationOptions = new List(); + private static readonly List _notificationOptions = new(); /// /// Create OS desktop notifications @@ -48,7 +48,7 @@ public void Show(NotificationOptions notificationOptions) { GenerateIDsForDefinedActions(notificationOptions); - BridgeConnector.Emit("createNotification", notificationOptions); + BridgeConnector.Emit("createNotification", JObject.FromObject(notificationOptions, _jsonSerializer)); } private static void GenerateIDsForDefinedActions(NotificationOptions notificationOptions) @@ -134,5 +134,12 @@ public Task IsSupportedAsync() return taskCompletionSource.Task; } + + private static readonly JsonSerializer _jsonSerializer = new() + { + ContractResolver = new CamelCasePropertyNamesContractResolver(), + NullValueHandling = NullValueHandling.Ignore, + DefaultValueHandling = DefaultValueHandling.Ignore + }; } } diff --git a/ElectronNET.API/PowerMonitor.cs b/ElectronNET.API/PowerMonitor.cs index 8a7ab809..8ddde896 100644 --- a/ElectronNET.API/PowerMonitor.cs +++ b/ElectronNET.API/PowerMonitor.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.Versioning; using System.Threading.Tasks; namespace ElectronNET.API @@ -11,6 +12,8 @@ public sealed class PowerMonitor /// /// Emitted when the system is about to lock the screen. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnLockScreen { add @@ -40,6 +43,8 @@ public event Action OnLockScreen /// /// Emitted when the system is about to unlock the screen. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnUnLockScreen { add @@ -69,6 +74,8 @@ public event Action OnUnLockScreen /// /// Emitted when the system is suspending. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnSuspend { add @@ -98,6 +105,8 @@ public event Action OnSuspend /// /// Emitted when system is resuming. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnResume { add @@ -127,6 +136,8 @@ public event Action OnResume /// /// Emitted when the system changes to AC power. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnAC { add @@ -156,6 +167,8 @@ public event Action OnAC /// /// Emitted when system changes to battery power. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnBattery { add @@ -189,6 +202,9 @@ public event Action OnBattery /// order for the app to exit cleanly.If `e.preventDefault()` is called, the app /// should exit as soon as possible by calling something like `app.quit()`. /// + [SupportedOSPlatform("linux")] + [SupportedOSPlatform("macos")] + public event Action OnShutdown { add @@ -216,7 +232,7 @@ public event Action OnShutdown private event Action _shutdown; private static PowerMonitor _powerMonitor; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal PowerMonitor() { } diff --git a/ElectronNET.API/ProcessHelper.cs b/ElectronNET.API/ProcessHelper.cs new file mode 100644 index 00000000..08fedc27 --- /dev/null +++ b/ElectronNET.API/ProcessHelper.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Concurrent; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace ElectronNET.API +{ + internal class ProcessHelper + { + public static void Execute(string command, string workingDirectoryPath) + { + using (Process cmd = new Process()) + { + bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); + + if (isWindows) + { + cmd.StartInfo = new ProcessStartInfo("cmd.exe", "/c " + command); + } + else + { + // works for OSX and Linux (at least on Ubuntu) + var escapedArgs = command.Replace("\"", "\\\""); + cmd.StartInfo = new ProcessStartInfo("bash", $"-c \"{escapedArgs}\""); + } + + cmd.StartInfo.RedirectStandardInput = false; + cmd.StartInfo.RedirectStandardOutput = false; + cmd.StartInfo.RedirectStandardError = false; + cmd.StartInfo.CreateNoWindow = true; + cmd.StartInfo.UseShellExecute = false; + cmd.StartInfo.WorkingDirectory = workingDirectoryPath; + cmd.Start(); + } + } + } +} diff --git a/ElectronNET.API/Screen.cs b/ElectronNET.API/Screen.cs index 48bf392a..a8e91689 100644 --- a/ElectronNET.API/Screen.cs +++ b/ElectronNET.API/Screen.cs @@ -102,7 +102,7 @@ public event Action OnDisplayMetricsChanged private event Action _onDisplayMetricsChanged; private static Screen _screen; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Screen() { } diff --git a/ElectronNET.API/Shell.cs b/ElectronNET.API/Shell.cs index 5bf82c4a..d51c142f 100644 --- a/ElectronNET.API/Shell.cs +++ b/ElectronNET.API/Shell.cs @@ -4,6 +4,7 @@ using Newtonsoft.Json.Serialization; using System.Threading.Tasks; using ElectronNET.API.Extensions; +using System.Runtime.Versioning; namespace ElectronNET.API { @@ -13,7 +14,7 @@ namespace ElectronNET.API public sealed class Shell { private static Shell _shell; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Shell() { } @@ -93,6 +94,7 @@ public Task OpenExternalAsync(string url) /// Max 2081 characters on windows. /// Controls the behavior of OpenExternal. /// The error message corresponding to the failure if a failure occurred, otherwise . + public Task OpenExternalAsync(string url, OpenExternalOptions options) { var taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); @@ -141,6 +143,7 @@ public void Beep() /// Default is /// Structure of a shortcut. /// Whether the shortcut was created successfully. + [SupportedOSPlatform("windows")] public Task WriteShortcutLinkAsync(string shortcutPath, ShortcutLinkOperation operation, ShortcutDetails options) { return BridgeConnector.OnResult("shell-writeShortcutLink", "shell-writeShortcutLinkCompleted", shortcutPath, operation.GetDescription(), options); @@ -152,6 +155,7 @@ public Task WriteShortcutLinkAsync(string shortcutPath, ShortcutLinkOperat /// /// The path tot the shortcut. /// of the shortcut. + [SupportedOSPlatform("windows")] public Task ReadShortcutLinkAsync(string shortcutPath) { return BridgeConnector.OnResult("shell-readShortcutLink", "shell-readShortcutLinkCompleted", shortcutPath); diff --git a/ElectronNET.API/SocketIO/ByteArrayConverter.cs b/ElectronNET.API/SocketIO/ByteArrayConverter.cs new file mode 100644 index 00000000..206b2664 --- /dev/null +++ b/ElectronNET.API/SocketIO/ByteArrayConverter.cs @@ -0,0 +1,64 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Linq; + +namespace SocketIOClient.Newtonsoft.Json +{ + class ByteArrayConverter : JsonConverter + { + public ByteArrayConverter() + { + Bytes = new List(); + } + + internal List Bytes { get; } + + public override bool CanConvert(Type objectType) + { + return objectType == typeof(byte[]); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, global::Newtonsoft.Json.JsonSerializer serializer) + { + byte[] bytes = null; + if (reader.TokenType == JsonToken.StartObject) + { + reader.Read(); + if (reader.TokenType == JsonToken.PropertyName && reader.Value?.ToString() == "_placeholder") + { + reader.Read(); + if (reader.TokenType == JsonToken.Boolean && (bool)reader.Value) + { + reader.Read(); + if (reader.TokenType == JsonToken.PropertyName && reader.Value?.ToString() == "num") + { + reader.Read(); + if (reader.Value != null) + { + if (int.TryParse(reader.Value.ToString(), out int num)) + { + bytes = Bytes[num]; + reader.Read(); + } + } + } + } + } + } + return bytes; + } + + public override void WriteJson(JsonWriter writer, object value, global::Newtonsoft.Json.JsonSerializer serializer) + { + var source = value as byte[]; + Bytes.Add(source.ToArray()); + writer.WriteStartObject(); + writer.WritePropertyName("_placeholder"); + writer.WriteValue(true); + writer.WritePropertyName("num"); + writer.WriteValue(Bytes.Count - 1); + writer.WriteEndObject(); + } + } +} diff --git a/ElectronNET.API/SocketIO/DisconnectReason.cs b/ElectronNET.API/SocketIO/DisconnectReason.cs new file mode 100644 index 00000000..ed66d955 --- /dev/null +++ b/ElectronNET.API/SocketIO/DisconnectReason.cs @@ -0,0 +1,11 @@ +namespace SocketIOClient +{ + public class DisconnectReason + { + public static string IOServerDisconnect = "io server disconnect"; + public static string IOClientDisconnect = "io client disconnect"; + public static string PingTimeout = "ping timeout"; + public static string TransportClose = "transport close"; + public static string TransportError = "transport error"; + } +} diff --git a/ElectronNET.API/SocketIO/EventHandlers.cs b/ElectronNET.API/SocketIO/EventHandlers.cs new file mode 100644 index 00000000..48d5f020 --- /dev/null +++ b/ElectronNET.API/SocketIO/EventHandlers.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; + +namespace SocketIOClient +{ + public delegate void OnAnyHandler(string eventName, SocketIOResponse response); + public delegate void OnOpenedHandler(string sid, int pingInterval, int pingTimeout); + //public delegate void OnDisconnectedHandler(string sid, int pingInterval, int pingTimeout); + public delegate void OnAck(int packetId, List array); + public delegate void OnBinaryAck(int packetId, int totalCount, List array); + public delegate void OnBinaryReceived(int packetId, int totalCount, string eventName, List array); + public delegate void OnDisconnected(); + public delegate void OnError(string error); + public delegate void OnEventReceived(int packetId, string eventName, List array); + public delegate void OnOpened(string sid, int pingInterval, int pingTimeout); + public delegate void OnPing(); + public delegate void OnPong(); +} diff --git a/ElectronNET.API/SocketIO/Extensions/CancellationTokenSourceExtensions.cs b/ElectronNET.API/SocketIO/Extensions/CancellationTokenSourceExtensions.cs new file mode 100644 index 00000000..ff5ae99d --- /dev/null +++ b/ElectronNET.API/SocketIO/Extensions/CancellationTokenSourceExtensions.cs @@ -0,0 +1,18 @@ +using System; +using System.Threading; + +namespace SocketIOClient.Extensions +{ + internal static class CancellationTokenSourceExtensions + { + public static void TryDispose(this CancellationTokenSource cts) + { + cts?.Dispose(); + } + + public static void TryCancel(this CancellationTokenSource cts) + { + cts?.Cancel(); + } + } +} diff --git a/ElectronNET.API/SocketIO/Extensions/DisposableExtensions.cs b/ElectronNET.API/SocketIO/Extensions/DisposableExtensions.cs new file mode 100644 index 00000000..a0f8722d --- /dev/null +++ b/ElectronNET.API/SocketIO/Extensions/DisposableExtensions.cs @@ -0,0 +1,12 @@ +using System; + +namespace SocketIOClient.Extensions +{ + internal static class DisposableExtensions + { + public static void TryDispose(this IDisposable disposable) + { + disposable?.Dispose(); + } + } +} diff --git a/ElectronNET.API/SocketIO/Extensions/EventHandlerExtensions.cs b/ElectronNET.API/SocketIO/Extensions/EventHandlerExtensions.cs new file mode 100644 index 00000000..b05b8f38 --- /dev/null +++ b/ElectronNET.API/SocketIO/Extensions/EventHandlerExtensions.cs @@ -0,0 +1,17 @@ +using System; + +namespace SocketIOClient.Extensions +{ + internal static class EventHandlerExtensions + { + public static void TryInvoke(this EventHandler handler, object sender, T args) + { + handler?.Invoke(sender, args); + } + + public static void TryInvoke(this EventHandler handler, object sender, EventArgs args) + { + handler?.Invoke(sender, args); + } + } +} diff --git a/ElectronNET.API/SocketIO/Extensions/SocketIOEventExtensions.cs b/ElectronNET.API/SocketIO/Extensions/SocketIOEventExtensions.cs new file mode 100644 index 00000000..a03fadf4 --- /dev/null +++ b/ElectronNET.API/SocketIO/Extensions/SocketIOEventExtensions.cs @@ -0,0 +1,30 @@ +using System; + +namespace SocketIOClient.Extensions +{ + internal static class SocketIOEventExtensions + { + public static void TryInvoke(this OnAnyHandler handler, string eventName, SocketIOResponse response) + { + try + { + handler(eventName, response); + } + catch + { + // The exception is thrown by the user code, so it can be swallowed + } + } + public static void TryInvoke(this Action handler, SocketIOResponse response) + { + try + { + handler(response); + } + catch + { + // The exception is thrown by the user code, so it can be swallowed + } + } + } +} diff --git a/ElectronNET.API/SocketIO/JsonSerializer/ByteArrayConverter.cs b/ElectronNET.API/SocketIO/JsonSerializer/ByteArrayConverter.cs new file mode 100644 index 00000000..30bc7046 --- /dev/null +++ b/ElectronNET.API/SocketIO/JsonSerializer/ByteArrayConverter.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace SocketIOClient.JsonSerializer +{ + class ByteArrayConverter : JsonConverter + { + public ByteArrayConverter() + { + Bytes = new List(); + } + + + public List Bytes { get; } + + public override byte[] Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + byte[] bytes = null; + if (reader.TokenType == JsonTokenType.StartObject) + { + reader.Read(); + if (reader.TokenType == JsonTokenType.PropertyName && reader.GetString() == "_placeholder") + { + reader.Read(); + if (reader.TokenType == JsonTokenType.True && reader.GetBoolean()) + { + reader.Read(); + if (reader.TokenType == JsonTokenType.PropertyName && reader.GetString() == "num") + { + reader.Read(); + int num = reader.GetInt32(); + bytes = Bytes[num]; + reader.Read(); + } + } + } + } + return bytes; + } + + public override void Write(Utf8JsonWriter writer, byte[] value, JsonSerializerOptions options) + { + Bytes.Add(value); + writer.WriteStartObject(); + writer.WritePropertyName("_placeholder"); + writer.WriteBooleanValue(true); + writer.WritePropertyName("num"); + writer.WriteNumberValue(Bytes.Count - 1); + writer.WriteEndObject(); + } + } +} diff --git a/ElectronNET.API/SocketIO/JsonSerializer/IJsonSerializer.cs b/ElectronNET.API/SocketIO/JsonSerializer/IJsonSerializer.cs new file mode 100644 index 00000000..8cfe4b8a --- /dev/null +++ b/ElectronNET.API/SocketIO/JsonSerializer/IJsonSerializer.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace SocketIOClient.JsonSerializer +{ + public interface IJsonSerializer + { + JsonSerializeResult Serialize(object[] data); + T Deserialize(string json); + T Deserialize(string json, IList incomingBytes); + } +} diff --git a/ElectronNET.API/SocketIO/JsonSerializer/JsonSerializeResult.cs b/ElectronNET.API/SocketIO/JsonSerializer/JsonSerializeResult.cs new file mode 100644 index 00000000..c4bc1e8c --- /dev/null +++ b/ElectronNET.API/SocketIO/JsonSerializer/JsonSerializeResult.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace SocketIOClient.JsonSerializer +{ + public class JsonSerializeResult + { + public string Json { get; set; } + public IList Bytes { get; set; } + } +} diff --git a/ElectronNET.API/SocketIO/JsonSerializer/SystemTextJsonSerializer.cs b/ElectronNET.API/SocketIO/JsonSerializer/SystemTextJsonSerializer.cs new file mode 100644 index 00000000..9a90981e --- /dev/null +++ b/ElectronNET.API/SocketIO/JsonSerializer/SystemTextJsonSerializer.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Text.Json; + +namespace SocketIOClient.JsonSerializer +{ + public class SystemTextJsonSerializer : IJsonSerializer + { + public JsonSerializeResult Serialize(object[] data) + { + var converter = new ByteArrayConverter(); + var options = GetOptions(); + options.Converters.Add(converter); + string json = System.Text.Json.JsonSerializer.Serialize(data, options); + return new JsonSerializeResult + { + Json = json, + Bytes = converter.Bytes + }; + } + + public T Deserialize(string json) + { + var options = GetOptions(); + return System.Text.Json.JsonSerializer.Deserialize(json, options); + } + + public T Deserialize(string json, IList bytes) + { + var options = GetOptions(); + var converter = new ByteArrayConverter(); + options.Converters.Add(converter); + converter.Bytes.AddRange(bytes); + return System.Text.Json.JsonSerializer.Deserialize(json, options); + } + + private JsonSerializerOptions GetOptions() + { + JsonSerializerOptions options = null; + if (OptionsProvider != null) + { + options = OptionsProvider(); + } + if (options == null) + { + options = new JsonSerializerOptions(); + } + return options; + } + + public Func OptionsProvider { get; set; } + } +} diff --git a/ElectronNET.API/SocketIO/LICENSE b/ElectronNET.API/SocketIO/LICENSE new file mode 100644 index 00000000..c0584ddf --- /dev/null +++ b/ElectronNET.API/SocketIO/LICENSE @@ -0,0 +1,23 @@ +Code from https://github.com/doghappy/socket.io-client-csharp + +MIT License + +Copyright (c) 2019 HeroWong + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/ElectronNET.API/SocketIO/Messages/BinaryMessage.cs b/ElectronNET.API/SocketIO/Messages/BinaryMessage.cs new file mode 100644 index 00000000..df2a7c00 --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/BinaryMessage.cs @@ -0,0 +1,100 @@ +using SocketIOClient.Transport; +using System.Collections.Generic; +using System.Text; +using System.Text.Json; + +namespace SocketIOClient.Messages +{ + public class BinaryMessage : IMessage + { + public MessageType Type => MessageType.BinaryMessage; + + public string Namespace { get; set; } + + public string Event { get; set; } + + public int Id { get; set; } + + public List JsonElements { get; set; } + + public string Json { get; set; } + + public int BinaryCount { get; set; } + + public int Eio { get; set; } + + public TransportProtocol Protocol { get; set; } + + public List OutgoingBytes { get; set; } + + public List IncomingBytes { get; set; } + + public void Read(string msg) + { + int index1 = msg.IndexOf('-'); + BinaryCount = int.Parse(msg.Substring(0, index1)); + + int index2 = msg.IndexOf('['); + + int index3 = msg.LastIndexOf(',', index2); + if (index3 > -1) + { + Namespace = msg.Substring(index1 + 1, index3 - index1 - 1); + int idLength = index2 - index3 - 1; + if (idLength > 0) + { + Id = int.Parse(msg.Substring(index3 + 1, idLength)); + } + } + else + { + int idLength = index2 - index1 - 1; + if (idLength > 0) + { + Id = int.Parse(msg.Substring(index1 + 1, idLength)); + } + } + + string json = msg.Substring(index2); + + var array = JsonDocument.Parse(json).RootElement.EnumerateArray(); + int i = -1; + foreach (var item in array) + { + i++; + if (i == 0) + { + Event = item.GetString(); + JsonElements = new List(); + } + else + { + JsonElements.Add(item); + } + } + } + + public string Write() + { + var builder = new StringBuilder(); + builder + .Append("45") + .Append(OutgoingBytes.Count) + .Append('-'); + if (!string.IsNullOrEmpty(Namespace)) + { + builder.Append(Namespace).Append(','); + } + if (string.IsNullOrEmpty(Json)) + { + builder.Append("[\"").Append(Event).Append("\"]"); + } + else + { + string data = Json.Insert(1, $"\"{Event}\","); + builder.Append(data); + } + return builder.ToString(); + } + } +} diff --git a/ElectronNET.API/SocketIO/Messages/ClientAckMessage.cs b/ElectronNET.API/SocketIO/Messages/ClientAckMessage.cs new file mode 100644 index 00000000..2b4dcda6 --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/ClientAckMessage.cs @@ -0,0 +1,75 @@ +using SocketIOClient.Transport; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; + +namespace SocketIOClient.Messages +{ + /// + /// The server calls the client's callback + /// + public class ClientAckMessage : IMessage + { + public MessageType Type => MessageType.AckMessage; + + public string Namespace { get; set; } + + public string Event { get; set; } + + public List JsonElements { get; set; } + + public string Json { get; set; } + + public int Id { get; set; } + + public List OutgoingBytes { get; set; } + + public List IncomingBytes { get; set; } + + public int BinaryCount { get; } + + public int Eio { get; set; } + + public TransportProtocol Protocol { get; set; } + + public void Read(string msg) + { + int index = msg.IndexOf('['); + int lastIndex = msg.LastIndexOf(',', index); + if (lastIndex > -1) + { + string text = msg.Substring(0, index); + Namespace = text.Substring(0, lastIndex); + Id = int.Parse(text.Substring(lastIndex + 1)); + } + else + { + Id = int.Parse(msg.Substring(0, index)); + } + msg = msg.Substring(index); + JsonElements = JsonDocument.Parse(msg).RootElement.EnumerateArray().ToList(); + } + + public string Write() + { + var builder = new StringBuilder(); + builder.Append("42"); + if (!string.IsNullOrEmpty(Namespace)) + { + builder.Append(Namespace).Append(','); + } + builder.Append(Id); + if (string.IsNullOrEmpty(Json)) + { + builder.Append("[\"").Append(Event).Append("\"]"); + } + else + { + string data = Json.Insert(1, $"\"{Event}\","); + builder.Append(data); + } + return builder.ToString(); + } + } +} diff --git a/ElectronNET.API/SocketIO/Messages/ClientBinaryAckMessage.cs b/ElectronNET.API/SocketIO/Messages/ClientBinaryAckMessage.cs new file mode 100644 index 00000000..f1512683 --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/ClientBinaryAckMessage.cs @@ -0,0 +1,82 @@ +using SocketIOClient.Transport; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.Json; + +namespace SocketIOClient.Messages +{ + /// + /// The server calls the client's callback with binary + /// + public class ClientBinaryAckMessage : IMessage + { + public MessageType Type => MessageType.BinaryAckMessage; + + public string Namespace { get; set; } + + public string Event { get; set; } + + public List JsonElements { get; set; } + + public string Json { get; set; } + + public int Id { get; set; } + + public int BinaryCount { get; set; } + + public int Eio { get; set; } + + public TransportProtocol Protocol { get; set; } + + public List OutgoingBytes { get; set; } + + public List IncomingBytes { get; set; } + + public void Read(string msg) + { + int index1 = msg.IndexOf('-'); + BinaryCount = int.Parse(msg.Substring(0, index1)); + + int index2 = msg.IndexOf('['); + + int index3 = msg.LastIndexOf(',', index2); + if (index3 > -1) + { + Namespace = msg.Substring(index1 + 1, index3 - index1 - 1); + Id = int.Parse(msg.Substring(index3 + 1, index2 - index3 - 1)); + } + else + { + Id = int.Parse(msg.Substring(index1 + 1, index2 - index1 - 1)); + } + + string json = msg.Substring(index2); + JsonElements = JsonDocument.Parse(json).RootElement.EnumerateArray().ToList(); + } + + public string Write() + { + var builder = new StringBuilder(); + builder + .Append("45") + .Append(OutgoingBytes.Count) + .Append('-'); + if (!string.IsNullOrEmpty(Namespace)) + { + builder.Append(Namespace).Append(','); + } + builder.Append(Id); + if (string.IsNullOrEmpty(Json)) + { + builder.Append("[\"").Append(Event).Append("\"]"); + } + else + { + string data = Json.Insert(1, $"\"{Event}\","); + builder.Append(data); + } + return builder.ToString(); + } + } +} diff --git a/ElectronNET.API/SocketIO/Messages/ConnectedMessage.cs b/ElectronNET.API/SocketIO/Messages/ConnectedMessage.cs new file mode 100644 index 00000000..0663ad58 --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/ConnectedMessage.cs @@ -0,0 +1,128 @@ +using System; +using SocketIOClient.Transport; +using System.Collections.Generic; +using System.Text; +using System.Text.Json; + +namespace SocketIOClient.Messages +{ + public class ConnectedMessage : IMessage + { + public MessageType Type => MessageType.Connected; + + public string Namespace { get; set; } + + public string Sid { get; set; } + + public List OutgoingBytes { get; set; } + + public List IncomingBytes { get; set; } + + public int BinaryCount { get; } + + public int Eio { get; set; } + + public TransportProtocol Protocol { get; set; } + + public IEnumerable> Query { get; set; } + public string AuthJsonStr { get; set; } + + public void Read(string msg) + { + if (Eio == 3) + { + Eio3Read(msg); + } + else + { + Eio4Read(msg); + } + } + + public string Write() + { + if (Eio == 3) + { + return Eio3Write(); + } + return Eio4Write(); + } + + public void Eio4Read(string msg) + { + int index = msg.IndexOf('{'); + if (index > 0) + { + Namespace = msg.Substring(0, index - 1); + msg = msg.Substring(index); + } + else + { + Namespace = string.Empty; + } + Sid = JsonDocument.Parse(msg).RootElement.GetProperty("sid").GetString(); + } + + public string Eio4Write() + { + var builder = new StringBuilder("40"); + if (!string.IsNullOrEmpty(Namespace)) + { + builder.Append(Namespace).Append(','); + } + builder.Append(AuthJsonStr); + return builder.ToString(); + } + + public void Eio3Read(string msg) + { + if (msg.Length >= 2) + { + int startIndex = msg.IndexOf('/'); + if (startIndex == -1) + { + return; + } + int endIndex = msg.IndexOf('?', startIndex); + if (endIndex == -1) + { + endIndex = msg.IndexOf(',', startIndex); + } + if (endIndex == -1) + { + endIndex = msg.Length; + } + Namespace = msg.Substring(startIndex, endIndex); + } + } + + public string Eio3Write() + { + if (string.IsNullOrEmpty(Namespace)) + { + return string.Empty; + } + var builder = new StringBuilder("40"); + builder.Append(Namespace); + if (Query != null) + { + int i = -1; + foreach (var item in Query) + { + i++; + if (i == 0) + { + builder.Append('?'); + } + else + { + builder.Append('&'); + } + builder.Append(item.Key).Append('=').Append(item.Value); + } + } + builder.Append(','); + return builder.ToString(); + } + } +} diff --git a/ElectronNET.API/SocketIO/Messages/DisconnectedMessage.cs b/ElectronNET.API/SocketIO/Messages/DisconnectedMessage.cs new file mode 100644 index 00000000..4bceba9b --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/DisconnectedMessage.cs @@ -0,0 +1,36 @@ +using SocketIOClient.Transport; +using System.Collections.Generic; + +namespace SocketIOClient.Messages +{ + public class DisconnectedMessage : IMessage + { + public MessageType Type => MessageType.Disconnected; + + public string Namespace { get; set; } + + public List OutgoingBytes { get; set; } + + public List IncomingBytes { get; set; } + + public int BinaryCount { get; } + + public int Eio { get; set; } + + public TransportProtocol Protocol { get; set; } + + public void Read(string msg) + { + Namespace = msg.TrimEnd(','); + } + + public string Write() + { + if (string.IsNullOrEmpty(Namespace)) + { + return "41"; + } + return "41" + Namespace + ","; + } + } +} diff --git a/ElectronNET.API/SocketIO/Messages/ErrorMessage.cs b/ElectronNET.API/SocketIO/Messages/ErrorMessage.cs new file mode 100644 index 00000000..f36d78b0 --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/ErrorMessage.cs @@ -0,0 +1,50 @@ +using SocketIOClient.Transport; +using System; +using System.Collections.Generic; +using System.Text.Json; + +namespace SocketIOClient.Messages +{ + public class ErrorMessage : IMessage + { + public MessageType Type => MessageType.ErrorMessage; + + public string Message { get; set; } + + public string Namespace { get; set; } + + public List OutgoingBytes { get; set; } + + public List IncomingBytes { get; set; } + + public int BinaryCount { get; } + + public int Eio { get; set; } + + public TransportProtocol Protocol { get; set; } + + public void Read(string msg) + { + if (Eio == 3) + { + Message = msg.Trim('"'); + } + else + { + int index = msg.IndexOf('{'); + if (index > 0) + { + Namespace = msg.Substring(0, index - 1); + msg = msg.Substring(index); + } + var doc = JsonDocument.Parse(msg); + Message = doc.RootElement.GetProperty("message").GetString(); + } + } + + public string Write() + { + throw new NotImplementedException(); + } + } +} diff --git a/ElectronNET.API/SocketIO/Messages/EventMessage.cs b/ElectronNET.API/SocketIO/Messages/EventMessage.cs new file mode 100644 index 00000000..522bd209 --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/EventMessage.cs @@ -0,0 +1,97 @@ +using SocketIOClient.Transport; +using System.Collections.Generic; +using System.Text; +using System.Text.Json; + +namespace SocketIOClient.Messages +{ + public class EventMessage : IMessage + { + public MessageType Type => MessageType.EventMessage; + + public string Namespace { get; set; } + + public string Event { get; set; } + + public int Id { get; set; } + + public List JsonElements { get; set; } + + public string Json { get; set; } + + public List OutgoingBytes { get; set; } + + public List IncomingBytes { get; set; } + + public int BinaryCount { get; } + + public int Eio { get; set; } + + public TransportProtocol Protocol { get; set; } + + public void Read(string msg) + { + int index = msg.IndexOf('['); + int lastIndex = msg.LastIndexOf(',', index); + if (lastIndex > -1) + { + string text = msg.Substring(0, index); + Namespace = text.Substring(0, lastIndex); + if (index - lastIndex > 1) + { + Id = int.Parse(text.Substring(lastIndex + 1)); + } + } + else + { + if (index > 0) + { + Id = int.Parse(msg.Substring(0, index)); + } + } + msg = msg.Substring(index); + + //int index = msg.IndexOf('['); + //if (index > 0) + //{ + // Namespace = msg.Substring(0, index - 1); + // msg = msg.Substring(index); + //} + var array = JsonDocument.Parse(msg).RootElement.EnumerateArray(); + int i = -1; + foreach (var item in array) + { + i++; + if (i == 0) + { + Event = item.GetString(); + JsonElements = new List(); + } + else + { + JsonElements.Add(item); + } + } + } + + public string Write() + { + var builder = new StringBuilder(); + builder.Append("42"); + if (!string.IsNullOrEmpty(Namespace)) + { + builder.Append(Namespace).Append(','); + } + if (string.IsNullOrEmpty(Json)) + { + builder.Append("[\"").Append(Event).Append("\"]"); + } + else + { + string data = Json.Insert(1, $"\"{Event}\","); + builder.Append(data); + } + return builder.ToString(); + } + } +} diff --git a/ElectronNET.API/SocketIO/Messages/IMessage.cs b/ElectronNET.API/SocketIO/Messages/IMessage.cs new file mode 100644 index 00000000..c7f0e250 --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/IMessage.cs @@ -0,0 +1,30 @@ +using SocketIOClient.Transport; +using System.Collections.Generic; + +namespace SocketIOClient.Messages +{ + public interface IMessage + { + MessageType Type { get; } + + List OutgoingBytes { get; set; } + + List IncomingBytes { get; set; } + + int BinaryCount { get; } + + int Eio { get; set; } + + TransportProtocol Protocol { get; set; } + + void Read(string msg); + + //void Eio3WsRead(string msg); + + //void Eio3HttpRead(string msg); + + string Write(); + + //string Eio3WsWrite(); + } +} diff --git a/ElectronNET.API/SocketIO/Messages/MessageFactory.cs b/ElectronNET.API/SocketIO/Messages/MessageFactory.cs new file mode 100644 index 00000000..227a6f72 --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/MessageFactory.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SocketIOClient.Messages +{ + public static class MessageFactory + { + private static IMessage CreateMessage(MessageType type) + { + switch (type) + { + case MessageType.Opened: + return new OpenedMessage(); + case MessageType.Ping: + return new PingMessage(); + case MessageType.Pong: + return new PongMessage(); + case MessageType.Connected: + return new ConnectedMessage(); + case MessageType.Disconnected: + return new DisconnectedMessage(); + case MessageType.EventMessage: + return new EventMessage(); + case MessageType.AckMessage: + return new ClientAckMessage(); + case MessageType.ErrorMessage: + return new ErrorMessage(); + case MessageType.BinaryMessage: + return new BinaryMessage(); + case MessageType.BinaryAckMessage: + return new ClientBinaryAckMessage(); + } + return null; + } + + private static readonly Dictionary _messageTypes = Enum.GetValues().ToDictionary(v => ((int)v).ToString(), v => v); + + public static IMessage CreateMessage(int eio, string msg) + { + foreach (var (prefix,item) in _messageTypes) + { + if (msg.StartsWith(prefix)) + { + IMessage result = CreateMessage(item); + if (result != null) + { + result.Eio = eio; + result.Read(msg.Substring(prefix.Length)); + return result; + } + } + } + return null; + } + + public static OpenedMessage CreateOpenedMessage(string msg) + { + var openedMessage = new OpenedMessage(); + if (msg[0] == '0') + { + openedMessage.Eio = 4; + openedMessage.Read(msg.Substring(1)); + } + else + { + openedMessage.Eio = 3; + int index = msg.IndexOf(':'); + openedMessage.Read(msg.Substring(index + 2)); + } + return openedMessage; + } + } +} diff --git a/ElectronNET.API/SocketIO/Messages/MessageType.cs b/ElectronNET.API/SocketIO/Messages/MessageType.cs new file mode 100644 index 00000000..345c98f6 --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/MessageType.cs @@ -0,0 +1,16 @@ +namespace SocketIOClient.Messages +{ + public enum MessageType + { + Opened, + Ping = 2, + Pong, + Connected = 40, + Disconnected, + EventMessage, + AckMessage, + ErrorMessage, + BinaryMessage, + BinaryAckMessage + } +} diff --git a/ElectronNET.API/SocketIO/Messages/OpenedMessage.cs b/ElectronNET.API/SocketIO/Messages/OpenedMessage.cs new file mode 100644 index 00000000..df297eae --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/OpenedMessage.cs @@ -0,0 +1,79 @@ +using System; +using System.Text.Json; +using System.Collections.Generic; +using SocketIOClient.Transport; + +namespace SocketIOClient.Messages +{ + public class OpenedMessage : IMessage + { + public MessageType Type => MessageType.Opened; + + public string Sid { get; set; } + + public string Namespace { get; set; } + + public List Upgrades { get; private set; } + + public int PingInterval { get; private set; } + + public int PingTimeout { get; private set; } + + public List OutgoingBytes { get; set; } + + public List IncomingBytes { get; set; } + + public int BinaryCount { get; } + + public int Eio { get; set; } + + public TransportProtocol Protocol { get; set; } + + private int GetInt32FromJsonElement(JsonElement element, string msg, string name) + { + var p = element.GetProperty(name); + int val; + switch (p.ValueKind) + { + case JsonValueKind.String: + val = int.Parse(p.GetString()); + break; + case JsonValueKind.Number: + val = p.GetInt32(); + break; + default: + throw new ArgumentException($"Invalid message: '{msg}'"); + } + return val; + } + + public void Read(string msg) + { + var doc = JsonDocument.Parse(msg); + var root = doc.RootElement; + Sid = root.GetProperty("sid").GetString(); + + PingInterval = GetInt32FromJsonElement(root, msg, "pingInterval"); + PingTimeout = GetInt32FromJsonElement(root, msg, "pingTimeout"); + + Upgrades = new List(); + var upgrades = root.GetProperty("upgrades").EnumerateArray(); + foreach (var item in upgrades) + { + Upgrades.Add(item.GetString()); + } + } + + public string Write() + { + //var builder = new StringBuilder(); + //builder.Append("40"); + //if (!string.IsNullOrEmpty(Namespace)) + //{ + // builder.Append(Namespace).Append(','); + //} + //return builder.ToString(); + throw new NotImplementedException(); + } + } +} diff --git a/ElectronNET.API/SocketIO/Messages/PingMessage.cs b/ElectronNET.API/SocketIO/Messages/PingMessage.cs new file mode 100644 index 00000000..fa2b1346 --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/PingMessage.cs @@ -0,0 +1,26 @@ +using SocketIOClient.Transport; +using System.Collections.Generic; + +namespace SocketIOClient.Messages +{ + public class PingMessage : IMessage + { + public MessageType Type => MessageType.Ping; + + public List OutgoingBytes { get; set; } + + public List IncomingBytes { get; set; } + + public int BinaryCount { get; } + + public int Eio { get; set; } + + public TransportProtocol Protocol { get; set; } + + public void Read(string msg) + { + } + + public string Write() => "2"; + } +} diff --git a/ElectronNET.API/SocketIO/Messages/PongMessage.cs b/ElectronNET.API/SocketIO/Messages/PongMessage.cs new file mode 100644 index 00000000..fb4ccfa4 --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/PongMessage.cs @@ -0,0 +1,29 @@ +using SocketIOClient.Transport; +using System; +using System.Collections.Generic; + +namespace SocketIOClient.Messages +{ + public class PongMessage : IMessage + { + public MessageType Type => MessageType.Pong; + + public List OutgoingBytes { get; set; } + + public List IncomingBytes { get; set; } + + public int BinaryCount { get; } + + public int Eio { get; set; } + + public TransportProtocol Protocol { get; set; } + + public TimeSpan Duration { get; set; } + + public void Read(string msg) + { + } + + public string Write() => "3"; + } +} diff --git a/ElectronNET.API/SocketIO/Messages/ServerAckMessage.cs b/ElectronNET.API/SocketIO/Messages/ServerAckMessage.cs new file mode 100644 index 00000000..ce8ce1ae --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/ServerAckMessage.cs @@ -0,0 +1,54 @@ +using SocketIOClient.Transport; +using System.Collections.Generic; +using System.Text; + +namespace SocketIOClient.Messages +{ + /// + /// The client calls the server's callback + /// + public class ServerAckMessage : IMessage + { + public MessageType Type => MessageType.AckMessage; + + public string Namespace { get; set; } + + public string Json { get; set; } + + public int Id { get; set; } + + public List OutgoingBytes { get; set; } + + public List IncomingBytes { get; set; } + + public int BinaryCount { get; } + + public int Eio { get; set; } + + public TransportProtocol Protocol { get; set; } + + public void Read(string msg) + { + } + + public string Write() + { + var builder = new StringBuilder(); + builder.Append("43"); + if (!string.IsNullOrEmpty(Namespace)) + { + builder.Append(Namespace).Append(','); + } + builder.Append(Id); + if (string.IsNullOrEmpty(Json)) + { + builder.Append("[]"); + } + else + { + builder.Append(Json); + } + return builder.ToString(); + } + } +} diff --git a/ElectronNET.API/SocketIO/Messages/ServerBinaryAckMessage.cs b/ElectronNET.API/SocketIO/Messages/ServerBinaryAckMessage.cs new file mode 100644 index 00000000..199f309f --- /dev/null +++ b/ElectronNET.API/SocketIO/Messages/ServerBinaryAckMessage.cs @@ -0,0 +1,60 @@ +using SocketIOClient.Transport; +using System.Collections.Generic; +using System.Text; +using System.Text.Json; + +namespace SocketIOClient.Messages +{ + /// + /// The client calls the server's callback with binary + /// + public class ServerBinaryAckMessage : IMessage + { + public MessageType Type => MessageType.BinaryAckMessage; + + public string Namespace { get; set; } + + public List JsonElements { get; set; } + + public string Json { get; set; } + + public int Id { get; set; } + + public int BinaryCount { get; } + + public int Eio { get; set; } + + public TransportProtocol Protocol { get; set; } + + public List OutgoingBytes { get; set; } + + public List IncomingBytes { get; set; } + + public void Read(string msg) + { + } + + public string Write() + { + var builder = new StringBuilder(); + builder + .Append("46") + .Append(OutgoingBytes.Count) + .Append('-'); + if (!string.IsNullOrEmpty(Namespace)) + { + builder.Append(Namespace).Append(','); + } + builder.Append(Id); + if (string.IsNullOrEmpty(Json)) + { + builder.Append("[]"); + } + else + { + builder.Append(Json); + } + return builder.ToString(); + } + } +} diff --git a/ElectronNET.API/SocketIO/NewtonsoftJsonSerializer.cs b/ElectronNET.API/SocketIO/NewtonsoftJsonSerializer.cs new file mode 100644 index 00000000..9691ffca --- /dev/null +++ b/ElectronNET.API/SocketIO/NewtonsoftJsonSerializer.cs @@ -0,0 +1,56 @@ +using System; +using Newtonsoft.Json; +using SocketIOClient.JsonSerializer; +using System.Collections.Generic; + +namespace SocketIOClient.Newtonsoft.Json +{ + public class NewtonsoftJsonSerializer : IJsonSerializer + { + public Func JsonSerializerOptions { get; } + + public JsonSerializeResult Serialize(object[] data) + { + var converter = new ByteArrayConverter(); + var settings = GetOptions(); + settings.Converters.Add(converter); + string json = JsonConvert.SerializeObject(data, settings); + return new JsonSerializeResult + { + Json = json, + Bytes = converter.Bytes + }; + } + + public T Deserialize(string json) + { + var settings = GetOptions(); + return JsonConvert.DeserializeObject(json, settings); + } + + public T Deserialize(string json, IList bytes) + { + var converter = new ByteArrayConverter(); + converter.Bytes.AddRange(bytes); + var settings = GetOptions(); + settings.Converters.Add(converter); + return JsonConvert.DeserializeObject(json, settings); + } + + private JsonSerializerSettings GetOptions() + { + JsonSerializerSettings options = null; + if (OptionsProvider != null) + { + options = OptionsProvider(); + } + if (options == null) + { + options = new JsonSerializerSettings(); + } + return options; + } + + public Func OptionsProvider { get; set; } + } +} diff --git a/ElectronNET.API/SocketIO/SocketIO.cs b/ElectronNET.API/SocketIO/SocketIO.cs new file mode 100644 index 00000000..edf2f1c3 --- /dev/null +++ b/ElectronNET.API/SocketIO/SocketIO.cs @@ -0,0 +1,769 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net.Http; +using System.Net.WebSockets; +using System.Threading; +using System.Threading.Tasks; +using SocketIOClient.Extensions; +using SocketIOClient.JsonSerializer; +using SocketIOClient.Messages; +using SocketIOClient.Transport; +using SocketIOClient.UriConverters; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; + +namespace SocketIOClient +{ + /// + /// socket.io client class + /// + public class SocketIO : IDisposable + { + /// + /// Create SocketIO object with default options + /// + /// + public SocketIO(string uri) : this(new Uri(uri)) { } + + /// + /// Create SocketIO object with options + /// + /// + public SocketIO(Uri uri) : this(uri, new SocketIOOptions()) { } + + /// + /// Create SocketIO object with options + /// + /// + /// + public SocketIO(string uri, SocketIOOptions options) : this(new Uri(uri), options) { } + + /// + /// Create SocketIO object with options + /// + /// + /// + public SocketIO(Uri uri, SocketIOOptions options) + { + ServerUri = uri ?? throw new ArgumentNullException("uri"); + Options = options ?? throw new ArgumentNullException("options"); + Initialize(); + } + + Uri _serverUri; + private Uri ServerUri + { + get => _serverUri; + set + { + if (_serverUri != value) + { + _serverUri = value; + if (value != null && value.AbsolutePath != "/") + { + _namespace = value.AbsolutePath; + } + } + } + } + + /// + /// An unique identifier for the socket session. Set after the connect event is triggered, and updated after the reconnect event. + /// + public string Id { get; private set; } + + string _namespace; + + /// + /// Whether or not the socket is connected to the server. + /// + public bool Connected { get; private set; } + + int _attempts; + + [Obsolete] + /// + /// Whether or not the socket is disconnected from the server. + /// + public bool Disconnected => !Connected; + + public SocketIOOptions Options { get; } + + public IJsonSerializer JsonSerializer { get; set; } + + public IUriConverter UriConverter { get; set; } + + internal ILogger Logger { get; set; } + + ILoggerFactory _loggerFactory; + public ILoggerFactory LoggerFactory + { + get => _loggerFactory; + set + { + _loggerFactory = value ?? throw new ArgumentNullException(nameof(LoggerFactory)); + Logger = _loggerFactory.CreateLogger(); + } + } + + public HttpClient HttpClient { get; set; } + + public Func ClientWebSocketProvider { get; set; } + private IClientWebSocket _clientWebsocket; + + BaseTransport _transport; + + List _expectedExceptions; + + int _packetId; + bool _isConnectCoreRunning; + Uri _realServerUri; + Exception _connectCoreException; + Dictionary> _ackHandlers; + List _onAnyHandlers; + Dictionary> _eventHandlers; + CancellationTokenSource _connectionTokenSource; + double _reconnectionDelay; + bool _hasError; + bool _isFaild; + readonly static object _connectionLock = new object(); + + #region Socket.IO event + public event EventHandler OnConnected; + //public event EventHandler OnConnectError; + //public event EventHandler OnConnectTimeout; + public event EventHandler OnError; + public event EventHandler OnDisconnected; + + /// + /// Fired upon a successful reconnection. + /// + public event EventHandler OnReconnected; + + /// + /// Fired upon an attempt to reconnect. + /// + public event EventHandler OnReconnectAttempt; + + /// + /// Fired upon a reconnection attempt error. + /// + public event EventHandler OnReconnectError; + + /// + /// Fired when couldn’t reconnect within reconnectionAttempts + /// + public event EventHandler OnReconnectFailed; + public event EventHandler OnPing; + public event EventHandler OnPong; + + #endregion + + #region Observable Event + //Subject _onConnected; + //public IObservable ConnectedObservable { get; private set; } + #endregion + + private void Initialize() + { + _packetId = -1; + _ackHandlers = new Dictionary>(); + _eventHandlers = new Dictionary>(); + _onAnyHandlers = new List(); + + JsonSerializer = new SystemTextJsonSerializer(); + UriConverter = new UriConverter(); + + HttpClient = new HttpClient(); + ClientWebSocketProvider = () => new SystemNetWebSocketsClientWebSocket(Options.EIO); + _expectedExceptions = new List + { + typeof(TimeoutException), + typeof(WebSocketException), + typeof(HttpRequestException), + typeof(OperationCanceledException), + typeof(TaskCanceledException) + }; + LoggerFactory = NullLoggerFactory.Instance; + } + + private async Task CreateTransportAsync() + { + Options.Transport = await GetProtocolAsync(); + if (Options.Transport == TransportProtocol.Polling) + { + HttpPollingHandler handler; + if (Options.EIO == 3) + handler = new Eio3HttpPollingHandler(HttpClient); + else + handler = new Eio4HttpPollingHandler(HttpClient); + _transport = new HttpTransport(HttpClient, handler, Options, JsonSerializer, Logger); + } + else + { + _clientWebsocket = ClientWebSocketProvider(); + _transport = new WebSocketTransport(_clientWebsocket, Options, JsonSerializer, Logger); + } + _transport.Namespace = _namespace; + SetHeaders(); + } + + private void SetHeaders() + { + if (Options.ExtraHeaders != null) + { + foreach (var item in Options.ExtraHeaders) + { + _transport.AddHeader(item.Key, item.Value); + } + } + } + + private void SyncExceptionToMain(Exception e) + { + _connectCoreException = e; + _isConnectCoreRunning = false; + } + + private void ConnectCore() + { + DisposeForReconnect(); + _reconnectionDelay = Options.ReconnectionDelay; + _connectionTokenSource = new CancellationTokenSource(); + var cct = _connectionTokenSource.Token; + Task.Factory.StartNew(async () => + { + while (true) + { + _clientWebsocket.TryDispose(); + _transport.TryDispose(); + CreateTransportAsync().Wait(); + _realServerUri = UriConverter.GetServerUri(Options.Transport == TransportProtocol.WebSocket, ServerUri, Options.EIO, Options.Path, Options.Query); + try + { + if (cct.IsCancellationRequested) + break; + if (_attempts > 0) + OnReconnectAttempt.TryInvoke(this, _attempts); + var timeoutCts = new CancellationTokenSource(Options.ConnectionTimeout); + _transport.Subscribe(OnMessageReceived, OnErrorReceived); + await _transport.ConnectAsync(_realServerUri, timeoutCts.Token).ConfigureAwait(false); + break; + } + catch (Exception e) + { + if (_expectedExceptions.Contains(e.GetType())) + { + if (!Options.Reconnection) + { + SyncExceptionToMain(e); + throw; + } + if (_attempts > 0) + { + OnReconnectError.TryInvoke(this, e); + } + _attempts++; + if (_attempts <= Options.ReconnectionAttempts) + { + if (_reconnectionDelay < Options.ReconnectionDelayMax) + { + _reconnectionDelay += 2 * Options.RandomizationFactor; + } + if (_reconnectionDelay > Options.ReconnectionDelayMax) + { + _reconnectionDelay = Options.ReconnectionDelayMax; + } + Thread.Sleep((int)_reconnectionDelay); + } + else + { + _isFaild = true; + OnReconnectFailed.TryInvoke(this, EventArgs.Empty); + break; + } + } + else + { + SyncExceptionToMain(e); + throw; + } + } + } + _isConnectCoreRunning = false; + }); + } + + private async Task GetProtocolAsync() + { + if (Options.Transport == TransportProtocol.Polling && Options.AutoUpgrade) + { + Uri uri = UriConverter.GetServerUri(false, ServerUri, Options.EIO, Options.Path, Options.Query); + try + { + string text = await HttpClient.GetStringAsync(uri); + if (text.Contains("websocket")) + { + return TransportProtocol.WebSocket; + } + } + catch (Exception e) + { + Logger.LogWarning(e, e.Message); + } + } + return Options.Transport; + } + + public async Task ConnectAsync() + { + if (Connected || _isConnectCoreRunning) + return; + + lock (_connectionLock) + { + if (_isConnectCoreRunning) + return; + _isConnectCoreRunning = true; + } + ConnectCore(); + while (_isConnectCoreRunning) + { + await Task.Delay(100); + } + if (_connectCoreException != null) + { + Logger.LogError(_connectCoreException, _connectCoreException.Message); + throw _connectCoreException; + } + int ms = 0; + while (!Connected) + { + if (_hasError) + { + Logger.LogWarning($"Got a connection error, try to use '{nameof(OnError)}' to detect it."); + break; + } + if (_isFaild) + { + Logger.LogWarning($"Reconnect failed, try to use '{nameof(OnReconnectFailed)}' to detect it."); + break; + } + ms += 100; + if (ms > Options.ConnectionTimeout.TotalMilliseconds) + { + throw new TimeoutException(); + } + await Task.Delay(100); + } + } + + private void PingHandler() + { + OnPing.TryInvoke(this, EventArgs.Empty); + } + + private void PongHandler(PongMessage msg) + { + OnPong.TryInvoke(this, msg.Duration); + } + + private void ConnectedHandler(ConnectedMessage msg) + { + Id = msg.Sid; + Connected = true; + OnConnected.TryInvoke(this, EventArgs.Empty); + if (_attempts > 0) + { + OnReconnected.TryInvoke(this, _attempts); + } + _attempts = 0; + } + + private void DisconnectedHandler() + { + _ = InvokeDisconnect(DisconnectReason.IOServerDisconnect); + } + + private void EventMessageHandler(EventMessage m) + { + var res = new SocketIOResponse(m.JsonElements, this) + { + PacketId = m.Id + }; + foreach (var item in _onAnyHandlers) + { + item.TryInvoke(m.Event, res); + } + if (_eventHandlers.ContainsKey(m.Event)) + { + _eventHandlers[m.Event].TryInvoke(res); + } + } + + private void AckMessageHandler(ClientAckMessage m) + { + if (_ackHandlers.ContainsKey(m.Id)) + { + var res = new SocketIOResponse(m.JsonElements, this); + _ackHandlers[m.Id].TryInvoke(res); + _ackHandlers.Remove(m.Id); + } + } + + private void ErrorMessageHandler(ErrorMessage msg) + { + _hasError = true; + OnError.TryInvoke(this, msg.Message); + } + + private void BinaryMessageHandler(BinaryMessage msg) + { + var response = new SocketIOResponse(msg.JsonElements, this) + { + PacketId = msg.Id, + }; + response.InComingBytes.AddRange(msg.IncomingBytes); + foreach (var item in _onAnyHandlers) + { + item.TryInvoke(msg.Event, response); + } + if (_eventHandlers.ContainsKey(msg.Event)) + { + _eventHandlers[msg.Event].TryInvoke(response); + } + } + + private void BinaryAckMessageHandler(ClientBinaryAckMessage msg) + { + if (_ackHandlers.ContainsKey(msg.Id)) + { + var response = new SocketIOResponse(msg.JsonElements, this) + { + PacketId = msg.Id, + }; + response.InComingBytes.AddRange(msg.IncomingBytes); + _ackHandlers[msg.Id].TryInvoke(response); + } + } + + private void OnErrorReceived(Exception ex) + { + Logger.LogError(ex, ex.Message); + _ = InvokeDisconnect(DisconnectReason.TransportClose); + } + + private void OnMessageReceived(IMessage msg) + { + try + { + switch (msg.Type) + { + case MessageType.Ping: + PingHandler(); + break; + case MessageType.Pong: + PongHandler(msg as PongMessage); + break; + case MessageType.Connected: + ConnectedHandler(msg as ConnectedMessage); + break; + case MessageType.Disconnected: + DisconnectedHandler(); + break; + case MessageType.EventMessage: + EventMessageHandler(msg as EventMessage); + break; + case MessageType.AckMessage: + AckMessageHandler(msg as ClientAckMessage); + break; + case MessageType.ErrorMessage: + ErrorMessageHandler(msg as ErrorMessage); + break; + case MessageType.BinaryMessage: + BinaryMessageHandler(msg as BinaryMessage); + break; + case MessageType.BinaryAckMessage: + BinaryAckMessageHandler(msg as ClientBinaryAckMessage); + break; + } + } + catch (Exception e) + { + Logger.LogError(e, e.Message); + } + } + + public async Task DisconnectAsync() + { + if (Connected) + { + var msg = new DisconnectedMessage + { + Namespace = _namespace + }; + try + { + await _transport.SendAsync(msg, CancellationToken.None).ConfigureAwait(false); + } + catch (Exception e) + { + Logger.LogError(e, e.Message); + } + await InvokeDisconnect(DisconnectReason.IOClientDisconnect); + } + } + + /// + /// Register a new handler for the given event. + /// + /// + /// + public void On(string eventName, Action callback) + { + if (_eventHandlers.ContainsKey(eventName)) + { + _eventHandlers.Remove(eventName); + } + _eventHandlers.Add(eventName, callback); + } + + + + /// + /// Unregister a new handler for the given event. + /// + /// + public void Off(string eventName) + { + if (_eventHandlers.ContainsKey(eventName)) + { + _eventHandlers.Remove(eventName); + } + } + + public void OnAny(OnAnyHandler handler) + { + if (handler != null) + { + _onAnyHandlers.Add(handler); + } + } + + public void PrependAny(OnAnyHandler handler) + { + if (handler != null) + { + _onAnyHandlers.Insert(0, handler); + } + } + + public void OffAny(OnAnyHandler handler) + { + if (handler != null) + { + _onAnyHandlers.Remove(handler); + } + } + + public OnAnyHandler[] ListenersAny() => _onAnyHandlers.ToArray(); + + internal async Task ClientAckAsync(int packetId, CancellationToken cancellationToken, params object[] data) + { + IMessage msg; + if (data != null && data.Length > 0) + { + var result = JsonSerializer.Serialize(data); + if (result.Bytes.Count > 0) + { + msg = new ServerBinaryAckMessage + { + Id = packetId, + Namespace = _namespace, + Json = result.Json + }; + msg.OutgoingBytes = new List(result.Bytes); + } + else + { + msg = new ServerAckMessage + { + Namespace = _namespace, + Id = packetId, + Json = result.Json + }; + } + } + else + { + msg = new ServerAckMessage + { + Namespace = _namespace, + Id = packetId + }; + } + await _transport.SendAsync(msg, cancellationToken).ConfigureAwait(false); + } + + /// + /// Emits an event to the socket + /// + /// + /// Any other parameters can be included. All serializable datastructures are supported, including byte[] + /// + public async Task EmitAsync(string eventName, params object[] data) + { + await EmitAsync(eventName, CancellationToken.None, data).ConfigureAwait(false); + } + + public async Task EmitAsync(string eventName, CancellationToken cancellationToken, params object[] data) + { + if (data != null && data.Length > 0) + { + var result = JsonSerializer.Serialize(data); + if (result.Bytes.Count > 0) + { + var msg = new BinaryMessage + { + Namespace = _namespace, + OutgoingBytes = new List(result.Bytes), + Event = eventName, + Json = result.Json + }; + await _transport.SendAsync(msg, cancellationToken).ConfigureAwait(false); + } + else + { + var msg = new EventMessage + { + Namespace = _namespace, + Event = eventName, + Json = result.Json + }; + await _transport.SendAsync(msg, cancellationToken).ConfigureAwait(false); + } + } + else + { + var msg = new EventMessage + { + Namespace = _namespace, + Event = eventName + }; + await _transport.SendAsync(msg, cancellationToken).ConfigureAwait(false); + } + } + + /// + /// Emits an event to the socket + /// + /// + /// will be called with the server answer. + /// Any other parameters can be included. All serializable datastructures are supported, including byte[] + /// + public async Task EmitAsync(string eventName, Action ack, params object[] data) + { + await EmitAsync(eventName, CancellationToken.None, ack, data).ConfigureAwait(false); + } + + public async Task EmitAsync(string eventName, CancellationToken cancellationToken, Action ack, params object[] data) + { + _ackHandlers.Add(++_packetId, ack); + if (data != null && data.Length > 0) + { + var result = JsonSerializer.Serialize(data); + if (result.Bytes.Count > 0) + { + var msg = new ClientBinaryAckMessage + { + Event = eventName, + Namespace = _namespace, + Json = result.Json, + Id = _packetId, + OutgoingBytes = new List(result.Bytes) + }; + await _transport.SendAsync(msg, cancellationToken).ConfigureAwait(false); + } + else + { + var msg = new ClientAckMessage + { + Event = eventName, + Namespace = _namespace, + Id = _packetId, + Json = result.Json + }; + await _transport.SendAsync(msg, cancellationToken).ConfigureAwait(false); + } + } + else + { + var msg = new ClientAckMessage + { + Event = eventName, + Namespace = _namespace, + Id = _packetId + }; + await _transport.SendAsync(msg, cancellationToken).ConfigureAwait(false); + } + } + + private async Task InvokeDisconnect(string reason) + { + if (Connected) + { + Connected = false; + Id = null; + OnDisconnected.TryInvoke(this, reason); + try + { + await _transport.DisconnectAsync(CancellationToken.None).ConfigureAwait(false); + } + catch (Exception e) + { + Logger.LogError(e, e.Message); + } + if (reason != DisconnectReason.IOServerDisconnect && reason != DisconnectReason.IOClientDisconnect) + { + //In the this cases (explicit disconnection), the client will not try to reconnect and you need to manually call socket.connect(). + if (Options.Reconnection) + { + ConnectCore(); + } + } + } + } + + public void AddExpectedException(Type type) + { + if (!_expectedExceptions.Contains(type)) + { + _expectedExceptions.Add(type); + } + } + + private void DisposeForReconnect() + { + _hasError = false; + _isFaild = false; + _packetId = -1; + _ackHandlers.Clear(); + _connectCoreException = null; + _hasError = false; + _connectionTokenSource.TryCancel(); + _connectionTokenSource.TryDispose(); + } + + public void Dispose() + { + HttpClient.Dispose(); + _transport.TryDispose(); + _ackHandlers.Clear(); + _onAnyHandlers.Clear(); + _eventHandlers.Clear(); + _connectionTokenSource.TryCancel(); + _connectionTokenSource.TryDispose(); + } + } +} \ No newline at end of file diff --git a/ElectronNET.API/SocketIO/SocketIOOptions.cs b/ElectronNET.API/SocketIO/SocketIOOptions.cs new file mode 100644 index 00000000..dc154bb9 --- /dev/null +++ b/ElectronNET.API/SocketIO/SocketIOOptions.cs @@ -0,0 +1,65 @@ +using SocketIOClient.Transport; +using System; +using System.Collections.Generic; + +namespace SocketIOClient +{ + public sealed class SocketIOOptions + { + public SocketIOOptions() + { + RandomizationFactor = 0.5; + ReconnectionDelay = 1000; + ReconnectionDelayMax = 5000; + ReconnectionAttempts = int.MaxValue; + Path = "/socket.io"; + ConnectionTimeout = TimeSpan.FromSeconds(20); + Reconnection = true; + Transport = TransportProtocol.Polling; + EIO = 4; + AutoUpgrade = true; + } + + public string Path { get; set; } + + public TimeSpan ConnectionTimeout { get; set; } + + public IEnumerable> Query { get; set; } + + /// + /// Whether to allow reconnection if accidentally disconnected + /// + public bool Reconnection { get; set; } + + public double ReconnectionDelay { get; set; } + public int ReconnectionDelayMax { get; set; } + public int ReconnectionAttempts { get; set; } + + double _randomizationFactor; + public double RandomizationFactor + { + get => _randomizationFactor; + set + { + if (value >= 0 && value <= 1) + { + _randomizationFactor = value; + } + else + { + throw new ArgumentException($"{nameof(RandomizationFactor)} should be greater than or equal to 0.0, and less than 1.0."); + } + } + } + + public Dictionary ExtraHeaders { get; set; } + + public TransportProtocol Transport { get; set; } + + public int EIO { get; set; } + + public bool AutoUpgrade { get; set; } + + public object Auth { get; set; } + } +} diff --git a/ElectronNET.API/SocketIO/SocketIOResponse.cs b/ElectronNET.API/SocketIO/SocketIOResponse.cs new file mode 100644 index 00000000..42d979c8 --- /dev/null +++ b/ElectronNET.API/SocketIO/SocketIOResponse.cs @@ -0,0 +1,62 @@ +using System.Collections.Generic; +using System.Text; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace SocketIOClient +{ + public class SocketIOResponse + { + public SocketIOResponse(IList array, SocketIO socket) + { + _array = array; + InComingBytes = new List(); + SocketIO = socket; + PacketId = -1; + } + + readonly IList _array; + + public List InComingBytes { get; } + public SocketIO SocketIO { get; } + public int PacketId { get; set; } + + public T GetValue(int index = 0) + { + var element = GetValue(index); + string json = element.GetRawText(); + return SocketIO.JsonSerializer.Deserialize(json, InComingBytes); + } + + public JsonElement GetValue(int index = 0) => _array[index]; + + public int Count => _array.Count; + + public override string ToString() + { + var builder = new StringBuilder(); + builder.Append('['); + foreach (var item in _array) + { + builder.Append(item.GetRawText()); + if (_array.IndexOf(item) < _array.Count - 1) + { + builder.Append(','); + } + } + builder.Append(']'); + return builder.ToString(); + } + + public async Task CallbackAsync(params object[] data) + { + await SocketIO.ClientAckAsync(PacketId, CancellationToken.None, data).ConfigureAwait(false); + } + + public async Task CallbackAsync(CancellationToken cancellationToken, params object[] data) + { + await SocketIO.ClientAckAsync(PacketId, cancellationToken, data).ConfigureAwait(false); + } + } +} diff --git a/ElectronNET.API/SocketIO/Transport/BaseTransport.cs b/ElectronNET.API/SocketIO/Transport/BaseTransport.cs new file mode 100644 index 00000000..efbdc644 --- /dev/null +++ b/ElectronNET.API/SocketIO/Transport/BaseTransport.cs @@ -0,0 +1,245 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Reactive.Subjects; +using Microsoft.Extensions.Logging; +using SocketIOClient.JsonSerializer; +using SocketIOClient.Messages; +using SocketIOClient.UriConverters; + +namespace SocketIOClient.Transport +{ + public abstract class BaseTransport : IObserver, IObserver, IObservable, IDisposable + { + public BaseTransport(SocketIOOptions options, IJsonSerializer jsonSerializer, ILogger logger) + { + Options = options; + MessageSubject = new Subject(); + JsonSerializer = jsonSerializer; + UriConverter = new UriConverter(); + _messageQueue = new Queue(); + _logger = logger; + } + + DateTime _pingTime; + readonly Queue _messageQueue; + readonly ILogger _logger; + + protected SocketIOOptions Options { get; } + protected Subject MessageSubject { get; } + + protected IJsonSerializer JsonSerializer { get; } + protected CancellationTokenSource PingTokenSource { get; private set; } + protected OpenedMessage OpenedMessage { get; private set; } + + public string Namespace { get; set; } + public IUriConverter UriConverter { get; set; } + + public async Task SendAsync(IMessage msg, CancellationToken cancellationToken) + { + msg.Eio = Options.EIO; + msg.Protocol = Options.Transport; + var payload = new Payload + { + Text = msg.Write() + }; + if (msg.OutgoingBytes != null) + { + payload.Bytes = msg.OutgoingBytes; + } + await SendAsync(payload, cancellationToken).ConfigureAwait(false); + } + + protected virtual async Task OpenAsync(OpenedMessage msg) + { + OpenedMessage = msg; + if (Options.EIO == 3 && string.IsNullOrEmpty(Namespace)) + { + return; + } + var connectMsg = new ConnectedMessage + { + Namespace = Namespace, + Eio = Options.EIO, + Query = Options.Query, + }; + if (Options.EIO == 4) + { + if (Options.Auth != null) + { + connectMsg.AuthJsonStr = JsonSerializer.Serialize(new[] { Options.Auth }).Json.TrimStart('[').TrimEnd(']'); + } + } + + for (int i = 1; i <= 3; i++) + { + try + { + await SendAsync(connectMsg, CancellationToken.None).ConfigureAwait(false); + break; + } + catch (Exception e) + { + if (i == 3) + OnError(e); + else + await Task.Delay(TimeSpan.FromMilliseconds(Math.Pow(2, i) * 100)); + } + } + } + + /// + /// Eio3 ping is sent by the client + /// Eio4 ping is sent by the server + /// + /// + private void StartPing(CancellationToken cancellationToken) + { + _logger.LogDebug($"[Ping] Interval: {OpenedMessage.PingInterval}"); + Task.Factory.StartNew(async () => + { + while (!cancellationToken.IsCancellationRequested) + { + await Task.Delay(OpenedMessage.PingInterval); + if (cancellationToken.IsCancellationRequested) + { + break; + } + try + { + var ping = new PingMessage(); + _logger.LogDebug($"[Ping] Sending"); + await SendAsync(ping, CancellationToken.None).ConfigureAwait(false); + _logger.LogDebug($"[Ping] Has been sent"); + _pingTime = DateTime.Now; + MessageSubject.OnNext(ping); + } + catch (Exception e) + { + _logger.LogDebug($"[Ping] Failed to send, {e.Message}"); + MessageSubject.OnError(e); + break; + } + } + }, TaskCreationOptions.LongRunning); + } + + public abstract Task ConnectAsync(Uri uri, CancellationToken cancellationToken); + + public abstract Task DisconnectAsync(CancellationToken cancellationToken); + + public abstract void AddHeader(string key, string val); + + public virtual void Dispose() + { + MessageSubject.Dispose(); + _messageQueue.Clear(); + if (PingTokenSource != null) + { + PingTokenSource.Cancel(); + PingTokenSource.Dispose(); + } + } + + public abstract Task SendAsync(Payload payload, CancellationToken cancellationToken); + + public void OnCompleted() + { + throw new NotImplementedException(); + } + + public void OnError(Exception error) + { + MessageSubject.OnError(error); + } + + public void OnNext(string text) + { + _logger.LogDebug($"[Receive] {text}"); + var msg = MessageFactory.CreateMessage(Options.EIO, text); + if (msg == null) + { + return; + } + if (msg.BinaryCount > 0) + { + msg.IncomingBytes = new List(msg.BinaryCount); + _messageQueue.Enqueue(msg); + return; + } + if (msg.Type == MessageType.Opened) + { + OpenAsync(msg as OpenedMessage).ConfigureAwait(false); + } + + if (Options.EIO == 3) + { + if (msg.Type == MessageType.Connected) + { + var connectMsg = msg as ConnectedMessage; + connectMsg.Sid = OpenedMessage.Sid; + if ((string.IsNullOrEmpty(Namespace) && string.IsNullOrEmpty(connectMsg.Namespace)) || connectMsg.Namespace == Namespace) + { + if (PingTokenSource != null) + { + PingTokenSource.Cancel(); + } + PingTokenSource = new CancellationTokenSource(); + StartPing(PingTokenSource.Token); + } + else + { + return; + } + } + else if (msg.Type == MessageType.Pong) + { + var pong = msg as PongMessage; + pong.Duration = DateTime.Now - _pingTime; + } + } + + MessageSubject.OnNext(msg); + + if (msg.Type == MessageType.Ping) + { + _pingTime = DateTime.Now; + try + { + SendAsync(new PongMessage(), CancellationToken.None).ConfigureAwait(false); + MessageSubject.OnNext(new PongMessage + { + Eio = Options.EIO, + Protocol = Options.Transport, + Duration = DateTime.Now - _pingTime + }); + } + catch (Exception e) + { + OnError(e); + } + } + } + + public void OnNext(byte[] bytes) + { + _logger.LogDebug($"[Receive] binary message"); + if (_messageQueue.Count > 0) + { + var msg = _messageQueue.Peek(); + msg.IncomingBytes.Add(bytes); + if (msg.IncomingBytes.Count == msg.BinaryCount) + { + MessageSubject.OnNext(msg); + _messageQueue.Dequeue(); + } + } + } + + public IDisposable Subscribe(IObserver observer) + { + return MessageSubject.Subscribe(observer); + } + } +} diff --git a/ElectronNET.API/SocketIO/Transport/Eio3HttpPollingHandler.cs b/ElectronNET.API/SocketIO/Transport/Eio3HttpPollingHandler.cs new file mode 100644 index 00000000..8134c3f6 --- /dev/null +++ b/ElectronNET.API/SocketIO/Transport/Eio3HttpPollingHandler.cs @@ -0,0 +1,76 @@ +using System.Collections.Generic; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using System.Linq; +using System.Net.Http.Headers; + +namespace SocketIOClient.Transport +{ + public class Eio3HttpPollingHandler : HttpPollingHandler + { + public Eio3HttpPollingHandler(HttpClient httpClient) : base(httpClient) { } + + public override async Task PostAsync(string uri, IEnumerable bytes, CancellationToken cancellationToken) + { + var list = new List(); + foreach (var item in bytes) + { + list.Add(1); + var length = SplitInt(item.Length + 1).Select(x => (byte)x); + list.AddRange(length); + list.Add(byte.MaxValue); + list.Add(4); + list.AddRange(item); + } + var content = new ByteArrayContent(list.ToArray()); + content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); + await HttpClient.PostAsync(AppendRandom(uri), content, cancellationToken).ConfigureAwait(false); + } + + private List SplitInt(int number) + { + List list = new List(); + while (number > 0) + { + list.Add(number % 10); + number /= 10; + } + list.Reverse(); + return list; + } + + protected override void ProduceText(string text) + { + int p = 0; + while (true) + { + int index = text.IndexOf(':', p); + if (index == -1) + { + break; + } + if (int.TryParse(text.Substring(p, index - p), out int length)) + { + string msg = text.Substring(index + 1, length); + TextSubject.OnNext(msg); + } + else + { + break; + } + p = index + length + 1; + if (p >= text.Length) + { + break; + } + } + } + + public override Task PostAsync(string uri, string content, CancellationToken cancellationToken) + { + content = content.Length + ":" + content; + return base.PostAsync(uri, content, cancellationToken); + } + } +} diff --git a/ElectronNET.API/SocketIO/Transport/Eio4HttpPollingHandler.cs b/ElectronNET.API/SocketIO/Transport/Eio4HttpPollingHandler.cs new file mode 100644 index 00000000..a8b12089 --- /dev/null +++ b/ElectronNET.API/SocketIO/Transport/Eio4HttpPollingHandler.cs @@ -0,0 +1,48 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace SocketIOClient.Transport +{ + public class Eio4HttpPollingHandler : HttpPollingHandler + { + public Eio4HttpPollingHandler(HttpClient httpClient) : base(httpClient) { } + + const char Separator = '\u001E'; //1E  + + public override async Task PostAsync(string uri, IEnumerable bytes, CancellationToken cancellationToken) + { + var builder = new StringBuilder(); + foreach (var item in bytes) + { + builder.Append('b').Append(Convert.ToBase64String(item)).Append(Separator); + } + if (builder.Length == 0) + { + return; + } + string text = builder.ToString().TrimEnd(Separator); + await PostAsync(uri, text, cancellationToken); + } + + protected override void ProduceText(string text) + { + string[] items = text.Split(new[] { Separator }, StringSplitOptions.RemoveEmptyEntries); + foreach (var item in items) + { + if (item[0] == 'b') + { + byte[] bytes = Convert.FromBase64String(item.Substring(1)); + BytesSubject.OnNext(bytes); + } + else + { + TextSubject.OnNext(item); + } + } + } + } +} diff --git a/ElectronNET.API/SocketIO/Transport/HttpPollingHandler.cs b/ElectronNET.API/SocketIO/Transport/HttpPollingHandler.cs new file mode 100644 index 00000000..48147dc8 --- /dev/null +++ b/ElectronNET.API/SocketIO/Transport/HttpPollingHandler.cs @@ -0,0 +1,118 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace SocketIOClient.Transport +{ + public abstract class HttpPollingHandler : IHttpPollingHandler + { + public HttpPollingHandler(HttpClient httpClient) + { + HttpClient = httpClient; + TextSubject = new Subject(); + BytesSubject = new Subject(); + TextObservable = TextSubject.AsObservable(); + BytesObservable = BytesSubject.AsObservable(); + } + + protected HttpClient HttpClient { get; } + protected Subject TextSubject{get;} + protected Subject BytesSubject{get;} + + public IObservable TextObservable { get; } + public IObservable BytesObservable { get; } + + protected string AppendRandom(string uri) + { + return uri + "&t=" + DateTimeOffset.Now.ToUnixTimeSeconds(); + } + + public async Task GetAsync(string uri, CancellationToken cancellationToken) + { + var req = new HttpRequestMessage(HttpMethod.Get, AppendRandom(uri)); + var resMsg = await HttpClient.SendAsync(req, cancellationToken).ConfigureAwait(false); + if (!resMsg.IsSuccessStatusCode) + { + throw new HttpRequestException($"Response status code does not indicate success: {resMsg.StatusCode}"); + } + await ProduceMessageAsync(resMsg).ConfigureAwait(false); + } + + public async Task SendAsync(HttpRequestMessage req, CancellationToken cancellationToken) + { + var resMsg = await HttpClient.SendAsync(req, cancellationToken).ConfigureAwait(false); + if (!resMsg.IsSuccessStatusCode) + { + throw new HttpRequestException($"Response status code does not indicate success: {resMsg.StatusCode}"); + } + await ProduceMessageAsync(resMsg).ConfigureAwait(false); + } + + public async virtual Task PostAsync(string uri, string content, CancellationToken cancellationToken) + { + var httpContent = new StringContent(content); + var resMsg = await HttpClient.PostAsync(AppendRandom(uri), httpContent, cancellationToken).ConfigureAwait(false); + await ProduceMessageAsync(resMsg).ConfigureAwait(false); + } + + public abstract Task PostAsync(string uri, IEnumerable bytes, CancellationToken cancellationToken); + + private async Task ProduceMessageAsync(HttpResponseMessage resMsg) + { + if (resMsg.Content.Headers.ContentType.MediaType == "application/octet-stream") + { + byte[] bytes = await resMsg.Content.ReadAsByteArrayAsync().ConfigureAwait(false); + ProduceBytes(bytes); + } + else + { + string text = await resMsg.Content.ReadAsStringAsync().ConfigureAwait(false); + ProduceText(text); + } + } + + protected abstract void ProduceText(string text); + + private void ProduceBytes(byte[] bytes) + { + int i = 0; + while (bytes.Length > i + 4) + { + byte type = bytes[i]; + var builder = new StringBuilder(); + i++; + while (bytes[i] != byte.MaxValue) + { + builder.Append(bytes[i]); + i++; + } + i++; + int length = int.Parse(builder.ToString()); + if (type == 0) + { + var buffer = new byte[length]; + Buffer.BlockCopy(bytes, i, buffer, 0, buffer.Length); + TextSubject.OnNext(Encoding.UTF8.GetString(buffer)); + } + else if (type == 1) + { + var buffer = new byte[length - 1]; + Buffer.BlockCopy(bytes, i + 1, buffer, 0, buffer.Length); + BytesSubject.OnNext(buffer); + } + i += length; + } + } + + public void Dispose() + { + TextSubject.Dispose(); + BytesSubject.Dispose(); + } + } +} diff --git a/ElectronNET.API/SocketIO/Transport/HttpTransport.cs b/ElectronNET.API/SocketIO/Transport/HttpTransport.cs new file mode 100644 index 00000000..4e7c6bf0 --- /dev/null +++ b/ElectronNET.API/SocketIO/Transport/HttpTransport.cs @@ -0,0 +1,121 @@ +using System; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using SocketIOClient.JsonSerializer; +using SocketIOClient.Messages; + +namespace SocketIOClient.Transport +{ + public class HttpTransport : BaseTransport + { + public HttpTransport(HttpClient http, + IHttpPollingHandler pollingHandler, + SocketIOOptions options, + IJsonSerializer jsonSerializer, + ILogger logger) : base(options, jsonSerializer, logger) + { + _http = http; + _httpPollingHandler = pollingHandler; + _httpPollingHandler.TextObservable.Subscribe(this); + _httpPollingHandler.BytesObservable.Subscribe(this); + } + + string _httpUri; + CancellationTokenSource _pollingTokenSource; + + readonly HttpClient _http; + readonly IHttpPollingHandler _httpPollingHandler; + + private void StartPolling(CancellationToken cancellationToken) + { + Task.Factory.StartNew(async () => + { + int retry = 0; + while (!cancellationToken.IsCancellationRequested) + { + if (!_httpUri.Contains("&sid=")) + { + await Task.Delay(20); + continue; + } + try + { + await _httpPollingHandler.GetAsync(_httpUri, CancellationToken.None).ConfigureAwait(false); + } + catch (Exception e) + { + retry++; + if (retry >= 3) + { + MessageSubject.OnError(e); + break; + } + await Task.Delay(100 * (int)Math.Pow(2, retry)); + } + } + }, TaskCreationOptions.LongRunning); + } + + public override async Task ConnectAsync(Uri uri, CancellationToken cancellationToken) + { + var req = new HttpRequestMessage(HttpMethod.Get, uri); + // if (_options.ExtraHeaders != null) + // { + // foreach (var item in _options.ExtraHeaders) + // { + // req.Headers.Add(item.Key, item.Value); + // } + // } + + _httpUri = uri.ToString(); + await _httpPollingHandler.SendAsync(req, new CancellationTokenSource(Options.ConnectionTimeout).Token).ConfigureAwait(false); + if (_pollingTokenSource != null) + { + _pollingTokenSource.Cancel(); + } + _pollingTokenSource = new CancellationTokenSource(); + StartPolling(_pollingTokenSource.Token); + } + + public override Task DisconnectAsync(CancellationToken cancellationToken) + { + _pollingTokenSource.Cancel(); + if (PingTokenSource != null) + { + PingTokenSource.Cancel(); + } + return Task.CompletedTask; + } + + public override void AddHeader(string key, string val) + { + _http.DefaultRequestHeaders.Add(key, val); + } + + public override void Dispose() + { + base.Dispose(); + _httpPollingHandler.Dispose(); + } + + public override async Task SendAsync(Payload payload, CancellationToken cancellationToken) + { + await _httpPollingHandler.PostAsync(_httpUri, payload.Text, cancellationToken); + if (payload.Bytes != null && payload.Bytes.Count > 0) + { + await _httpPollingHandler.PostAsync(_httpUri, payload.Bytes, cancellationToken); + } + } + + protected override async Task OpenAsync(OpenedMessage msg) + { + //if (!_httpUri.Contains("&sid=")) + //{ + //} + _httpUri += "&sid=" + msg.Sid; + await base.OpenAsync(msg); + } + } +} diff --git a/ElectronNET.API/SocketIO/Transport/IClientWebSocket.cs b/ElectronNET.API/SocketIO/Transport/IClientWebSocket.cs new file mode 100644 index 00000000..a3f75fd8 --- /dev/null +++ b/ElectronNET.API/SocketIO/Transport/IClientWebSocket.cs @@ -0,0 +1,16 @@ +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace SocketIOClient.Transport +{ + public interface IClientWebSocket : IDisposable + { + IObservable TextObservable { get; } + IObservable BytesObservable { get; } + Task ConnectAsync(Uri uri, CancellationToken cancellationToken); + Task DisconnectAsync(CancellationToken cancellationToken); + Task SendAsync(byte[] bytes, TransportMessageType type, bool endOfMessage, CancellationToken cancellationToken); + void AddHeader(string key, string val); + } +} diff --git a/ElectronNET.API/SocketIO/Transport/IHttpPollingHandler.cs b/ElectronNET.API/SocketIO/Transport/IHttpPollingHandler.cs new file mode 100644 index 00000000..f1170109 --- /dev/null +++ b/ElectronNET.API/SocketIO/Transport/IHttpPollingHandler.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace SocketIOClient.Transport +{ + public interface IHttpPollingHandler : IDisposable + { + IObservable TextObservable { get; } + IObservable BytesObservable { get; } + Task GetAsync(string uri, CancellationToken cancellationToken); + Task SendAsync(HttpRequestMessage req, CancellationToken cancellationToken); + Task PostAsync(string uri, string content, CancellationToken cancellationToken); + Task PostAsync(string uri, IEnumerable bytes, CancellationToken cancellationToken); + } +} diff --git a/ElectronNET.API/SocketIO/Transport/Payload.cs b/ElectronNET.API/SocketIO/Transport/Payload.cs new file mode 100644 index 00000000..e906f67b --- /dev/null +++ b/ElectronNET.API/SocketIO/Transport/Payload.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace SocketIOClient.Transport +{ + public class Payload + { + public string Text { get; set; } + public List Bytes { get; set; } + } +} diff --git a/ElectronNET.API/SocketIO/Transport/SystemNetWebSocketsClientWebSocket.cs b/ElectronNET.API/SocketIO/Transport/SystemNetWebSocketsClientWebSocket.cs new file mode 100644 index 00000000..5a49dbd6 --- /dev/null +++ b/ElectronNET.API/SocketIO/Transport/SystemNetWebSocketsClientWebSocket.cs @@ -0,0 +1,143 @@ +using System; +using System.Net.WebSockets; +using System.Reactive.Linq; +using System.Reactive.Subjects; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace SocketIOClient.Transport +{ + public class SystemNetWebSocketsClientWebSocket : IClientWebSocket + { + public SystemNetWebSocketsClientWebSocket(int eio) + { + _eio = eio; + _textSubject = new Subject(); + _bytesSubject = new Subject(); + TextObservable = _textSubject.AsObservable(); + BytesObservable = _bytesSubject.AsObservable(); + _ws = new ClientWebSocket(); + _listenCancellation = new CancellationTokenSource(); + _sendLock = new SemaphoreSlim(1, 1); + } + + const int ReceiveChunkSize = 1024 * 8; + + readonly int _eio; + readonly ClientWebSocket _ws; + readonly Subject _textSubject; + readonly Subject _bytesSubject; + readonly CancellationTokenSource _listenCancellation; + readonly SemaphoreSlim _sendLock; + + public IObservable TextObservable { get; } + public IObservable BytesObservable { get; } + + private void Listen() + { + Task.Factory.StartNew(async() => + { + while (true) + { + if (_listenCancellation.IsCancellationRequested) + { + break; + } + var buffer = new byte[ReceiveChunkSize]; + int count = 0; + WebSocketReceiveResult result = null; + + while (_ws.State == WebSocketState.Open) + { + var subBuffer = new byte[ReceiveChunkSize]; + try + { + result = await _ws.ReceiveAsync(new ArraySegment(subBuffer), CancellationToken.None).ConfigureAwait(false); + + // resize + if (buffer.Length - count < result.Count) + { + Array.Resize(ref buffer, buffer.Length + result.Count); + } + Buffer.BlockCopy(subBuffer, 0, buffer, count, result.Count); + count += result.Count; + if (result.EndOfMessage) + { + break; + } + } + catch (Exception e) + { + _textSubject.OnError(e); + break; + } + } + + if (result == null) + { + break; + } + + switch (result.MessageType) + { + case WebSocketMessageType.Text: + string text = Encoding.UTF8.GetString(buffer, 0, count); + _textSubject.OnNext(text); + break; + case WebSocketMessageType.Binary: + byte[] bytes; + if (_eio == 3) + { + bytes = new byte[count - 1]; + Buffer.BlockCopy(buffer, 1, bytes, 0, bytes.Length); + } + else + { + bytes = new byte[count]; + Buffer.BlockCopy(buffer, 0, bytes, 0, bytes.Length); + } + _bytesSubject.OnNext(bytes); + break; + case WebSocketMessageType.Close: + _textSubject.OnError(new WebSocketException("Received a Close message")); + break; + } + } + }); + } + + public async Task ConnectAsync(Uri uri, CancellationToken cancellationToken) + { + await _ws.ConnectAsync(uri, cancellationToken); + Listen(); + } + + public async Task DisconnectAsync(CancellationToken cancellationToken) + { + await _ws.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, cancellationToken); + } + + public async Task SendAsync(byte[] bytes, TransportMessageType type, bool endOfMessage, CancellationToken cancellationToken) + { + var msgType = WebSocketMessageType.Text; + if (type == TransportMessageType.Binary) + { + msgType = WebSocketMessageType.Binary; + } + await _ws.SendAsync(new ArraySegment(bytes), msgType, endOfMessage, cancellationToken).ConfigureAwait(false); + } + + public void AddHeader(string key, string val) + { + _ws.Options.SetRequestHeader(key, val); + } + + public void Dispose() + { + _textSubject.Dispose(); + _bytesSubject.Dispose(); + _ws.Dispose(); + } + } +} diff --git a/ElectronNET.API/SocketIO/Transport/TransportMessageType.cs b/ElectronNET.API/SocketIO/Transport/TransportMessageType.cs new file mode 100644 index 00000000..24f9aebb --- /dev/null +++ b/ElectronNET.API/SocketIO/Transport/TransportMessageType.cs @@ -0,0 +1,8 @@ +namespace SocketIOClient.Transport +{ + public enum TransportMessageType + { + Text = 0, + Binary = 1 + } +} diff --git a/ElectronNET.API/SocketIO/Transport/TransportProtocol.cs b/ElectronNET.API/SocketIO/Transport/TransportProtocol.cs new file mode 100644 index 00000000..50ad89bb --- /dev/null +++ b/ElectronNET.API/SocketIO/Transport/TransportProtocol.cs @@ -0,0 +1,8 @@ +namespace SocketIOClient.Transport +{ + public enum TransportProtocol + { + Polling, + WebSocket + } +} diff --git a/ElectronNET.API/SocketIO/Transport/WebSocketTransport.cs b/ElectronNET.API/SocketIO/Transport/WebSocketTransport.cs new file mode 100644 index 00000000..532ac66c --- /dev/null +++ b/ElectronNET.API/SocketIO/Transport/WebSocketTransport.cs @@ -0,0 +1,92 @@ +using System; +using System.Reactive.Linq; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using SocketIOClient.JsonSerializer; + +namespace SocketIOClient.Transport +{ + public class WebSocketTransport : BaseTransport + { + public WebSocketTransport(IClientWebSocket ws, SocketIOOptions options, IJsonSerializer jsonSerializer, ILogger logger) + : base(options, jsonSerializer, logger) + { + _ws = ws; + _sendLock = new SemaphoreSlim(1, 1); + _ws.TextObservable.Subscribe(this); + _ws.BytesObservable.Subscribe(this); + } + + const int ReceiveChunkSize = 1024 * 8; + const int SendChunkSize = 1024 * 8; + + readonly IClientWebSocket _ws; + readonly SemaphoreSlim _sendLock; + + private async Task SendAsync(TransportMessageType type, byte[] bytes, CancellationToken cancellationToken) + { + try + { + await _sendLock.WaitAsync().ConfigureAwait(false); + if (type == TransportMessageType.Binary && Options.EIO == 3) + { + byte[] buffer = new byte[bytes.Length + 1]; + buffer[0] = 4; + Buffer.BlockCopy(bytes, 0, buffer, 1, bytes.Length); + bytes = buffer; + } + int pages = (int)Math.Ceiling(bytes.Length * 1.0 / SendChunkSize); + for (int i = 0; i < pages; i++) + { + int offset = i * SendChunkSize; + int length = SendChunkSize; + if (offset + length > bytes.Length) + { + length = bytes.Length - offset; + } + byte[] subBuffer = new byte[length]; + Buffer.BlockCopy(bytes, offset, subBuffer, 0, subBuffer.Length); + bool endOfMessage = pages - 1 == i; + await _ws.SendAsync(subBuffer, type, endOfMessage, cancellationToken).ConfigureAwait(false); + } + } + finally + { + _sendLock.Release(); + } + } + + public override async Task ConnectAsync(Uri uri, CancellationToken cancellationToken) + { + await _ws.ConnectAsync(uri, cancellationToken); + } + + public override async Task DisconnectAsync(CancellationToken cancellationToken) + { + await _ws.DisconnectAsync(cancellationToken); + } + + public override async Task SendAsync(Payload payload, CancellationToken cancellationToken) + { + byte[] bytes = Encoding.UTF8.GetBytes(payload.Text); + await SendAsync(TransportMessageType.Text, bytes, cancellationToken); + if (payload.Bytes != null) + { + foreach (var item in payload.Bytes) + { + await SendAsync(TransportMessageType.Binary, item, cancellationToken); + } + } + } + + public override void AddHeader(string key, string val) => _ws.AddHeader(key, val); + + public override void Dispose() + { + base.Dispose(); + _sendLock.Dispose(); + } + } +} diff --git a/ElectronNET.API/SocketIO/UriConverters/IUriConverter.cs b/ElectronNET.API/SocketIO/UriConverters/IUriConverter.cs new file mode 100644 index 00000000..923f8132 --- /dev/null +++ b/ElectronNET.API/SocketIO/UriConverters/IUriConverter.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; + +namespace SocketIOClient.UriConverters +{ + public interface IUriConverter + { + Uri GetServerUri(bool ws, Uri serverUri, int eio, string path, IEnumerable> queryParams); + } +} diff --git a/ElectronNET.API/SocketIO/UriConverters/UriConverter.cs b/ElectronNET.API/SocketIO/UriConverters/UriConverter.cs new file mode 100644 index 00000000..922ee9dc --- /dev/null +++ b/ElectronNET.API/SocketIO/UriConverters/UriConverter.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SocketIOClient.UriConverters +{ + public class UriConverter : IUriConverter + { + public Uri GetServerUri(bool ws, Uri serverUri, int eio, string path, IEnumerable> queryParams) + { + var builder = new StringBuilder(); + if (serverUri.Scheme == "https" || serverUri.Scheme == "wss") + { + builder.Append(ws ? "wss://" : "https://"); + } + else if (serverUri.Scheme == "http" || serverUri.Scheme == "ws") + { + builder.Append(ws ? "ws://" : "http://"); + } + else + { + throw new ArgumentException("Only supports 'http, https, ws, wss' protocol"); + } + builder.Append(serverUri.Host); + if (!serverUri.IsDefaultPort) + { + builder.Append(":").Append(serverUri.Port); + } + if (string.IsNullOrEmpty(path)) + { + builder.Append("/socket.io"); + } + else + { + builder.Append(path); + } + builder + .Append("/?EIO=") + .Append(eio) + .Append("&transport=") + .Append(ws ? "websocket" : "polling"); + + if (queryParams != null) + { + foreach (var item in queryParams) + { + builder.Append('&').Append(item.Key).Append('=').Append(item.Value); + } + } + + return new Uri(builder.ToString()); + } + } +} diff --git a/ElectronNET.API/Tray.cs b/ElectronNET.API/Tray.cs index c37f5fe6..50ef49d6 100644 --- a/ElectronNET.API/Tray.cs +++ b/ElectronNET.API/Tray.cs @@ -5,6 +5,7 @@ using Newtonsoft.Json.Serialization; using System; using System.Collections.Generic; +using System.Runtime.Versioning; using System.Threading.Tasks; namespace ElectronNET.API @@ -12,6 +13,9 @@ namespace ElectronNET.API /// /// Add icons and context menus to the system's notification area. /// + + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public sealed class Tray { /// @@ -46,6 +50,8 @@ public event Action OnClick /// /// macOS, Windows: Emitted when the tray icon is right clicked. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnRightClick { add @@ -75,6 +81,8 @@ public event Action OnRightClick /// /// macOS, Windows: Emitted when the tray icon is double clicked. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnDoubleClick { add @@ -104,6 +112,7 @@ public event Action OnDoubleClick /// /// Windows: Emitted when the tray balloon shows. /// + [SupportedOSPlatform("windows")] public event Action OnBalloonShow { add @@ -133,6 +142,7 @@ public event Action OnBalloonShow /// /// Windows: Emitted when the tray balloon is clicked. /// + [SupportedOSPlatform("windows")] public event Action OnBalloonClick { add @@ -163,6 +173,8 @@ public event Action OnBalloonClick /// Windows: Emitted when the tray balloon is closed /// because of timeout or user manually closes it. /// + + [SupportedOSPlatform("windows")] public event Action OnBalloonClosed { add @@ -192,7 +204,7 @@ public event Action OnBalloonClosed // TODO: Implement macOS Events private static Tray _tray; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Tray() { } @@ -222,7 +234,7 @@ internal static Tray Instance /// The menu items. /// public IReadOnlyCollection MenuItems { get { return _items.AsReadOnly(); } } - private List _items = new List(); + private readonly List _items = new(); /// /// Shows the Traybar. @@ -285,6 +297,7 @@ public void SetImage(string image) /// Sets the image associated with this tray icon when pressed on macOS. /// /// + [SupportedOSPlatform("macos")] public void SetPressedImage(string image) { BridgeConnector.Emit("tray-setPressedImage", image); @@ -303,6 +316,7 @@ public void SetToolTip(string toolTip) /// macOS: Sets the title displayed aside of the tray icon in the status bar. /// /// + [SupportedOSPlatform("macos")] public void SetTitle(string title) { BridgeConnector.Emit("tray-setTitle", title); @@ -312,6 +326,7 @@ public void SetTitle(string title) /// Windows: Displays a tray balloon. /// /// + [SupportedOSPlatform("windows")] public void DisplayBalloon(DisplayBalloonOptions options) { BridgeConnector.Emit("tray-displayBalloon", options); @@ -353,7 +368,7 @@ public void DisplayBalloon(DisplayBalloonOptions options) /// The handler public void Once(string eventName, Action fn) => Events.Instance.Once(ModuleName, eventName, fn); - private JsonSerializer _jsonSerializer = new JsonSerializer() + private readonly JsonSerializer _jsonSerializer = new() { ContractResolver = new CamelCasePropertyNamesContractResolver(), NullValueHandling = NullValueHandling.Ignore diff --git a/ElectronNET.API/WebHostBuilderExtensions.cs b/ElectronNET.API/WebHostBuilderExtensions.cs index af7cf910..6c5735f3 100644 --- a/ElectronNET.API/WebHostBuilderExtensions.cs +++ b/ElectronNET.API/WebHostBuilderExtensions.cs @@ -23,7 +23,7 @@ public static IWebHostBuilder UseElectron(this IWebHostBuilder builder, string[] if (argument.ToUpper().Contains("ELECTRONPORT")) { BridgeSettings.SocketPort = argument.ToUpper().Replace("/ELECTRONPORT=", ""); - Console.WriteLine("Use Electron Port: " + BridgeSettings.SocketPort); + BridgeConnector.Log("Use Electron Port: " + BridgeSettings.SocketPort); } else if (argument.ToUpper().Contains("ELECTRONWEBPORT")) { diff --git a/ElectronNET.API/WindowManager.cs b/ElectronNET.API/WindowManager.cs index e8869d3a..ec73cae3 100644 --- a/ElectronNET.API/WindowManager.cs +++ b/ElectronNET.API/WindowManager.cs @@ -3,9 +3,11 @@ using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; +using System.Threading; using System.Threading.Tasks; namespace ElectronNET.API @@ -16,7 +18,7 @@ namespace ElectronNET.API public sealed class WindowManager { private static WindowManager _windowManager; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal WindowManager() { } @@ -62,8 +64,18 @@ public bool IsQuitOnWindowAllClosed /// /// The browser windows. /// - public IReadOnlyCollection BrowserWindows { get { return _browserWindows.AsReadOnly(); } } - private List _browserWindows = new List(); + public IReadOnlyCollection BrowserWindows { get { return _browserWindows.Values.ToList().AsReadOnly(); } } + + /// + /// Get a browser window using the ID + /// + /// The id of the browser window + /// The window, if any + /// True if it found the window + public bool TryGetBrowserWindows(int id, out BrowserWindow window) => _browserWindows.TryGetValue(id, out window); + + + private readonly ConcurrentDictionary _browserWindows = new (); /// /// Gets the browser views. @@ -71,8 +83,16 @@ public bool IsQuitOnWindowAllClosed /// /// The browser view. /// - public IReadOnlyCollection BrowserViews { get { return _browserViews.AsReadOnly(); } } - private List _browserViews = new List(); + public IReadOnlyCollection BrowserViews { get { return _browserViews.Values.ToList().AsReadOnly(); } } + private readonly ConcurrentDictionary _browserViews = new (); + + /// + /// Get a browser view using the ID + /// + /// The id of the browser view + /// The view, if any + /// True if it found the view + public bool TryGetBrowserViews(int id, out BrowserView view) => _browserViews.TryGetValue(id, out view); /// /// Creates the window asynchronous. @@ -90,76 +110,93 @@ public async Task CreateWindowAsync(string loadUrl = "http://loca /// The options. /// The load URL. /// - public Task CreateWindowAsync(BrowserWindowOptions options, string loadUrl = "http://localhost") + public async Task CreateWindowAsync(BrowserWindowOptions options, string loadUrl = "http://localhost") { + BootstrapUpdateOpenIDsEvent(); + var taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - BridgeConnector.On("BrowserWindowCreated", (id) => + var guid = Guid.NewGuid().ToString(); + + BridgeConnector.Once("BrowserWindowCreated" + guid, (id) => { - BridgeConnector.Off("BrowserWindowCreated"); + var browserWindow = new BrowserWindow(id); - BrowserWindow browserWindow = new BrowserWindow(id); - _browserWindows.Add(browserWindow); + _browserWindows[id] = browserWindow; taskCompletionSource.SetResult(browserWindow); }); - BridgeConnector.Off("BrowserWindowClosed"); - BridgeConnector.On("BrowserWindowClosed", (browserWindowIds) => - { - for (int index = 0; index < _browserWindows.Count; index++) - { - if (!browserWindowIds.Contains(_browserWindows[index].Id)) - { - _browserWindows.RemoveAt(index); - } - } - }); - if (loadUrl.ToUpper() == "HTTP://LOCALHOST") + if (string.Equals(loadUrl, "HTTP://LOCALHOST", StringComparison.InvariantCultureIgnoreCase)) { loadUrl = $"{loadUrl}:{BridgeSettings.WebPort}"; } // Workaround Windows 10 / Electron Bug // https://github.com/electron/electron/issues/4045 - if (isWindows10()) + if (IsWindows10()) { - options.Width = options.Width + 14; - options.Height = options.Height + 7; + options.Width += 14; + options.Height += 7; } if (options.X == -1 && options.Y == -1) { - options.X = 0; + options.X = 0; //This is manually removed by the browserWindows.js code before creating the window options.Y = 0; - BridgeConnector.Emit("createBrowserWindow", options, loadUrl); + BridgeConnector.Emit("createBrowserWindow", guid, JObject.FromObject(options, _keepDefaultValuesSerializer), loadUrl); } else { // Workaround Windows 10 / Electron Bug // https://github.com/electron/electron/issues/4045 - if (isWindows10()) + if (IsWindows10()) { - options.X = options.X - 7; + options.X -= 7; } - var ownjsonSerializer = new JsonSerializer() - { - ContractResolver = new CamelCasePropertyNamesContractResolver(), - NullValueHandling = NullValueHandling.Ignore - }; - - BridgeConnector.Emit("createBrowserWindow", JObject.FromObject(options, ownjsonSerializer), loadUrl); + BridgeConnector.Emit("createBrowserWindow", guid, JObject.FromObject(options, _keepDefaultValuesSerializer), loadUrl); } - return taskCompletionSource.Task; + return await taskCompletionSource.Task; } - private bool isWindows10() + + private bool _hasClosedEvent = false; + private readonly object _hasClosedEventLock = new(); + private void BootstrapUpdateOpenIDsEvent() { - return RuntimeInformation.OSDescription.Contains("Windows 10"); + if (!_hasClosedEvent) + { + lock(_hasClosedEventLock) + { + if(!_hasClosedEvent) + { + BridgeConnector.On("BrowserWindowUpdateOpenIDs", (browserWindowIdsStillOpen) => + { + if (browserWindowIdsStillOpen.Any()) + { + foreach (var id in _browserWindows.Keys.ToArray()) + { + if (!browserWindowIdsStillOpen.Contains(id)) _browserWindows.TryRemove(id, out _); + } + } + else + { + _browserWindows.Clear(); + } + }); + _hasClosedEvent = true; + } + } + } + } + + private bool IsWindows10() + { + return OperatingSystem.IsWindowsVersionAtLeast(10); } /// @@ -180,30 +217,41 @@ public Task CreateBrowserViewAsync() /// /// /// - public Task CreateBrowserViewAsync(BrowserViewConstructorOptions options) + public async Task CreateBrowserViewAsync(BrowserViewConstructorOptions options) { + var guid = Guid.NewGuid().ToString(); + var taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - BridgeConnector.On("BrowserViewCreated", (id) => + BridgeConnector.Once("BrowserViewCreated" + guid, (id) => { - BridgeConnector.Off("BrowserViewCreated"); - - BrowserView browserView = new BrowserView(id); - - _browserViews.Add(browserView); - + var browserView = new BrowserView(id); + _browserViews[id] = browserView; taskCompletionSource.SetResult(browserView); }); - var keepDefaultValuesSerializer = new JsonSerializer() - { - ContractResolver = new CamelCasePropertyNamesContractResolver(), - NullValueHandling = NullValueHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Include - }; - BridgeConnector.Emit("createBrowserView", JObject.FromObject(options, keepDefaultValuesSerializer)); + BridgeConnector.Emit("createBrowserView", guid, JObject.FromObject(options, _keepDefaultValuesSerializer)); + + return await taskCompletionSource.Task; + } + - return taskCompletionSource.Task; + /// + /// Destroy all windows. + /// + /// Number of windows destroyed + public async Task DestroyAllWindows() + { + var destroyed = await BridgeConnector.OnResult("browserWindowDestroyAll", "browserWindowDestroyAll-completed"); + _browserViews.Clear(); + _browserWindows.Clear(); + return destroyed; } + + private static readonly JsonSerializer _keepDefaultValuesSerializer = new() + { + ContractResolver = new CamelCasePropertyNamesContractResolver(), + NullValueHandling = NullValueHandling.Ignore + }; } } diff --git a/ElectronNET.CLI/Commands/Actions/DeployEmbeddedElectronFiles.cs b/ElectronNET.CLI/Commands/Actions/DeployEmbeddedElectronFiles.cs index 64b26d43..840d6fea 100644 --- a/ElectronNET.CLI/Commands/Actions/DeployEmbeddedElectronFiles.cs +++ b/ElectronNET.CLI/Commands/Actions/DeployEmbeddedElectronFiles.cs @@ -30,6 +30,7 @@ public static void Do(string tempPath) EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "globalShortcut.js", "api."); EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "shell.js", "api."); EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "screen.js", "api."); + EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "desktopCapturer.js", "api."); EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "clipboard.js", "api."); EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "autoUpdater.js", "api."); EmbeddedFileHelper.DeployEmbeddedFile(hostApiFolder, "browserView.js", "api."); diff --git a/ElectronNET.CLI/Commands/Actions/DirectoryCopy.cs b/ElectronNET.CLI/Commands/Actions/DirectoryCopy.cs index 39ded697..2509f54f 100644 --- a/ElectronNET.CLI/Commands/Actions/DirectoryCopy.cs +++ b/ElectronNET.CLI/Commands/Actions/DirectoryCopy.cs @@ -8,16 +8,14 @@ public static class DirectoryCopy public static void Do(string sourceDirName, string destDirName, bool copySubDirs, List ignoredSubDirs) { // Get the subdirectories for the specified directory. - DirectoryInfo dir = new DirectoryInfo(sourceDirName); + var dir = new DirectoryInfo(sourceDirName); if (!dir.Exists) { - throw new DirectoryNotFoundException( - "Source directory does not exist or could not be found: " - + sourceDirName); + throw new DirectoryNotFoundException($"Source directory does not exist or could not be found: {sourceDirName}"); } - DirectoryInfo[] dirs = dir.GetDirectories(); + var dirs = dir.GetDirectories(); // If the destination directory doesn't exist, create it. if (!Directory.Exists(destDirName)) { @@ -25,13 +23,14 @@ public static void Do(string sourceDirName, string destDirName, bool copySubDirs } else { - DirectoryInfo targetDir = new DirectoryInfo(destDirName); + var targetDir = new DirectoryInfo(destDirName); - foreach (FileInfo fileDel in targetDir.EnumerateFiles()) + foreach (var fileDel in targetDir.EnumerateFiles()) { fileDel.Delete(); } - foreach (DirectoryInfo dirDel in targetDir.EnumerateDirectories()) + + foreach (var dirDel in targetDir.EnumerateDirectories()) { dirDel.Delete(true); } @@ -41,8 +40,8 @@ public static void Do(string sourceDirName, string destDirName, bool copySubDirs // Get the files in the directory and copy them to the new location. - FileInfo[] files = dir.GetFiles(); - foreach (FileInfo file in files) + var files = dir.GetFiles(); + foreach (var file in files) { string temppath = Path.Combine(destDirName, file.Name); file.CopyTo(temppath, false); @@ -51,7 +50,7 @@ public static void Do(string sourceDirName, string destDirName, bool copySubDirs // If copying subdirectories, copy them and their contents to new location. if (copySubDirs) { - foreach (DirectoryInfo subdir in dirs) + foreach (var subdir in dirs) { if (ignoredSubDirs.Contains(subdir.Name)) { diff --git a/ElectronNET.CLI/Commands/Actions/GetTargetPlatformInformation.cs b/ElectronNET.CLI/Commands/Actions/GetTargetPlatformInformation.cs index a12d4275..987e741c 100644 --- a/ElectronNET.CLI/Commands/Actions/GetTargetPlatformInformation.cs +++ b/ElectronNET.CLI/Commands/Actions/GetTargetPlatformInformation.cs @@ -27,6 +27,10 @@ public static GetTargetPlatformInformationResult Do(string desiredPlatform, stri netCorePublishRid = "osx-x64"; electronPackerPlatform = "mac"; break; + case "osx-arm64": + netCorePublishRid = "osx-arm64"; + electronPackerPlatform = "mac"; + break; case "linux": netCorePublishRid = "linux-x64"; electronPackerPlatform = "linux"; @@ -46,12 +50,22 @@ public static GetTargetPlatformInformationResult Do(string desiredPlatform, stri netCorePublishRid = $"win-x{(Environment.Is64BitOperatingSystem ? "64" : "86")}"; electronPackerPlatform = "win"; } - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { - netCorePublishRid = "osx-x64"; - electronPackerPlatform = "mac"; + if (RuntimeInformation.OSArchitecture.Equals(Architecture.Arm64)) + { + //Apple Silicon Mac: + netCorePublishRid = "osx-arm64"; + electronPackerPlatform = "mac"; + } + else + { + //Intel Mac: + netCorePublishRid = "osx-x64"; + electronPackerPlatform = "mac"; + } } - if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { netCorePublishRid = "linux-x64"; electronPackerPlatform = "linux"; diff --git a/ElectronNET.CLI/Commands/AddCommand.cs b/ElectronNET.CLI/Commands/AddCommand.cs index cbfb0dd6..9d002407 100644 --- a/ElectronNET.CLI/Commands/AddCommand.cs +++ b/ElectronNET.CLI/Commands/AddCommand.cs @@ -16,14 +16,14 @@ public class AddCommand : ICommand public static IList CommandOptions { get; set; } = new List(); - private string[] _args; + private readonly string[] _args; public AddCommand(string[] args) { _args = args; } - private static string ElectronHostHookFolderName = "ElectronHostHook"; + private const string ElectronHostHookFolderName = "ElectronHostHook"; public Task ExecuteAsync() { @@ -124,11 +124,10 @@ private static bool EditProjectFile(string projectFile) OmitXmlDeclaration = true, Indent = true }; - using (XmlWriter xw = XmlWriter.Create(stream, xws)) - { - xmlDocument.Save(xw); - } + + using XmlWriter xw = XmlWriter.Create(stream, xws); + xmlDocument.Save(xw); } Console.WriteLine($"Publish setting added in csproj/fsproj!"); diff --git a/ElectronNET.CLI/Commands/BuildCommand.cs b/ElectronNET.CLI/Commands/BuildCommand.cs index 080998b7..cc37eab0 100644 --- a/ElectronNET.CLI/Commands/BuildCommand.cs +++ b/ElectronNET.CLI/Commands/BuildCommand.cs @@ -1,7 +1,8 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text.RegularExpressions; using System.Threading.Tasks; using ElectronNET.CLI.Commands.Actions; @@ -9,31 +10,35 @@ namespace ElectronNET.CLI.Commands { public class BuildCommand : ICommand { + private const string _defaultElectronVersion = "19.0.9"; + public const string COMMAND_NAME = "build"; public const string COMMAND_DESCRIPTION = "Build your Electron Application."; - public static string COMMAND_ARGUMENTS = "Needed: '/target' with params 'win/osx/linux' to build for a typical app or use 'custom' and specify .NET Core build config & electron build config" + Environment.NewLine + - " for custom target, check .NET Core RID Catalog and Electron build target/" + Environment.NewLine + - " e.g. '/target win' or '/target custom \"win7-x86;win\"'" + Environment.NewLine + - "Optional: '/dotnet-configuration' with the desired .NET Core build config e.g. release or debug. Default = Release" + Environment.NewLine + - "Optional: '/electron-arch' to specify the resulting electron processor architecture (e.g. ia86 for x86 builds). Be aware to use the '/target custom' param as well!" + Environment.NewLine + - "Optional: '/electron-params' specify any other valid parameter, which will be routed to the electron-packager." + Environment.NewLine + - "Optional: '/relative-path' to specify output a subdirectory for output." + Environment.NewLine + - "Optional: '/absolute-path to specify and absolute path for output." + Environment.NewLine + - "Optional: '/package-json' to specify a custom package.json file." + Environment.NewLine + - "Optional: '/install-modules' to force node module install. Implied by '/package-json'" + Environment.NewLine + - "Optional: '/Version' to specify the version that should be applied to both the `dotnet publish` and `electron-builder` commands. Implied by '/Version'" + Environment.NewLine + - "Optional: '/p:[property]' or '/property:[property]' to pass in dotnet publish properties. Example: '/property:Version=1.0.0' to override the FileVersion" + Environment.NewLine + - "Full example for a 32bit debug build with electron prune: build /target custom win7-x86;win32 /dotnet-configuration Debug /electron-arch ia32 /electron-params \"--prune=true \""; + public const string COMMAND_ARGUMENTS = +@"Needed: '/target' with params 'win/osx/linux' to build for a typical app or use 'custom' and specify .NET Core build config & electron build config +for custom target, check .NET Core RID Catalog and Electron build target/ +e.g. '/target win' or '/target custom ""win7-x86;win""' +Optional: '/dotnet-configuration' with the desired .NET Core build config e.g. release or debug. Default = Release +Optional: '/electron-arch' to specify the resulting electron processor architecture (e.g. ia86 for x86 builds). Be aware to use the '/target custom' param as well! +Optional: '/electron-params' specify any other valid parameter, which will be routed to the electron-packager. +Optional: '/relative-path' to specify output a subdirectory for output. +Optional: '/absolute-path to specify and absolute path for output. +Optional: '/package-json' to specify a custom package.json file. +Optional: '/install-modules' to force node module install. Implied by '/package-json' +Optional: '/Version' to specify the version that should be applied to both the `dotnet publish` and `electron-builder` commands. Implied by '/Version' +Optional: '/p:[property]' or '/property:[property]' to pass in dotnet publish properties. Example: '/property:Version=1.0.0' to override the FileVersion +Full example for a 32bit debug build with electron prune: build /target custom win7-x86;win32 /dotnet-configuration Debug /electron-arch ia32 /electron-params ""--prune=true """; public static IList CommandOptions { get; set; } = new List(); - private string[] _args; + private readonly string[] _args; public BuildCommand(string[] args) { _args = args; } + private const string _paramTarget = "target"; private const string _paramDotNetConfig = "dotnet-configuration"; private const string _paramElectronArch = "electron-arch"; @@ -173,16 +178,45 @@ public Task ExecuteAsync() Console.WriteLine("Executing electron magic in this directory: " + buildPath); string electronArch = "x64"; + + if (platformInfo.NetCorePublishRid == "osx-arm64") //Apple Silicon Mac + { + electronArch = "arm64"; + } + if (parser.Arguments.ContainsKey(_paramElectronArch)) { electronArch = parser.Arguments[_paramElectronArch][0]; } - string electronVersion = "13.1.5"; + var electronVersion = ""; if (parser.Arguments.ContainsKey(_paramElectronVersion)) { electronVersion = parser.Arguments[_paramElectronVersion][0]; } + else + { + //try getting version from project + foreach(var project in Directory.GetFiles(Directory.GetCurrentDirectory(), "*.csproj")) + { + var projectXML = File.ReadAllText(project); + var match = Regex.Match(projectXML, @""); + if (match.Success) + { + var candidate = match.Groups[1].Value; + var majorMinorRevision = string.Join(".",candidate.Split(new char[] { '.' }).Take(3)); + electronVersion = majorMinorRevision; + Console.WriteLine($"Found electron version {majorMinorRevision} in project file {project}"); + break; + } + } + } + + if (string.IsNullOrWhiteSpace(electronVersion)) + { + electronVersion = _defaultElectronVersion; + } + string electronParams = ""; if (parser.Arguments.ContainsKey(_paramElectronParams)) diff --git a/ElectronNET.CLI/Commands/InitCommand.cs b/ElectronNET.CLI/Commands/InitCommand.cs index c2539200..88e7bd5d 100644 --- a/ElectronNET.CLI/Commands/InitCommand.cs +++ b/ElectronNET.CLI/Commands/InitCommand.cs @@ -25,8 +25,8 @@ public InitCommand(string[] args) _parser.Parse(args); } - private static string _aspCoreProjectPath = "project-path"; - private static string _manifest = "manifest"; + private const string _aspCoreProjectPath = "project-path"; + private const string _manifest = "manifest"; public Task ExecuteAsync() { diff --git a/ElectronNET.CLI/Commands/StartElectronCommand.cs b/ElectronNET.CLI/Commands/StartElectronCommand.cs index ff013cdc..11672fad 100644 --- a/ElectronNET.CLI/Commands/StartElectronCommand.cs +++ b/ElectronNET.CLI/Commands/StartElectronCommand.cs @@ -15,7 +15,7 @@ public class StartElectronCommand : ICommand public const string COMMAND_ARGUMENTS = " from ASP.NET Core Project."; public static IList CommandOptions { get; set; } = new List(); - private string[] _args; + private readonly string[] _args; public StartElectronCommand(string[] args) { diff --git a/ElectronNET.CLI/Commands/VersionCommand.cs b/ElectronNET.CLI/Commands/VersionCommand.cs index c8f60f83..0d2637ce 100644 --- a/ElectronNET.CLI/Commands/VersionCommand.cs +++ b/ElectronNET.CLI/Commands/VersionCommand.cs @@ -12,7 +12,7 @@ public class VersionCommand : ICommand public const string COMMAND_ARGUMENTS = ""; public static IList CommandOptions { get; set; } = new List(); - public VersionCommand(string[] args) + public VersionCommand() { } diff --git a/ElectronNET.CLI/ElectronNET.CLI.csproj b/ElectronNET.CLI/ElectronNET.CLI.csproj index 1569a433..8a6a95c0 100644 --- a/ElectronNET.CLI/ElectronNET.CLI.csproj +++ b/ElectronNET.CLI/ElectronNET.CLI.csproj @@ -3,7 +3,7 @@ Exe - net5.0 + net6.0 dotnet-electronize-h5 electronize-h5 @@ -66,6 +66,7 @@ + @@ -77,7 +78,7 @@ - + all runtime; build; native; contentfiles; analyzers diff --git a/ElectronNET.CLI/ProcessHelper.cs b/ElectronNET.CLI/ProcessHelper.cs index 5f7d6cc1..9ac02f96 100644 --- a/ElectronNET.CLI/ProcessHelper.cs +++ b/ElectronNET.CLI/ProcessHelper.cs @@ -7,7 +7,7 @@ namespace ElectronNET.CLI { public class ProcessHelper { - private static ConcurrentDictionary _activeProcess = new(); + private static readonly ConcurrentDictionary _activeProcess = new(); public static void KillActive() { diff --git a/ElectronNET.CLI/Program.cs b/ElectronNET.CLI/Program.cs index 891b15ef..8621efc6 100644 --- a/ElectronNET.CLI/Program.cs +++ b/ElectronNET.CLI/Program.cs @@ -42,7 +42,7 @@ static async Task Main(string[] args) command = new AddCommand(args.Skip(1).ToArray()); break; case VersionCommand.COMMAND_NAME: - command = new VersionCommand(args.Skip(1).ToArray()); + command = new VersionCommand(); break; case "--help": case "--h": @@ -90,27 +90,27 @@ private static void PrintUsage() Console.WriteLine("\t"); Console.WriteLine("Commands to start the Electron Application:"); Console.WriteLine("\t"); - Console.WriteLine($"\t{StartElectronCommand.COMMAND_NAME.PadRight(NAME_WIDTH)} {StartElectronCommand.COMMAND_DESCRIPTION}"); + Console.WriteLine($"\t{StartElectronCommand.COMMAND_NAME,-NAME_WIDTH} {StartElectronCommand.COMMAND_DESCRIPTION}"); Console.WriteLine("\t"); Console.WriteLine("Command to build the Electron Application:"); Console.WriteLine("\t"); - Console.WriteLine($"\t{BuildCommand.COMMAND_NAME.PadRight(NAME_WIDTH)} {BuildCommand.COMMAND_DESCRIPTION}"); + Console.WriteLine($"\t{BuildCommand.COMMAND_NAME,-NAME_WIDTH} {BuildCommand.COMMAND_DESCRIPTION}"); Console.WriteLine("\t"); Console.WriteLine("Command to init the Electron Application:"); Console.WriteLine("\t"); - Console.WriteLine($"\t{InitCommand.COMMAND_NAME.PadRight(NAME_WIDTH)} {InitCommand.COMMAND_DESCRIPTION}"); + Console.WriteLine($"\t{InitCommand.COMMAND_NAME,-NAME_WIDTH} {InitCommand.COMMAND_DESCRIPTION}"); Console.WriteLine("\t"); Console.WriteLine("Command to add a custom npm packages to the Electron Application:"); Console.WriteLine("\t"); - Console.WriteLine($"\t{AddCommand.COMMAND_NAME.PadRight(NAME_WIDTH)} {AddCommand.COMMAND_DESCRIPTION}"); + Console.WriteLine($"\t{AddCommand.COMMAND_NAME,-NAME_WIDTH} {AddCommand.COMMAND_DESCRIPTION}"); Console.WriteLine("\t"); Console.WriteLine("Commands to see the current ElectronNET version number:"); Console.WriteLine("\t"); - Console.WriteLine($"\t{VersionCommand.COMMAND_NAME.PadRight(NAME_WIDTH)} {VersionCommand.COMMAND_DESCRIPTION}"); + Console.WriteLine($"\t{VersionCommand.COMMAND_NAME,-NAME_WIDTH} {VersionCommand.COMMAND_DESCRIPTION}"); Console.WriteLine("\t"); Console.WriteLine("\t"); @@ -172,7 +172,7 @@ private static void PrintUsage(string command, string description, IList(); + } else + { values.Add(arg); + } } if (currentName != "") Arguments[currentName] = values.ToArray(); diff --git a/ElectronNET.Host/Web.config b/ElectronNET.Host/Web.config new file mode 100644 index 00000000..46ac13b1 --- /dev/null +++ b/ElectronNET.Host/Web.config @@ -0,0 +1,15 @@ + + + + + + + + \ No newline at end of file diff --git a/ElectronNET.Host/api/app.js b/ElectronNET.Host/api/app.js index e9fb535d..5e5a6693 100644 --- a/ElectronNET.Host/api/app.js +++ b/ElectronNET.Host/api/app.js @@ -1,23 +1,30 @@ "use strict"; let isQuitWindowAllClosed = true, electronSocket; let appWindowAllClosedEventId; -module.exports = (socket, app) => { +module.exports = (socket, app, firstTime) => { electronSocket = socket; - // By default, quit when all windows are closed - app.on('window-all-closed', () => { - // On macOS it is common for applications and their menu bar - // to stay active until the user quits explicitly with Cmd + Q - if (process.platform !== 'darwin' && isQuitWindowAllClosed) { - app.quit(); - } - else if (appWindowAllClosedEventId) { - // If the user is on macOS - // - OR - - // If the user has indicated NOT to quit when all windows are closed, - // emit the event. - electronSocket.emit('app-window-all-closed' + appWindowAllClosedEventId); - } - }); + if (firstTime) { + // By default, quit when all windows are closed + app.on('window-all-closed', () => { + // On macOS it is common for applications and their menu bar + // to stay active until the user quits explicitly with Cmd + Q + if (process.platform !== 'darwin' && isQuitWindowAllClosed) { + app.quit(); + } + else if (appWindowAllClosedEventId) { + // If the user is on macOS + // - OR - + // If the user has indicated NOT to quit when all windows are closed, + // emit the event. + electronSocket.emit('app-window-all-closed' + appWindowAllClosedEventId); + } + }); + app.on('activate', () => { + // On macOS it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + electronSocket.emit('app-activate'); + }); + } socket.on('quit-app-window-all-closed-event', (quit) => { isQuitWindowAllClosed = quit; }); diff --git a/ElectronNET.Host/api/app.js.map b/ElectronNET.Host/api/app.js.map index 25e66972..88a91317 100644 --- a/ElectronNET.Host/api/app.js.map +++ b/ElectronNET.Host/api/app.js.map @@ -1 +1 @@ -{"version":3,"file":"app.js","sourceRoot":"","sources":["app.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"app.js","sourceRoot":"","sources":["app.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/ElectronNET.Host/api/app.ts b/ElectronNET.Host/api/app.ts index 1f04f9f0..ae39126d 100644 --- a/ElectronNET.Host/api/app.ts +++ b/ElectronNET.Host/api/app.ts @@ -1,24 +1,32 @@ -import { Socket } from "net"; +import {Socket} from "net"; let isQuitWindowAllClosed = true, electronSocket; let appWindowAllClosedEventId; -export = (socket: Socket, app: Electron.App) => { +export = (socket: Socket, app: Electron.App, firstTime: boolean) => { electronSocket = socket; - // By default, quit when all windows are closed - app.on('window-all-closed', () => { - // On macOS it is common for applications and their menu bar - // to stay active until the user quits explicitly with Cmd + Q - if (process.platform !== 'darwin' && isQuitWindowAllClosed) { - app.quit(); - } else if (appWindowAllClosedEventId) { - // If the user is on macOS - // - OR - - // If the user has indicated NOT to quit when all windows are closed, - // emit the event. - electronSocket.emit('app-window-all-closed' + appWindowAllClosedEventId); - } - }); + if (firstTime) { + // By default, quit when all windows are closed + app.on('window-all-closed', () => { + // On macOS it is common for applications and their menu bar + // to stay active until the user quits explicitly with Cmd + Q + if (process.platform !== 'darwin' && isQuitWindowAllClosed) { + app.quit(); + } else if (appWindowAllClosedEventId) { + // If the user is on macOS + // - OR - + // If the user has indicated NOT to quit when all windows are closed, + // emit the event. + electronSocket.emit('app-window-all-closed' + appWindowAllClosedEventId); + } + }); + + app.on('activate', () => { + // On macOS it's common to re-create a window in the app when the + // dock icon is clicked and there are no other windows open. + electronSocket.emit('app-activate'); + }); + } socket.on('quit-app-window-all-closed-event', (quit) => { isQuitWindowAllClosed = quit; @@ -116,11 +124,11 @@ export = (socket: Socket, app: Electron.App) => { let error = {}; if (options) { - const nativeImage = await app.getFileIcon(path, options).catch((errorFileIcon) => error = errorFileIcon); + const nativeImage = await app.getFileIcon(path, options).catch((errorFileIcon) => error = errorFileIcon); electronSocket.emit('appGetFileIconCompleted', [error, nativeImage]); } else { - const nativeImage = await app.getFileIcon(path).catch((errorFileIcon) => error = errorFileIcon); + const nativeImage = await app.getFileIcon(path).catch((errorFileIcon) => error = errorFileIcon); electronSocket.emit('appGetFileIconCompleted', [error, nativeImage]); } @@ -190,7 +198,7 @@ export = (socket: Socket, app: Electron.App) => { electronSocket.emit('appRequestSingleInstanceLockCompleted', success); app.on('second-instance', (event, args = [], workingDirectory = '') => { - electronSocket.emit('secondInstance', [args, workingDirectory]); + electronSocket.emit('secondInstance', {args: args, workingDirectory: workingDirectory}); }); }); diff --git a/ElectronNET.Host/api/autoUpdater.js b/ElectronNET.Host/api/autoUpdater.js index 3ba69caa..683c1d44 100644 --- a/ElectronNET.Host/api/autoUpdater.js +++ b/ElectronNET.Host/api/autoUpdater.js @@ -1,7 +1,8 @@ "use strict"; const electron_updater_1 = require("electron-updater"); +const electron_1 = require("electron"); let electronSocket; -module.exports = (socket) => { +module.exports = (socket, app) => { electronSocket = socket; socket.on('register-autoUpdater-error-event', (id) => { electron_updater_1.autoUpdater.on('error', (error) => { @@ -100,7 +101,31 @@ module.exports = (socket) => { }); }); socket.on('autoUpdaterQuitAndInstall', async (isSilent, isForceRunAfter) => { - electron_updater_1.autoUpdater.quitAndInstall(isSilent, isForceRunAfter); + console.log('running autoUpdaterQuitAndInstall'); + + app.removeAllListeners("window-all-closed"); + + const windows = electron_1.BrowserWindow.getAllWindows(); + if (windows && windows.length) { + windows.forEach(w => { + try { + w.removeAllListeners('close'); + w.removeAllListeners('closed'); + w.destroy(); + } + catch { + //ignore, probably already destroyed + } + }); + } + //The call to quitAndInstall needs to happen after the windows + //get a chance to close and release resources, so it must be done on a timeout + setTimeout(() => { + console.log('running autoUpdater.quitAndInstall'); + console.log('isSilent:' + isSilent); + console.log('isForceRunAfter:' + isForceRunAfter); + electron_updater_1.autoUpdater.quitAndInstall(isSilent, isForceRunAfter); + }, 100); }); socket.on('autoUpdaterDownloadUpdate', async (guid) => { const downloadedPath = await electron_updater_1.autoUpdater.downloadUpdate(); diff --git a/ElectronNET.Host/api/autoUpdater.js.map b/ElectronNET.Host/api/autoUpdater.js.map index 3e9bdd2c..425f2a94 100644 --- a/ElectronNET.Host/api/autoUpdater.js.map +++ b/ElectronNET.Host/api/autoUpdater.js.map @@ -1 +1 @@ -{"version":3,"file":"autoUpdater.js","sourceRoot":"","sources":["autoUpdater.ts"],"names":[],"mappings":";AACA,uDAA+C;AAC/C,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IAExB,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,CAAC,EAAE,EAAE,EAAE;QACjD,8BAAW,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YAC9B,cAAc,CAAC,IAAI,CAAC,mBAAmB,GAAG,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gDAAgD,EAAE,CAAC,EAAE,EAAE,EAAE;QAC/D,8BAAW,CAAC,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;YACvC,cAAc,CAAC,IAAI,CAAC,iCAAiC,GAAG,EAAE,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,6CAA6C,EAAE,CAAC,EAAE,EAAE,EAAE;QAC5D,8BAAW,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,UAAU,EAAE,EAAE;YAC9C,cAAc,CAAC,IAAI,CAAC,8BAA8B,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iDAAiD,EAAE,CAAC,EAAE,EAAE,EAAE;QAChE,8BAAW,CAAC,EAAE,CAAC,sBAAsB,EAAE,CAAC,UAAU,EAAE,EAAE;YAClD,cAAc,CAAC,IAAI,CAAC,kCAAkC,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;QAC7E,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8CAA8C,EAAE,CAAC,EAAE,EAAE,EAAE;QAC7D,8BAAW,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,YAAY,EAAE,EAAE;YACjD,cAAc,CAAC,IAAI,CAAC,+BAA+B,GAAG,EAAE,EAAE,YAAY,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8CAA8C,EAAE,CAAC,EAAE,EAAE,EAAE;QAC7D,8BAAW,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,UAAU,EAAE,EAAE;YAC/C,cAAc,CAAC,IAAI,CAAC,+BAA+B,GAAG,EAAE,EAAE,UAAU,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,mBAAmB;IAEnB,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC3C,cAAc,CAAC,IAAI,CAAC,oCAAoC,EAAE,8BAAW,CAAC,YAAY,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,CAAC,KAAK,EAAE,EAAE;QAChD,8BAAW,CAAC,YAAY,GAAG,KAAK,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QACnD,cAAc,CAAC,IAAI,CAAC,4CAA4C,EAAE,8BAAW,CAAC,oBAAoB,CAAC,CAAC;IACxG,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,sCAAsC,EAAE,CAAC,KAAK,EAAE,EAAE;QACxD,8BAAW,CAAC,oBAAoB,GAAG,KAAK,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QAC9C,cAAc,CAAC,IAAI,CAAC,uCAAuC,EAAE,8BAAW,CAAC,eAAe,CAAC,CAAC;IAC9F,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,CAAC,KAAK,EAAE,EAAE;QACnD,8BAAW,CAAC,eAAe,GAAG,KAAK,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,+BAA+B,EAAE,GAAG,EAAE;QAC5C,cAAc,CAAC,IAAI,CAAC,qCAAqC,EAAE,8BAAW,CAAC,aAAa,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,+BAA+B,EAAE,CAAC,KAAK,EAAE,EAAE;QACjD,8BAAW,CAAC,aAAa,GAAG,KAAK,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QAC7C,cAAc,CAAC,IAAI,CAAC,sCAAsC,EAAE,8BAAW,CAAC,cAAc,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gCAAgC,EAAE,CAAC,KAAK,EAAE,EAAE;QAClD,8BAAW,CAAC,cAAc,GAAG,KAAK,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QAC/C,cAAc,CAAC,IAAI,CAAC,wCAAwC,EAAE,8BAAW,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;IACtG,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,CAAC,KAAK,EAAE,EAAE;QACpD,8BAAW,CAAC,gBAAgB,GAAG,KAAK,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QAC7C,cAAc,CAAC,IAAI,CAAC,sCAAsC,EAAE,8BAAW,CAAC,cAAc,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACtC,cAAc,CAAC,IAAI,CAAC,+BAA+B,EAAE,8BAAW,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,KAAK,EAAE,EAAE;QAC3C,8BAAW,CAAC,OAAO,GAAG,KAAK,CAAC;IAChC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;QAC7C,cAAc,CAAC,IAAI,CAAC,sCAAsC,EAAE,8BAAW,CAAC,cAAc,CAAC,CAAC;IAC5F,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gCAAgC,EAAE,CAAC,KAAK,EAAE,EAAE;QAClD,8BAAW,CAAC,cAAc,GAAG,KAAK,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,qCAAqC,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAC5D,8BAAW,CAAC,wBAAwB,EAAE,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE,EAAE;YAC9D,cAAc,CAAC,IAAI,CAAC,6CAA6C,GAAG,IAAI,EAAE,iBAAiB,CAAC,CAAC;QACjG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACf,cAAc,CAAC,IAAI,CAAC,0CAA0C,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC;QAClF,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,4BAA4B,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACnD,8BAAW,CAAC,eAAe,EAAE,CAAC,IAAI,CAAC,CAAC,iBAAiB,EAAE,EAAE;YACrD,cAAc,CAAC,IAAI,CAAC,oCAAoC,GAAG,IAAI,EAAE,iBAAiB,CAAC,CAAC;QACxF,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACf,cAAc,CAAC,IAAI,CAAC,iCAAiC,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC;QACzE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,2BAA2B,EAAE,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,EAAE;QACvE,8BAAW,CAAC,cAAc,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,2BAA2B,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAClD,MAAM,cAAc,GAAG,MAAM,8BAAW,CAAC,cAAc,EAAE,CAAC;QAC1D,cAAc,CAAC,IAAI,CAAC,mCAAmC,GAAG,IAAI,EAAE,cAAc,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,uBAAuB,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAC9C,MAAM,OAAO,GAAG,MAAM,8BAAW,CAAC,UAAU,EAAE,CAAC;QAC/C,cAAc,CAAC,IAAI,CAAC,+BAA+B,GAAG,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"autoUpdater.js","sourceRoot":"","sources":["autoUpdater.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/ElectronNET.Host/api/autoUpdater.ts b/ElectronNET.Host/api/autoUpdater.ts index f72c5d18..34715a2a 100644 --- a/ElectronNET.Host/api/autoUpdater.ts +++ b/ElectronNET.Host/api/autoUpdater.ts @@ -1,8 +1,10 @@ -import { Socket } from 'net'; -import { autoUpdater } from 'electron-updater'; +import {Socket} from 'net'; +import {autoUpdater} from 'electron-updater'; +import {BrowserWindow} from 'electron'; + let electronSocket; -export = (socket: Socket) => { +export = (socket: Socket, app: Electron.App) => { electronSocket = socket; socket.on('register-autoUpdater-error-event', (id) => { @@ -128,7 +130,30 @@ export = (socket: Socket) => { }); socket.on('autoUpdaterQuitAndInstall', async (isSilent, isForceRunAfter) => { - autoUpdater.quitAndInstall(isSilent, isForceRunAfter); + console.log('running autoUpdaterQuitAndInstall'); + + app.removeAllListeners("window-all-closed"); + const windows = BrowserWindow.getAllWindows(); + if (windows && windows.length) { + windows.forEach(w => { + try { + w.removeAllListeners('close'); + w.removeAllListeners('closed'); + w.destroy(); + } catch { + //ignore, probably already destroyed + } + }); + } + + //The call to quitAndInstall needs to happen after the windows + //get a chance to close and release resources, so it must be done on a timeout + setTimeout(() => { + console.log('running autoUpdater.quitAndInstall'); + console.log('isSilent:' + isSilent); + console.log('isForceRunAfter:' + isForceRunAfter); + autoUpdater.quitAndInstall(isSilent, isForceRunAfter); + }, 100); }); socket.on('autoUpdaterDownloadUpdate', async (guid) => { diff --git a/ElectronNET.Host/api/browserView.js b/ElectronNET.Host/api/browserView.js index b0d23cc4..b992b17e 100644 --- a/ElectronNET.Host/api/browserView.js +++ b/ElectronNET.Host/api/browserView.js @@ -7,7 +7,7 @@ let browserView, electronSocket; const proxyToCredentialsMap = (global['proxyToCredentialsMap'] = global['proxyToCredentialsMap'] || []); const browserViewApi = (socket) => { electronSocket = socket; - socket.on('createBrowserView', (options) => { + socket.on('createBrowserView', (guid, options) => { if (!hasOwnChildreen(options, 'webPreferences', 'nodeIntegration')) { options = { ...options, webPreferences: { nodeIntegration: true, contextIsolation: false } }; } @@ -20,7 +20,7 @@ const browserViewApi = (socket) => { proxyToCredentialsMap[options.proxy] = options.proxyCredentials; } browserViews.push(browserView); - electronSocket.emit('BrowserViewCreated', browserView['id']); + electronSocket.emit('BrowserViewCreated' + guid, browserView['id']); }); socket.on('browserView-getBounds', (id) => { const bounds = getBrowserViewById(id).getBounds(); diff --git a/ElectronNET.Host/api/browserView.js.map b/ElectronNET.Host/api/browserView.js.map index 596b53ab..1bece3a6 100644 --- a/ElectronNET.Host/api/browserView.js.map +++ b/ElectronNET.Host/api/browserView.js.map @@ -1 +1 @@ -{"version":3,"file":"browserView.js","sourceRoot":"","sources":["browserView.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"browserView.js","sourceRoot":"","sources":["browserView.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/ElectronNET.Host/api/browserView.ts b/ElectronNET.Host/api/browserView.ts index 6ccf33c6..95a47b1d 100644 --- a/ElectronNET.Host/api/browserView.ts +++ b/ElectronNET.Host/api/browserView.ts @@ -1,5 +1,6 @@ -import { Socket } from 'net'; -import { BrowserView } from 'electron'; +import {Socket} from 'net'; +import {BrowserView} from 'electron'; + const browserViews: BrowserView[] = (global['browserViews'] = global['browserViews'] || []) as BrowserView[]; let browserView: BrowserView, electronSocket; const proxyToCredentialsMap: { [proxy: string]: string } = (global['proxyToCredentialsMap'] = global['proxyToCredentialsMap'] || []) as { [proxy: string]: string }; @@ -7,9 +8,9 @@ const proxyToCredentialsMap: { [proxy: string]: string } = (global['proxyToCrede const browserViewApi = (socket: Socket) => { electronSocket = socket; - socket.on('createBrowserView', (options) => { + socket.on('createBrowserView', (guid, options) => { if (!hasOwnChildreen(options, 'webPreferences', 'nodeIntegration')) { - options = { ...options, webPreferences: { nodeIntegration: true, contextIsolation: false } }; + options = {...options, webPreferences: {nodeIntegration: true, contextIsolation: false}}; } browserView = new BrowserView(options); @@ -25,7 +26,7 @@ const browserViewApi = (socket: Socket) => { browserViews.push(browserView); - electronSocket.emit('BrowserViewCreated', browserView['id']); + electronSocket.emit('BrowserViewCreated' + guid, browserView['id']); }); socket.on('browserView-getBounds', (id) => { @@ -71,4 +72,4 @@ function getBrowserViewById(id: number) { } } -export { browserViewApi, browserViewMediateService }; +export {browserViewApi, browserViewMediateService}; diff --git a/ElectronNET.Host/api/browserWindows.js b/ElectronNET.Host/api/browserWindows.js index af3f7e61..10b7a51f 100644 --- a/ElectronNET.Host/api/browserWindows.js +++ b/ElectronNET.Host/api/browserWindows.js @@ -4,22 +4,24 @@ const browserView_1 = require("./browserView"); const path = require('path'); const windows = (global['browserWindows'] = global['browserWindows'] || []); let readyToShowWindowsIds = []; -let window, lastOptions, electronSocket; +let window, electronSocket; let mainWindowURL; const proxyToCredentialsMap = (global['proxyToCredentialsMap'] = global['proxyToCredentialsMap'] || []); -module.exports = (socket, app) => { +module.exports = (socket, app, firstTime) => { electronSocket = socket; - app.on('login', (event, webContents, request, authInfo, callback) => { - if (authInfo.isProxy) { - let proxy = `${authInfo.host}:${authInfo.port}`; - if (proxy in proxyToCredentialsMap && proxyToCredentialsMap[proxy].split(':').length === 2) { - event.preventDefault(); - let user = proxyToCredentialsMap[proxy].split(':')[0]; - let pass = proxyToCredentialsMap[proxy].split(':')[1]; - callback(user, pass); + if (firstTime) { + app.on('login', (event, webContents, request, authInfo, callback) => { + if (authInfo.isProxy) { + let proxy = `${authInfo.host}:${authInfo.port}`; + if (proxy in proxyToCredentialsMap && proxyToCredentialsMap[proxy].split(':').length === 2) { + event.preventDefault(); + let user = proxyToCredentialsMap[proxy].split(':')[0]; + let pass = proxyToCredentialsMap[proxy].split(':')[1]; + callback(user, pass); + } } - } - }); + }); + } socket.on('register-browserWindow-ready-to-show', (id) => { if (readyToShowWindowsIds.includes(id)) { readyToShowWindowsIds = readyToShowWindowsIds.filter(value => value !== id); @@ -175,20 +177,30 @@ module.exports = (socket, app) => { electronSocket.emit('browserWindow-new-window-for-tab' + id); }); }); - socket.on('createBrowserWindow', (options, loadUrl) => { + socket.on('createBrowserWindow', (guid, options, loadUrl) => { if (options.webPreferences && !('nodeIntegration' in options.webPreferences)) { - options = { ...options, webPreferences: { ...options.webPreferences, nodeIntegration: true, contextIsolation: false } }; + options = { + ...options, + webPreferences: { ...options.webPreferences, nodeIntegration: true, contextIsolation: false } + }; } else if (!options.webPreferences) { options = { ...options, webPreferences: { nodeIntegration: true, contextIsolation: false } }; } + if (options.parent) { + options.parent = electron_1.BrowserWindow.fromId(options.parent.id); + } + if (options.x && options.y && options.x == 0 && options.y == 0) { + delete options.x; + delete options.y; + } // we dont want to recreate the window when watch is ready. if (app.commandLine.hasSwitch('watch') && app['mainWindowURL'] === loadUrl) { window = app['mainWindow']; if (window) { window.reload(); windows.push(window); - electronSocket.emit('BrowserWindowCreated', window.id); + electronSocket.emit('BrowserWindowCreated' + guid, window.id); return; } } @@ -210,7 +222,6 @@ module.exports = (socket, app) => { return; } } - if (readyToShowWindowsIds.includes(window.id)) { readyToShowWindowsIds = readyToShowWindowsIds.filter(value => value !== window.id); } @@ -218,9 +229,8 @@ module.exports = (socket, app) => { readyToShowWindowsIds.push(window.id); } }); - lastOptions = options; window.on('closed', (sender) => { - for (let index = 0; index < windows.length; index++) { + again: for (let index = 0; index < windows.length; index++) { const windowItem = windows[index]; try { windowItem.id; @@ -228,19 +238,13 @@ module.exports = (socket, app) => { catch (error) { if (error.message === 'Object has been destroyed') { windows.splice(index, 1); - const ids = []; - windows.forEach(x => ids.push(x.id)); - electronSocket.emit('BrowserWindowClosed', ids); + break again; } } } - }); - app.on('activate', () => { - // On macOS it's common to re-create a window in the app when the - // dock icon is clicked and there are no other windows open. - if (window === null && lastOptions) { - window = new electron_1.BrowserWindow(lastOptions); - } + const ids = []; + windows.forEach(x => ids.push(x.id)); + electronSocket.emit('BrowserWindowUpdateOpenIDs', ids); }); if (loadUrl) { window.loadURL(loadUrl); @@ -256,11 +260,29 @@ module.exports = (socket, app) => { app['mainWindow'] = window; } windows.push(window); - electronSocket.emit('BrowserWindowCreated', window.id); + electronSocket.emit('BrowserWindowCreated' + guid, window.id); }); socket.on('browserWindowDestroy', (id) => { getWindowById(id)?.destroy(); }); + socket.on('browserWindowDestroyAll', () => { + const windows = electron_1.BrowserWindow.getAllWindows(); + let count = 0; + if (windows.length) { + windows.forEach(w => { + try { + w.removeAllListeners('close'); + w.hide(); + w.destroy(); + count++; + } + catch { + //ignore, probably already destroyed + } + }); + } + electronSocket.emit('browserWindowDestroyAll-completed', count); + }); socket.on('browserWindowClose', (id) => { getWindowById(id)?.close(); }); @@ -279,7 +301,8 @@ module.exports = (socket, app) => { if (w) { const isDestroyed = w.isDestroyed(); electronSocket.emit('browserWindow-isDestroyed-completed' + id, isDestroyed); - } else { + } + else { electronSocket.emit('browserWindow-isDestroyed-completed' + id, true); } }); @@ -323,6 +346,9 @@ module.exports = (socket, app) => { socket.on('browserWindowSetFullScreen', (id, fullscreen) => { getWindowById(id)?.setFullScreen(fullscreen); }); + socket.on('browserWindowSetBackgroundColor', (id, color) => { + getWindowById(id)?.setBackgroundColor(color); + }); socket.on('browserWindowIsFullScreen', (id) => { const isFullScreen = getWindowById(id)?.isFullScreen() ?? null; electronSocket.emit('browserWindow-isFullScreen-completed' + id, isFullScreen); @@ -517,7 +543,9 @@ module.exports = (socket, app) => { addMenuItemClickConnector(item.submenu.items, callback); } if ('id' in item && item.id) { - item.click = () => { callback(item.id); }; + item.click = () => { + callback(item.id); + }; } }); } @@ -554,6 +582,9 @@ module.exports = (socket, app) => { socket.on('browserWindowSetAppDetails', (id, options) => { getWindowById(id)?.setAppDetails(options); }); + socket.on('browserWindowSetTitleBarOverlay', (id, options) => { + getWindowById(id)?.setTitleBarOverlay(options); + }); socket.on('browserWindowShowDefinitionForSelection', (id) => { getWindowById(id)?.showDefinitionForSelection(); }); @@ -609,14 +640,26 @@ module.exports = (socket, app) => { socket.on('browserWindowSetVibrancy', (id, type) => { getWindowById(id)?.setVibrancy(type); }); + socket.on('browserWindowSetExcludedFromShownWindowsMenu', (id) => { + const w = getWindowById(id); + if (w) { + w.excludedFromShownWindowsMenu = true; + } + }); socket.on('browserWindow-setBrowserView', (id, browserViewId) => { - getWindowById(id)?.setBrowserView(browserView_1.browserViewMediateService(browserViewId)); + getWindowById(id)?.setBrowserView((0, browserView_1.browserViewMediateService)(browserViewId)); }); function getWindowById(id) { for (let index = 0; index < windows.length; index++) { const element = windows[index]; - if (element.id === id) { - return element; + try { + if (element.id === id) { + return element; + } + } + catch { + //Accessing .id might throw 'Object has been destroyed', so we ignore it here + //The "closed" event should clean this up } } return null; diff --git a/ElectronNET.Host/api/browserWindows.js.map b/ElectronNET.Host/api/browserWindows.js.map index 23ed93c2..ffd599f0 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":"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"} \ No newline at end of file +{"version":3,"file":"browserWindows.js","sourceRoot":"","sources":["browserWindows.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/ElectronNET.Host/api/browserWindows.ts b/ElectronNET.Host/api/browserWindows.ts index 76f7ffbd..4a4b7abd 100644 --- a/ElectronNET.Host/api/browserWindows.ts +++ b/ElectronNET.Host/api/browserWindows.ts @@ -1,27 +1,30 @@ -import { Socket } from 'net'; -import { BrowserWindow, Menu, nativeImage } from 'electron'; -import { browserViewMediateService } from './browserView'; +import {Socket} from 'net'; +import {BrowserWindow, Menu, nativeImage} from 'electron'; +import {browserViewMediateService} from './browserView'; + const path = require('path'); const windows: Electron.BrowserWindow[] = (global['browserWindows'] = global['browserWindows'] || []) as Electron.BrowserWindow[]; let readyToShowWindowsIds: number[] = []; -let window, lastOptions, electronSocket; +let window, electronSocket; let mainWindowURL; const proxyToCredentialsMap: { [proxy: string]: string } = (global['proxyToCredentialsMap'] = global['proxyToCredentialsMap'] || []) as { [proxy: string]: string }; -export = (socket: Socket, app: Electron.App) => { +export = (socket: Socket, app: Electron.App, firstTime: boolean) => { electronSocket = socket; - app.on('login', (event, webContents, request, authInfo, callback) => { - if (authInfo.isProxy) { - let proxy = `${authInfo.host}:${authInfo.port}` - if (proxy in proxyToCredentialsMap && proxyToCredentialsMap[proxy].split(':').length === 2) { - event.preventDefault() - let user = proxyToCredentialsMap[proxy].split(':')[0] - let pass = proxyToCredentialsMap[proxy].split(':')[1] - callback(user, pass) + if (firstTime) { + app.on('login', (event, webContents, request, authInfo, callback) => { + if (authInfo.isProxy) { + let proxy = `${authInfo.host}:${authInfo.port}` + if (proxy in proxyToCredentialsMap && proxyToCredentialsMap[proxy].split(':').length === 2) { + event.preventDefault() + let user = proxyToCredentialsMap[proxy].split(':')[0] + let pass = proxyToCredentialsMap[proxy].split(':')[1] + callback(user, pass) + } } - } - }) + }) + } socket.on('register-browserWindow-ready-to-show', (id) => { if (readyToShowWindowsIds.includes(id)) { @@ -209,11 +212,23 @@ export = (socket: Socket, app: Electron.App) => { }); }); - socket.on('createBrowserWindow', (options, loadUrl) => { + socket.on('createBrowserWindow', (guid, options, loadUrl) => { if (options.webPreferences && !('nodeIntegration' in options.webPreferences)) { - options = { ...options, webPreferences: { ...options.webPreferences, nodeIntegration: true, contextIsolation: false } }; + options = { + ...options, + webPreferences: {...options.webPreferences, nodeIntegration: true, contextIsolation: false} + }; } else if (!options.webPreferences) { - options = { ...options, webPreferences: { nodeIntegration: true, contextIsolation: false } }; + options = {...options, webPreferences: {nodeIntegration: true, contextIsolation: false}}; + } + + if (options.parent) { + options.parent = BrowserWindow.fromId(options.parent.id); + } + + if (options.x && options.y && options.x == 0 && options.y == 0) { + delete options.x; + delete options.y; } // we dont want to recreate the window when watch is ready. @@ -222,7 +237,7 @@ export = (socket: Socket, app: Electron.App) => { if (window) { window.reload(); windows.push(window); - electronSocket.emit('BrowserWindowCreated', window.id); + electronSocket.emit('BrowserWindowCreated' + guid, window.id); return; } } else { @@ -238,6 +253,14 @@ export = (socket: Socket, app: Electron.App) => { } window.on('ready-to-show', () => { + try { + window.id; + } catch (error) { + if (error.message === 'Object has been destroyed') { + return; + } + } + if (readyToShowWindowsIds.includes(window.id)) { readyToShowWindowsIds = readyToShowWindowsIds.filter(value => value !== window.id); } else { @@ -245,31 +268,22 @@ export = (socket: Socket, app: Electron.App) => { } }); - lastOptions = options; - window.on('closed', (sender) => { - for (let index = 0; index < windows.length; index++) { - const windowItem = windows[index]; - try { - windowItem.id; - } catch (error) { - if (error.message === 'Object has been destroyed') { - windows.splice(index, 1); - - const ids = []; - windows.forEach(x => ids.push(x.id)); - electronSocket.emit('BrowserWindowClosed', ids); + again: + for (let index = 0; index < windows.length; index++) { + const windowItem = windows[index]; + try { + windowItem.id; + } catch (error) { + if (error.message === 'Object has been destroyed') { + windows.splice(index, 1); + break again; + } } } - } - }); - - app.on('activate', () => { - // On macOS it's common to re-create a window in the app when the - // dock icon is clicked and there are no other windows open. - if (window === null && lastOptions) { - window = new BrowserWindow(lastOptions); - } + const ids = []; + windows.forEach(x => ids.push(x.id)); + electronSocket.emit('BrowserWindowUpdateOpenIDs', ids); }); if (loadUrl) { @@ -289,13 +303,31 @@ export = (socket: Socket, app: Electron.App) => { } windows.push(window); - electronSocket.emit('BrowserWindowCreated', window.id); + electronSocket.emit('BrowserWindowCreated' + guid, window.id); }); socket.on('browserWindowDestroy', (id) => { getWindowById(id)?.destroy(); }); + socket.on('browserWindowDestroyAll', () => { + const windows = BrowserWindow.getAllWindows(); + let count = 0; + if (windows.length) { + windows.forEach(w => { + try { + w.removeAllListeners('close'); + w.hide(); + w.destroy(); + count++; + } catch { + //ignore, probably already destroyed + } + }); + } + electronSocket.emit('browserWindowDestroyAll-completed', count); + }); + socket.on('browserWindowClose', (id) => { getWindowById(id)?.close(); }); @@ -380,6 +412,10 @@ export = (socket: Socket, app: Electron.App) => { getWindowById(id)?.setFullScreen(fullscreen); }); + socket.on('browserWindowSetBackgroundColor', (id, color) => { + getWindowById(id)?.setBackgroundColor(color); + }); + socket.on('browserWindowIsFullScreen', (id) => { const isFullScreen = getWindowById(id)?.isFullScreen() ?? null; @@ -648,7 +684,9 @@ export = (socket: Socket, app: Electron.App) => { } if ('id' in item && item.id) { - item.click = () => { callback(item.id); }; + item.click = () => { + callback(item.id); + }; } }); } @@ -696,6 +734,10 @@ export = (socket: Socket, app: Electron.App) => { getWindowById(id)?.setAppDetails(options); }); + socket.on('browserWindowSetTitleBarOverlay', (id, options) => { + getWindowById(id)?.setTitleBarOverlay(options); + }); + socket.on('browserWindowShowDefinitionForSelection', (id) => { getWindowById(id)?.showDefinitionForSelection(); }); @@ -774,6 +816,13 @@ export = (socket: Socket, app: Electron.App) => { getWindowById(id)?.setVibrancy(type); }); + socket.on('browserWindowSetExcludedFromShownWindowsMenu', (id) => { + const w = getWindowById(id); + if (w) { + w.excludedFromShownWindowsMenu = true; + } + }); + socket.on('browserWindow-setBrowserView', (id, browserViewId) => { getWindowById(id)?.setBrowserView(browserViewMediateService(browserViewId)); }); @@ -781,8 +830,13 @@ export = (socket: Socket, app: Electron.App) => { function getWindowById(id: number): Electron.BrowserWindow { for (let index = 0; index < windows.length; index++) { const element = windows[index]; - if (element.id === id) { - return element; + try { + if (element.id === id) { + return element; + } + } catch { + //Accessing .id might throw 'Object has been destroyed', so we ignore it here + //The "closed" event should clean this up } } return null; diff --git a/ElectronNET.Host/api/clipboard.js b/ElectronNET.Host/api/clipboard.js index f7e7ef10..76c599b7 100644 --- a/ElectronNET.Host/api/clipboard.js +++ b/ElectronNET.Host/api/clipboard.js @@ -46,6 +46,9 @@ module.exports = (socket) => { electronSocket.emit('clipboard-availableFormats-Completed', formats); }); socket.on('clipboard-write', (data, type) => { + if (data.hasOwnProperty("image")) { + data["image"] = deserializeImage(data["image"]); + } electron_1.clipboard.write(data, type); }); socket.on('clipboard-readImage', (type) => { @@ -54,15 +57,19 @@ module.exports = (socket) => { }); socket.on('clipboard-writeImage', (data, type) => { const dataContent = JSON.parse(data); + const image = deserializeImage(dataContent); + electron_1.clipboard.writeImage(image, type); + }); + function deserializeImage(data) { const image = electron_1.nativeImage.createEmpty(); // tslint:disable-next-line: forin - for (const key in dataContent) { + for (const key in data) { const scaleFactor = key; const bytes = data[key]; const buffer = Buffer.from(bytes, 'base64'); image.addRepresentation({ scaleFactor: +scaleFactor, buffer: buffer }); } - electron_1.clipboard.writeImage(image, type); - }); + return image; + } }; //# sourceMappingURL=clipboard.js.map \ No newline at end of file diff --git a/ElectronNET.Host/api/clipboard.js.map b/ElectronNET.Host/api/clipboard.js.map index c45e255f..b2981431 100644 --- a/ElectronNET.Host/api/clipboard.js.map +++ b/ElectronNET.Host/api/clipboard.js.map @@ -1 +1 @@ -{"version":3,"file":"clipboard.js","sourceRoot":"","sources":["clipboard.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"clipboard.js","sourceRoot":"","sources":["clipboard.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/ElectronNET.Host/api/clipboard.ts b/ElectronNET.Host/api/clipboard.ts index 6a172299..19db075e 100644 --- a/ElectronNET.Host/api/clipboard.ts +++ b/ElectronNET.Host/api/clipboard.ts @@ -1,5 +1,6 @@ -import { Socket } from 'net'; -import { clipboard, nativeImage } from 'electron'; +import {Socket} from 'net'; +import {clipboard, nativeImage} from 'electron'; + let electronSocket; export = (socket: Socket) => { @@ -59,26 +60,32 @@ export = (socket: Socket) => { }); socket.on('clipboard-write', (data, type) => { + if (data.hasOwnProperty("image")) { + data["image"] = deserializeImage(data["image"]); + } clipboard.write(data, type); }); socket.on('clipboard-readImage', (type) => { const image = clipboard.readImage(type); - electronSocket.emit('clipboard-readImage-Completed', { 1: image.toPNG().toString('base64') }); + electronSocket.emit('clipboard-readImage-Completed', {1: image.toPNG().toString('base64')}); }); socket.on('clipboard-writeImage', (data, type) => { const dataContent = JSON.parse(data); - const image = nativeImage.createEmpty(); + const image = deserializeImage(dataContent); + clipboard.writeImage(image, type); + }); + function deserializeImage(data) { + const image = nativeImage.createEmpty(); // tslint:disable-next-line: forin - for (const key in dataContent) { + for (const key in data) { const scaleFactor = key; const bytes = data[key]; const buffer = Buffer.from(bytes, 'base64'); - image.addRepresentation({ scaleFactor: +scaleFactor, buffer: buffer }); + image.addRepresentation({scaleFactor: +scaleFactor, buffer: buffer}); } - - clipboard.writeImage(image, type); - }); + return image; + } }; diff --git a/ElectronNET.Host/api/commandLine.js.map b/ElectronNET.Host/api/commandLine.js.map index 7d84909c..e4c907f0 100644 --- a/ElectronNET.Host/api/commandLine.js.map +++ b/ElectronNET.Host/api/commandLine.js.map @@ -1 +1 @@ -{"version":3,"file":"commandLine.js","sourceRoot":"","sources":["commandLine.ts"],"names":[],"mappings":";AACA,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,GAAiB,EAAE,EAAE;IAC3C,cAAc,GAAG,MAAM,CAAC;IAExB,MAAM,CAAC,EAAE,CAAC,4BAA4B,EAAE,CAAC,UAAkB,EAAE,KAAa,EAAE,EAAE;QAC1E,GAAG,CAAC,WAAW,CAAC,YAAY,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,CAAC,KAAa,EAAE,EAAE;QACxD,GAAG,CAAC,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,KAAa,EAAE,EAAE;QACnD,MAAM,SAAS,GAAG,GAAG,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnD,cAAc,CAAC,IAAI,CAAC,kCAAkC,EAAE,SAAS,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,CAAC,UAAkB,EAAE,EAAE;QAC7D,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QACzD,cAAc,CAAC,IAAI,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"commandLine.js","sourceRoot":"","sources":["commandLine.ts"],"names":[],"mappings":";AAEA,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,GAAiB,EAAE,EAAE;IAC3C,cAAc,GAAG,MAAM,CAAC;IAExB,MAAM,CAAC,EAAE,CAAC,4BAA4B,EAAE,CAAC,UAAkB,EAAE,KAAa,EAAE,EAAE;QAC1E,GAAG,CAAC,WAAW,CAAC,YAAY,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACpD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,CAAC,KAAa,EAAE,EAAE;QACxD,GAAG,CAAC,WAAW,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,KAAa,EAAE,EAAE;QACnD,MAAM,SAAS,GAAG,GAAG,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACnD,cAAc,CAAC,IAAI,CAAC,kCAAkC,EAAE,SAAS,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,CAAC,UAAkB,EAAE,EAAE;QAC7D,MAAM,KAAK,GAAG,GAAG,CAAC,WAAW,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;QACzD,cAAc,CAAC,IAAI,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file diff --git a/ElectronNET.Host/api/commandLine.ts b/ElectronNET.Host/api/commandLine.ts index f206b93e..475ac08d 100644 --- a/ElectronNET.Host/api/commandLine.ts +++ b/ElectronNET.Host/api/commandLine.ts @@ -1,4 +1,5 @@ -import { Socket } from 'net'; +import {Socket} from 'net'; + let electronSocket; export = (socket: Socket, app: Electron.App) => { diff --git a/ElectronNET.Host/api/desktopCapturer.js b/ElectronNET.Host/api/desktopCapturer.js new file mode 100644 index 00000000..fb2fbbb7 --- /dev/null +++ b/ElectronNET.Host/api/desktopCapturer.js @@ -0,0 +1,22 @@ +"use strict"; +const electron_1 = require("electron"); +let electronSocket; +; +module.exports = (socket) => { + electronSocket = socket; + socket.on('desktop-capturer-get-sources', (options) => { + electron_1.desktopCapturer.getSources(options).then(sources => { + const result = sources.map(src => { + return { + appIcon: src.appIcon, + name: src.name, + id: src.id, + display_id: src.display_id, + thumbnail: { 1: src.thumbnail.toPNG().toString('base64') } + }; + }); + electronSocket.emit('desktop-capturer-get-sources-result', result); + }); + }); +}; +//# sourceMappingURL=desktopCapturer.js.map \ No newline at end of file diff --git a/ElectronNET.Host/api/desktopCapturer.js.map b/ElectronNET.Host/api/desktopCapturer.js.map new file mode 100644 index 00000000..9be8fa78 --- /dev/null +++ b/ElectronNET.Host/api/desktopCapturer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"desktopCapturer.js","sourceRoot":"","sources":["desktopCapturer.ts"],"names":[],"mappings":";AACA,uCAA2C;AAE3C,IAAI,cAAc,CAAC;AAsBjB,CAAC;AApBH,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,CAAC,OAAO,EAAE,EAAE;QAClD,0BAAe,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;YAE/C,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;gBAC7B,OAAO;oBACH,OAAO,EAAE,GAAG,CAAC,OAAO;oBACpB,IAAI,EAAE,GAAG,CAAC,IAAI;oBACd,EAAE,EAAE,GAAG,CAAC,EAAE;oBACV,UAAU,EAAE,GAAG,CAAC,UAAU;oBAC1B,SAAS,EAAE,EAAE,CAAC,EAAE,GAAG,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;iBAC7D,CAAC;YACN,CAAC,CAAC,CAAC;YAEH,cAAc,CAAC,IAAI,CAAC,qCAAqC,EAAE,MAAM,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AAGP,CAAC,CAAC"} \ No newline at end of file diff --git a/ElectronNET.Host/api/desktopCapturer.ts b/ElectronNET.Host/api/desktopCapturer.ts new file mode 100644 index 00000000..dd28600d --- /dev/null +++ b/ElectronNET.Host/api/desktopCapturer.ts @@ -0,0 +1,26 @@ +import { Socket } from 'net'; +import { desktopCapturer } from 'electron'; + +let electronSocket; + +export = (socket: Socket) => { + electronSocket = socket; + socket.on('desktop-capturer-get-sources', (options) => { + desktopCapturer.getSources(options).then(sources => { + + const result = sources.map(src => { + return { + appIcon: src.appIcon, + name: src.name, + id: src.id, + display_id: src.display_id, + thumbnail: { 1: src.thumbnail.toPNG().toString('base64') } + }; + }); + + electronSocket.emit('desktop-capturer-get-sources-result', result); + }); + }); + + +};; diff --git a/ElectronNET.Host/api/dialog.js b/ElectronNET.Host/api/dialog.js index 5234bcb1..de8458cb 100644 --- a/ElectronNET.Host/api/dialog.js +++ b/ElectronNET.Host/api/dialog.js @@ -7,12 +7,18 @@ module.exports = (socket) => { if ('id' in browserWindow) { const window = electron_1.BrowserWindow.fromId(browserWindow.id); const messageBoxReturnValue = await electron_1.dialog.showMessageBox(window, options); - electronSocket.emit('showMessageBoxComplete' + guid, { response: messageBoxReturnValue.response, checked: messageBoxReturnValue.checkboxChecked }); + electronSocket.emit('showMessageBoxComplete' + guid, { + response: messageBoxReturnValue.response, + checked: messageBoxReturnValue.checkboxChecked + }); } else { const id = guid || options; const messageBoxReturnValue = await electron_1.dialog.showMessageBox(browserWindow); - electronSocket.emit('showMessageBoxComplete' + id, { response: messageBoxReturnValue.response, checked: messageBoxReturnValue.checkboxChecked }); + electronSocket.emit('showMessageBoxComplete' + id, { + response: messageBoxReturnValue.response, + checked: messageBoxReturnValue.checkboxChecked + }); } }); socket.on('showOpenDialog', async (browserWindow, options, guid) => { diff --git a/ElectronNET.Host/api/dialog.js.map b/ElectronNET.Host/api/dialog.js.map index 26467177..c58b9e1a 100644 --- a/ElectronNET.Host/api/dialog.js.map +++ b/ElectronNET.Host/api/dialog.js.map @@ -1 +1 @@ -{"version":3,"file":"dialog.js","sourceRoot":"","sources":["dialog.ts"],"names":[],"mappings":";AACA,uCAAiD;AACjD,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC/D,IAAI,IAAI,IAAI,aAAa,EAAE;YACvB,MAAM,MAAM,GAAG,wBAAa,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;YAEtD,MAAM,qBAAqB,GAAG,MAAM,iBAAM,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC3E,cAAc,CAAC,IAAI,CAAC,wBAAwB,GAAG,IAAI,EAAE,CAAC,qBAAqB,CAAC,QAAQ,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAC,CAAC;SACjI;aAAM;YACH,MAAM,EAAE,GAAG,IAAI,IAAI,OAAO,CAAC;YAC3B,MAAM,qBAAqB,GAAG,MAAM,iBAAM,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;YAEzE,cAAc,CAAC,IAAI,CAAC,wBAAwB,GAAG,EAAE,EAAE,CAAC,qBAAqB,CAAC,QAAQ,EAAE,qBAAqB,CAAC,eAAe,CAAC,CAAC,CAAC;SAC/H;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC/D,MAAM,MAAM,GAAG,wBAAa,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QACtD,MAAM,qBAAqB,GAAG,MAAM,iBAAM,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAE3E,cAAc,CAAC,IAAI,CAAC,wBAAwB,GAAG,IAAI,EAAE,qBAAqB,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC/D,MAAM,MAAM,GAAG,wBAAa,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QACtD,MAAM,qBAAqB,GAAG,MAAM,iBAAM,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAE3E,cAAc,CAAC,IAAI,CAAC,wBAAwB,GAAG,IAAI,EAAE,qBAAqB,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAC/F,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACzC,iBAAM,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,4BAA4B,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC3E,MAAM,MAAM,GAAG,wBAAa,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QACtD,MAAM,iBAAM,CAAC,0BAA0B,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAEzD,cAAc,CAAC,IAAI,CAAC,oCAAoC,GAAG,IAAI,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"dialog.js","sourceRoot":"","sources":["dialog.ts"],"names":[],"mappings":";AACA,uCAA+C;AAE/C,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC/D,IAAI,IAAI,IAAI,aAAa,EAAE;YACvB,MAAM,MAAM,GAAG,wBAAa,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;YAEtD,MAAM,qBAAqB,GAAG,MAAM,iBAAM,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC3E,cAAc,CAAC,IAAI,CAAC,wBAAwB,GAAG,IAAI,EAAE;gBACjD,QAAQ,EAAE,qBAAqB,CAAC,QAAQ;gBACxC,OAAO,EAAE,qBAAqB,CAAC,eAAe;aACjD,CAAC,CAAC;SACN;aAAM;YACH,MAAM,EAAE,GAAG,IAAI,IAAI,OAAO,CAAC;YAC3B,MAAM,qBAAqB,GAAG,MAAM,iBAAM,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC;YAEzE,cAAc,CAAC,IAAI,CAAC,wBAAwB,GAAG,EAAE,EAAE;gBAC/C,QAAQ,EAAE,qBAAqB,CAAC,QAAQ;gBACxC,OAAO,EAAE,qBAAqB,CAAC,eAAe;aACjD,CAAC,CAAC;SACN;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC/D,MAAM,MAAM,GAAG,wBAAa,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QACtD,MAAM,qBAAqB,GAAG,MAAM,iBAAM,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAE3E,cAAc,CAAC,IAAI,CAAC,wBAAwB,GAAG,IAAI,EAAE,qBAAqB,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAChG,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC/D,MAAM,MAAM,GAAG,wBAAa,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QACtD,MAAM,qBAAqB,GAAG,MAAM,iBAAM,CAAC,cAAc,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAE3E,cAAc,CAAC,IAAI,CAAC,wBAAwB,GAAG,IAAI,EAAE,qBAAqB,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;IAC/F,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACzC,iBAAM,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,4BAA4B,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC3E,MAAM,MAAM,GAAG,wBAAa,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QACtD,MAAM,iBAAM,CAAC,0BAA0B,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAEzD,cAAc,CAAC,IAAI,CAAC,oCAAoC,GAAG,IAAI,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file diff --git a/ElectronNET.Host/api/dialog.ts b/ElectronNET.Host/api/dialog.ts index 932c5fdc..0e9d7b18 100644 --- a/ElectronNET.Host/api/dialog.ts +++ b/ElectronNET.Host/api/dialog.ts @@ -1,5 +1,6 @@ -import { Socket } from 'net'; -import { BrowserWindow, dialog } from 'electron'; +import {Socket} from 'net'; +import {BrowserWindow, dialog} from 'electron'; + let electronSocket; export = (socket: Socket) => { @@ -9,12 +10,18 @@ export = (socket: Socket) => { const window = BrowserWindow.fromId(browserWindow.id); const messageBoxReturnValue = await dialog.showMessageBox(window, options); - electronSocket.emit('showMessageBoxComplete' + guid, [messageBoxReturnValue.response, messageBoxReturnValue.checkboxChecked]); + electronSocket.emit('showMessageBoxComplete' + guid, { + response: messageBoxReturnValue.response, + checked: messageBoxReturnValue.checkboxChecked + }); } else { const id = guid || options; const messageBoxReturnValue = await dialog.showMessageBox(browserWindow); - electronSocket.emit('showMessageBoxComplete' + id, [messageBoxReturnValue.response, messageBoxReturnValue.checkboxChecked]); + electronSocket.emit('showMessageBoxComplete' + id, { + response: messageBoxReturnValue.response, + checked: messageBoxReturnValue.checkboxChecked + }); } }); diff --git a/ElectronNET.Host/api/dock.js b/ElectronNET.Host/api/dock.js index 7d5010d6..ad71fe33 100644 --- a/ElectronNET.Host/api/dock.js +++ b/ElectronNET.Host/api/dock.js @@ -54,7 +54,9 @@ module.exports = (socket) => { addMenuItemClickConnector(item.submenu.items, callback); } if ('id' in item && item.id) { - item.click = () => { callback(item.id); }; + item.click = () => { + callback(item.id); + }; } }); } diff --git a/ElectronNET.Host/api/dock.js.map b/ElectronNET.Host/api/dock.js.map index 449d44b6..ddac6619 100644 --- a/ElectronNET.Host/api/dock.js.map +++ b/ElectronNET.Host/api/dock.js.map @@ -1 +1 @@ -{"version":3,"file":"dock.js","sourceRoot":"","sources":["dock.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"dock.js","sourceRoot":"","sources":["dock.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/ElectronNET.Host/api/dock.ts b/ElectronNET.Host/api/dock.ts index bf2b908d..c83130cf 100644 --- a/ElectronNET.Host/api/dock.ts +++ b/ElectronNET.Host/api/dock.ts @@ -1,5 +1,6 @@ -import { Socket } from 'net'; -import { app, Menu } from 'electron'; +import {Socket} from 'net'; +import {app, Menu} from 'electron'; + let electronSocket; export = (socket: Socket) => { @@ -71,7 +72,9 @@ export = (socket: Socket) => { } if ('id' in item && item.id) { - item.click = () => { callback(item.id); }; + item.click = () => { + callback(item.id); + }; } }); } diff --git a/ElectronNET.Host/api/globalShortcut.js b/ElectronNET.Host/api/globalShortcut.js index dd018d02..081581aa 100644 --- a/ElectronNET.Host/api/globalShortcut.js +++ b/ElectronNET.Host/api/globalShortcut.js @@ -19,7 +19,8 @@ module.exports = (socket) => { try { electron_1.globalShortcut.unregisterAll(); } - catch (error) { } + catch (error) { + } }); }; //# sourceMappingURL=globalShortcut.js.map \ No newline at end of file diff --git a/ElectronNET.Host/api/globalShortcut.js.map b/ElectronNET.Host/api/globalShortcut.js.map index bed5642c..0e2b8fc3 100644 --- a/ElectronNET.Host/api/globalShortcut.js.map +++ b/ElectronNET.Host/api/globalShortcut.js.map @@ -1 +1 @@ -{"version":3,"file":"globalShortcut.js","sourceRoot":"","sources":["globalShortcut.ts"],"names":[],"mappings":";AAAA,uCAA0C;AAE1C,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,WAAW,EAAE,EAAE;QACjD,yBAAc,CAAC,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;YACtC,cAAc,CAAC,IAAI,CAAC,wBAAwB,EAAE,WAAW,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,6BAA6B,EAAE,CAAC,WAAW,EAAE,EAAE;QACrD,MAAM,YAAY,GAAG,yBAAc,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QAE9D,cAAc,CAAC,IAAI,CAAC,sCAAsC,EAAE,YAAY,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,2BAA2B,EAAE,CAAC,WAAW,EAAE,EAAE;QACnD,yBAAc,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC3C,IAAI;YACA,yBAAc,CAAC,aAAa,EAAE,CAAC;SAClC;QAAC,OAAO,KAAK,EAAE,GAAG;IACvB,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"globalShortcut.js","sourceRoot":"","sources":["globalShortcut.ts"],"names":[],"mappings":";AAAA,uCAAwC;AAGxC,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,WAAW,EAAE,EAAE;QACjD,yBAAc,CAAC,QAAQ,CAAC,WAAW,EAAE,GAAG,EAAE;YACtC,cAAc,CAAC,IAAI,CAAC,wBAAwB,EAAE,WAAW,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,6BAA6B,EAAE,CAAC,WAAW,EAAE,EAAE;QACrD,MAAM,YAAY,GAAG,yBAAc,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QAE9D,cAAc,CAAC,IAAI,CAAC,sCAAsC,EAAE,YAAY,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,2BAA2B,EAAE,CAAC,WAAW,EAAE,EAAE;QACnD,yBAAc,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QAC3C,IAAI;YACA,yBAAc,CAAC,aAAa,EAAE,CAAC;SAClC;QAAC,OAAO,KAAK,EAAE;SACf;IACL,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file diff --git a/ElectronNET.Host/api/globalShortcut.ts b/ElectronNET.Host/api/globalShortcut.ts index da9e7652..3a9bd574 100644 --- a/ElectronNET.Host/api/globalShortcut.ts +++ b/ElectronNET.Host/api/globalShortcut.ts @@ -1,5 +1,6 @@ -import { globalShortcut } from 'electron'; -import { Socket } from 'net'; +import {globalShortcut} from 'electron'; +import {Socket} from 'net'; + let electronSocket; export = (socket: Socket) => { @@ -23,6 +24,7 @@ export = (socket: Socket) => { socket.on('globalShortcut-unregisterAll', () => { try { globalShortcut.unregisterAll(); - } catch (error) { } + } catch (error) { + } }); }; diff --git a/ElectronNET.Host/api/ipc.js b/ElectronNET.Host/api/ipc.js index 4c18ea83..8bcbbea9 100644 --- a/ElectronNET.Host/api/ipc.js +++ b/ElectronNET.Host/api/ipc.js @@ -5,7 +5,21 @@ module.exports = (socket) => { electronSocket = socket; socket.on('registerIpcMainChannel', (channel) => { electron_1.ipcMain.on(channel, (event, args) => { - electronSocket.emit(channel, [event.preventDefault(), args]); + event.preventDefault(); + electronSocket.emit(channel, [args]); + event.returnValue = null; + }); + }); + socket.on('registerIpcMainChannelWithId', (channel) => { + electron_1.ipcMain.on(channel, (event, args) => { + event.preventDefault(); + let wcId = event.sender.id; + let wc = electron_1.webContents.fromId(wcId); + let bw = electron_1.BrowserWindow.fromWebContents(wc); + if (bw) { + electronSocket.emit(channel, { id: bw.id, wcId: wcId, args: [args] }); + } + event.returnValue = null; }); }); socket.on('registerSyncIpcMainChannel', (channel) => { @@ -15,19 +29,22 @@ module.exports = (socket) => { socket.on(channel + 'Sync', (result) => { event.returnValue = result; }); - electronSocket.emit(channel, [event.preventDefault(), args]); + event.preventDefault(); + electronSocket.emit(channel, [args]); }); }); socket.on('registerOnceIpcMainChannel', (channel) => { electron_1.ipcMain.once(channel, (event, args) => { - electronSocket.emit(channel, [event.preventDefault(), args]); + event.preventDefault(); + electronSocket.emit(channel, [args]); + event.returnValue = null; }); }); socket.on('removeAllListenersIpcMainChannel', (channel) => { electron_1.ipcMain.removeAllListeners(channel); }); - socket.on('sendToIpcRenderer', (browserWindow, channel, ...data) => { - const window = electron_1.BrowserWindow.fromId(browserWindow.id); + socket.on('sendToIpcRenderer', (browserWindowId, channel, ...data) => { + const window = electron_1.BrowserWindow.fromId(browserWindowId); if (window) { window.webContents.send(channel, ...data); } diff --git a/ElectronNET.Host/api/ipc.js.map b/ElectronNET.Host/api/ipc.js.map index 2876296b..65679d0a 100644 --- a/ElectronNET.Host/api/ipc.js.map +++ b/ElectronNET.Host/api/ipc.js.map @@ -1 +1 @@ -{"version":3,"file":"ipc.js","sourceRoot":"","sources":["ipc.ts"],"names":[],"mappings":";AAAA,uCAA+D;AAE/D,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,wBAAwB,EAAE,CAAC,OAAO,EAAE,EAAE;QAC5C,kBAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YAChC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,4BAA4B,EAAE,CAAC,OAAO,EAAE,EAAE;QAChD,kBAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YAChC,MAAM,CAAC,GAAQ,MAAM,CAAC;YACtB,CAAC,CAAC,kBAAkB,CAAC,OAAO,GAAG,MAAM,CAAC,CAAC;YACvC,MAAM,CAAC,EAAE,CAAC,OAAO,GAAG,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE;gBACnC,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC;YAC/B,CAAC,CAAC,CAAC;YAEH,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,4BAA4B,EAAE,CAAC,OAAO,EAAE,EAAE;QAChD,kBAAO,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YAClC,cAAc,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,CAAC,OAAO,EAAE,EAAE;QACtD,kBAAO,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,aAAa,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE;QAC/D,MAAM,MAAM,GAAG,wBAAa,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;QAEtD,IAAI,MAAM,EAAE;YACR,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;SAC7C;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,EAAE;QAC/D,MAAM,YAAY,GAAkB,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,CAAkB,CAAC;QAC7G,IAAI,IAAI,GAAgB,IAAI,CAAC;QAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC1C,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE;gBAC9B,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;gBACvB,MAAM;aACT;SACJ;QAED,IAAI,IAAI,EAAE;YACN,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;SAC3C;IACL,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"ipc.js","sourceRoot":"","sources":["ipc.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/ElectronNET.Host/api/ipc.ts b/ElectronNET.Host/api/ipc.ts index 801160f6..63b1d453 100644 --- a/ElectronNET.Host/api/ipc.ts +++ b/ElectronNET.Host/api/ipc.ts @@ -1,12 +1,28 @@ -import { ipcMain, BrowserWindow, BrowserView } from 'electron'; -import { Socket } from 'net'; +import {BrowserView, BrowserWindow, ipcMain, webContents} from 'electron'; +import {Socket} from 'net'; + let electronSocket; export = (socket: Socket) => { electronSocket = socket; socket.on('registerIpcMainChannel', (channel) => { ipcMain.on(channel, (event, args) => { - electronSocket.emit(channel, [event.preventDefault(), args]); + event.preventDefault(); + electronSocket.emit(channel, [args]); + event.returnValue = null; + }); + }); + + socket.on('registerIpcMainChannelWithId', (channel) => { + ipcMain.on(channel, (event, args) => { + event.preventDefault(); + let wcId = event.sender.id; + let wc = webContents.fromId(wcId) + let bw = BrowserWindow.fromWebContents(wc); + if (bw) { + electronSocket.emit(channel, {id: bw.id, wcId: wcId, args: [args]}); + } + event.returnValue = null; }); }); @@ -17,14 +33,16 @@ export = (socket: Socket) => { socket.on(channel + 'Sync', (result) => { event.returnValue = result; }); - - electronSocket.emit(channel, [event.preventDefault(), args]); + event.preventDefault(); + electronSocket.emit(channel, [args]); }); }); socket.on('registerOnceIpcMainChannel', (channel) => { ipcMain.once(channel, (event, args) => { - electronSocket.emit(channel, [event.preventDefault(), args]); + event.preventDefault(); + electronSocket.emit(channel, [args]); + event.returnValue = null; }); }); @@ -32,8 +50,8 @@ export = (socket: Socket) => { ipcMain.removeAllListeners(channel); }); - socket.on('sendToIpcRenderer', (browserWindow, channel, ...data) => { - const window = BrowserWindow.fromId(browserWindow.id); + socket.on('sendToIpcRenderer', (browserWindowId, channel, ...data) => { + const window = BrowserWindow.fromId(browserWindowId); if (window) { window.webContents.send(channel, ...data); diff --git a/ElectronNET.Host/api/menu.js b/ElectronNET.Host/api/menu.js index 28fac07e..434c9c39 100644 --- a/ElectronNET.Host/api/menu.js +++ b/ElectronNET.Host/api/menu.js @@ -27,7 +27,9 @@ module.exports = (socket) => { addContextMenuItemClickConnector(item.submenu.items, browserWindowId, callback); } if ('id' in item && item.id) { - item.click = () => { callback(item.id, browserWindowId); }; + item.click = () => { + callback(item.id, browserWindowId); + }; } }); } @@ -52,7 +54,9 @@ module.exports = (socket) => { addMenuItemClickConnector(item.submenu.items, callback); } if ('id' in item && item.id) { - item.click = () => { callback(item.id); }; + item.click = () => { + callback(item.id); + }; } }); } diff --git a/ElectronNET.Host/api/menu.js.map b/ElectronNET.Host/api/menu.js.map index 1ad421e4..1c56134e 100644 --- a/ElectronNET.Host/api/menu.js.map +++ b/ElectronNET.Host/api/menu.js.map @@ -1 +1 @@ -{"version":3,"file":"menu.js","sourceRoot":"","sources":["menu.ts"],"names":[],"mappings":";AACA,uCAA+C;AAC/C,MAAM,gBAAgB,GAAG,CAAC,MAAM,CAAC,kBAAkB,CAAC,GAAG,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,CAAC,CAAC;AACzF,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,qBAAqB,EAAE,CAAC,eAAe,EAAE,SAAS,EAAE,EAAE;QAC5D,MAAM,IAAI,GAAG,eAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAE/C,gCAAgC,CAAC,IAAI,CAAC,KAAK,EAAE,eAAe,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE;YAC3E,cAAc,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,MAAM,KAAK,GAAG,gBAAgB,CAAC,SAAS,CAAC,WAAW,CAAC,EAAE,CAAC,WAAW,CAAC,eAAe,KAAK,eAAe,CAAC,CAAC;QAEzG,MAAM,eAAe,GAAG;YACpB,IAAI,EAAE,IAAI;YACV,eAAe,EAAE,eAAe;SACnC,CAAC;QAEF,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;YACd,gBAAgB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;SAC1C;aAAM;YACH,gBAAgB,CAAC,KAAK,CAAC,GAAG,eAAe,CAAC;SAC7C;IACL,CAAC,CAAC,CAAC;IAEH,SAAS,gCAAgC,CAAC,SAAS,EAAE,eAAe,EAAE,QAAQ;QAC1E,SAAS,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACvB,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC/C,gCAAgC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC;aACnF;YAED,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,EAAE,EAAE;gBACzB,IAAI,CAAC,KAAK,GAAG,GAAG,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;aAC9D;QACL,CAAC,CAAC,CAAC;IACP,CAAC;IAED,MAAM,CAAC,EAAE,CAAC,uBAAuB,EAAE,CAAC,eAAe,EAAE,EAAE;QACnD,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YACzB,IAAI,CAAC,CAAC,eAAe,KAAK,eAAe,EAAE;gBACvC,MAAM,aAAa,GAAG,wBAAa,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;gBAC5D,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;aAC/B;QACL,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,SAAS,EAAE,EAAE;QAC/C,MAAM,IAAI,GAAG,eAAI,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAE/C,yBAAyB,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE;YACzC,cAAc,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;QAC/C,CAAC,CAAC,CAAC;QAEH,eAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;IAEH,SAAS,yBAAyB,CAAC,SAAS,EAAE,QAAQ;QAClD,SAAS,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACvB,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC/C,yBAAyB,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;aAC3D;YAED,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,EAAE,EAAE;gBACzB,IAAI,CAAC,KAAK,GAAG,GAAG,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;aAC7C;QACL,CAAC,CAAC,CAAC;IACP,CAAC;AACL,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"menu.js","sourceRoot":"","sources":["menu.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/ElectronNET.Host/api/menu.ts b/ElectronNET.Host/api/menu.ts index efadf31d..45de8fc9 100644 --- a/ElectronNET.Host/api/menu.ts +++ b/ElectronNET.Host/api/menu.ts @@ -1,5 +1,6 @@ -import { Socket } from 'net'; -import { Menu, BrowserWindow } from 'electron'; +import {Socket} from 'net'; +import {BrowserWindow, Menu} from 'electron'; + const contextMenuItems = (global['contextMenuItems'] = global['contextMenuItems'] || []); let electronSocket; @@ -9,7 +10,7 @@ export = (socket: Socket) => { const menu = Menu.buildFromTemplate(menuItems); addContextMenuItemClickConnector(menu.items, browserWindowId, (id, windowId) => { - electronSocket.emit('contextMenuItemClicked', [id, windowId]); + electronSocket.emit('contextMenuItemClicked', {id: id, windowId: windowId}); }); const index = contextMenuItems.findIndex(contextMenu => contextMenu.browserWindowId === browserWindowId); @@ -33,7 +34,9 @@ export = (socket: Socket) => { } if ('id' in item && item.id) { - item.click = () => { callback(item.id, browserWindowId); }; + item.click = () => { + callback(item.id, browserWindowId); + }; } }); } @@ -64,7 +67,9 @@ export = (socket: Socket) => { } if ('id' in item && item.id) { - item.click = () => { callback(item.id); }; + item.click = () => { + callback(item.id); + }; } }); } diff --git a/ElectronNET.Host/api/nativeTheme.js.map b/ElectronNET.Host/api/nativeTheme.js.map index 5f4bfd4d..6a5b517b 100644 --- a/ElectronNET.Host/api/nativeTheme.js.map +++ b/ElectronNET.Host/api/nativeTheme.js.map @@ -1 +1 @@ -{"version":3,"file":"nativeTheme.js","sourceRoot":"","sources":["nativeTheme.ts"],"names":[],"mappings":";AACA,uCAAuC;AACvC,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IAExB,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QAC9C,MAAM,mBAAmB,GAAG,sBAAW,CAAC,mBAAmB,CAAC;QAE5D,cAAc,CAAC,IAAI,CAAC,2CAA2C,EAAE,mBAAmB,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACtD,MAAM,2BAA2B,GAAG,sBAAW,CAAC,2BAA2B,CAAC;QAE5E,cAAc,CAAC,IAAI,CAAC,mDAAmD,EAAE,2BAA2B,CAAC,CAAC;IAC1G,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QACvD,MAAM,4BAA4B,GAAG,sBAAW,CAAC,4BAA4B,CAAC;QAE9E,cAAc,CAAC,IAAI,CAAC,oDAAoD,EAAE,4BAA4B,CAAC,CAAC;IAC5G,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QAC1C,MAAM,WAAW,GAAG,sBAAW,CAAC,WAAW,CAAC;QAE5C,cAAc,CAAC,IAAI,CAAC,sCAAsC,EAAE,WAAW,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,WAAW,EAAE,EAAE;QACjD,sBAAW,CAAC,WAAW,GAAG,WAAW,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,oCAAoC,EAAE,CAAC,EAAE,EAAE,EAAE;QACnD,sBAAW,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YAC3B,cAAc,CAAC,IAAI,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"nativeTheme.js","sourceRoot":"","sources":["nativeTheme.ts"],"names":[],"mappings":";AACA,uCAAqC;AAErC,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IAExB,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QAC9C,MAAM,mBAAmB,GAAG,sBAAW,CAAC,mBAAmB,CAAC;QAE5D,cAAc,CAAC,IAAI,CAAC,2CAA2C,EAAE,mBAAmB,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACtD,MAAM,2BAA2B,GAAG,sBAAW,CAAC,2BAA2B,CAAC;QAE5E,cAAc,CAAC,IAAI,CAAC,mDAAmD,EAAE,2BAA2B,CAAC,CAAC;IAC1G,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QACvD,MAAM,4BAA4B,GAAG,sBAAW,CAAC,4BAA4B,CAAC;QAE9E,cAAc,CAAC,IAAI,CAAC,oDAAoD,EAAE,4BAA4B,CAAC,CAAC;IAC5G,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QAC1C,MAAM,WAAW,GAAG,sBAAW,CAAC,WAAW,CAAC;QAE5C,cAAc,CAAC,IAAI,CAAC,sCAAsC,EAAE,WAAW,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,WAAW,EAAE,EAAE;QACjD,sBAAW,CAAC,WAAW,GAAG,WAAW,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,oCAAoC,EAAE,CAAC,EAAE,EAAE,EAAE;QACnD,sBAAW,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YAC3B,cAAc,CAAC,IAAI,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;QACpD,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file diff --git a/ElectronNET.Host/api/nativeTheme.ts b/ElectronNET.Host/api/nativeTheme.ts index 16d22cdc..6a186a16 100644 --- a/ElectronNET.Host/api/nativeTheme.ts +++ b/ElectronNET.Host/api/nativeTheme.ts @@ -1,5 +1,6 @@ -import { Socket } from 'net'; -import { nativeTheme } from 'electron'; +import {Socket} from 'net'; +import {nativeTheme} from 'electron'; + let electronSocket; export = (socket: Socket) => { diff --git a/ElectronNET.Host/api/notification.js.map b/ElectronNET.Host/api/notification.js.map index f6e58d46..cccd0cba 100644 --- a/ElectronNET.Host/api/notification.js.map +++ b/ElectronNET.Host/api/notification.js.map @@ -1 +1 @@ -{"version":3,"file":"notification.js","sourceRoot":"","sources":["notification.ts"],"names":[],"mappings":";AACA,uCAAwC;AACxC,MAAM,aAAa,GAA4B,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,CAA4B,CAAC;AACpI,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,OAAO,EAAE,EAAE;QACxC,MAAM,YAAY,GAAG,IAAI,uBAAY,CAAC,OAAO,CAAC,CAAC;QAC/C,IAAI,SAAS,GAAG,KAAK,CAAC;QAEtB,IAAI,OAAO,CAAC,MAAM,EAAE;YAChB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;gBACzB,cAAc,CAAC,IAAI,CAAC,uBAAuB,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YACjE,CAAC,CAAC,CAAC;SACN;QAED,IAAI,OAAO,CAAC,OAAO,EAAE;YACjB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBAC1B,cAAc,CAAC,IAAI,CAAC,wBAAwB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YACnE,CAAC,CAAC,CAAC;SACN;QAED,IAAI,OAAO,CAAC,OAAO,EAAE;YACjB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBAC1B,cAAc,CAAC,IAAI,CAAC,wBAAwB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YACnE,CAAC,CAAC,CAAC;SACN;QAED,IAAI,OAAO,CAAC,OAAO,EAAE;YACjB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;gBACtC,cAAc,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;YAC5E,CAAC,CAAC,CAAC;SACN;QAED,IAAI,OAAO,CAAC,QAAQ,EAAE;YAClB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;gBACvC,cAAc,CAAC,IAAI,CAAC,yBAAyB,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;YAC9E,CAAC,CAAC,CAAC;SACN;QAED,IAAI,SAAS,EAAE;YACX,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;SACpC;QAED,YAAY,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACtC,MAAM,WAAW,GAAG,uBAAY,CAAC,WAAW,CAAC;QAC7C,cAAc,CAAC,IAAI,CAAC,iCAAiC,EAAE,WAAW,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"notification.js","sourceRoot":"","sources":["notification.ts"],"names":[],"mappings":";AACA,uCAAsC;AAEtC,MAAM,aAAa,GAA4B,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,CAA4B,CAAC;AACpI,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,OAAO,EAAE,EAAE;QACxC,MAAM,YAAY,GAAG,IAAI,uBAAY,CAAC,OAAO,CAAC,CAAC;QAC/C,IAAI,SAAS,GAAG,KAAK,CAAC;QAEtB,IAAI,OAAO,CAAC,MAAM,EAAE;YAChB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE;gBACzB,cAAc,CAAC,IAAI,CAAC,uBAAuB,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YACjE,CAAC,CAAC,CAAC;SACN;QAED,IAAI,OAAO,CAAC,OAAO,EAAE;YACjB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBAC1B,cAAc,CAAC,IAAI,CAAC,wBAAwB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YACnE,CAAC,CAAC,CAAC;SACN;QAED,IAAI,OAAO,CAAC,OAAO,EAAE;YACjB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;gBAC1B,cAAc,CAAC,IAAI,CAAC,wBAAwB,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;YACnE,CAAC,CAAC,CAAC;SACN;QAED,IAAI,OAAO,CAAC,OAAO,EAAE;YACjB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;gBACtC,cAAc,CAAC,IAAI,CAAC,wBAAwB,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC;YAC5E,CAAC,CAAC,CAAC;SACN;QAED,IAAI,OAAO,CAAC,QAAQ,EAAE;YAClB,SAAS,GAAG,IAAI,CAAC;YACjB,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;gBACvC,cAAc,CAAC,IAAI,CAAC,yBAAyB,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;YAC9E,CAAC,CAAC,CAAC;SACN;QAED,IAAI,SAAS,EAAE;YACX,aAAa,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;SACpC;QAED,YAAY,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACtC,MAAM,WAAW,GAAG,uBAAY,CAAC,WAAW,CAAC;QAC7C,cAAc,CAAC,IAAI,CAAC,iCAAiC,EAAE,WAAW,CAAC,CAAC;IACxE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file diff --git a/ElectronNET.Host/api/notification.ts b/ElectronNET.Host/api/notification.ts index 50f1a2d6..32c497d0 100644 --- a/ElectronNET.Host/api/notification.ts +++ b/ElectronNET.Host/api/notification.ts @@ -1,5 +1,6 @@ -import { Socket } from 'net'; -import { Notification } from 'electron'; +import {Socket} from 'net'; +import {Notification} from 'electron'; + const notifications: Electron.Notification[] = (global['notifications'] = global['notifications'] || []) as Electron.Notification[]; let electronSocket; diff --git a/ElectronNET.Host/api/powerMonitor.js.map b/ElectronNET.Host/api/powerMonitor.js.map index f83530e0..ea39668e 100644 --- a/ElectronNET.Host/api/powerMonitor.js.map +++ b/ElectronNET.Host/api/powerMonitor.js.map @@ -1 +1 @@ -{"version":3,"file":"powerMonitor.js","sourceRoot":"","sources":["powerMonitor.ts"],"names":[],"mappings":";AACA,uCAAwC;AACxC,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACtC,uBAAY,CAAC,EAAE,CAAC,aAAa,EAAE,GAAG,EAAE;YAChC,cAAc,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACxC,uBAAY,CAAC,EAAE,CAAC,eAAe,EAAE,GAAG,EAAE;YAClC,cAAc,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAClC,uBAAY,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YAC5B,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QACjC,uBAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YAC3B,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAChC,uBAAY,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAC1B,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACrC,uBAAY,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;YAC/B,cAAc,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACnC,uBAAY,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE;YAC7B,cAAc,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"powerMonitor.js","sourceRoot":"","sources":["powerMonitor.ts"],"names":[],"mappings":";AACA,uCAAsC;AAEtC,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACtC,uBAAY,CAAC,EAAE,CAAC,aAAa,EAAE,GAAG,EAAE;YAChC,cAAc,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC1C,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;QACxC,uBAAY,CAAC,EAAE,CAAC,eAAe,EAAE,GAAG,EAAE;YAClC,cAAc,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,qBAAqB,EAAE,GAAG,EAAE;QAClC,uBAAY,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE;YAC5B,cAAc,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QACjC,uBAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;YAC3B,cAAc,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAChC,uBAAY,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YAC1B,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QACrC,uBAAY,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;YAC/B,cAAc,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QACnC,uBAAY,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE;YAC7B,cAAc,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QACvC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file diff --git a/ElectronNET.Host/api/powerMonitor.ts b/ElectronNET.Host/api/powerMonitor.ts index f4c1fd45..e2ad6f98 100644 --- a/ElectronNET.Host/api/powerMonitor.ts +++ b/ElectronNET.Host/api/powerMonitor.ts @@ -1,5 +1,6 @@ -import { Socket } from 'net'; -import { powerMonitor } from 'electron'; +import {Socket} from 'net'; +import {powerMonitor} from 'electron'; + let electronSocket; export = (socket: Socket) => { diff --git a/ElectronNET.Host/api/screen.js b/ElectronNET.Host/api/screen.js index 37a6f2a3..855ef131 100644 --- a/ElectronNET.Host/api/screen.js +++ b/ElectronNET.Host/api/screen.js @@ -15,7 +15,10 @@ module.exports = (socket) => { }); socket.on('register-screen-display-metrics-changed', (id) => { electron_1.screen.on('display-metrics-changed', (event, display, changedMetrics) => { - electronSocket.emit('screen-display-metrics-changed-event' + id, {display: display, changedMetrics: changedMetrics}); + electronSocket.emit('screen-display-metrics-changed-event' + id, { + display: display, + changedMetrics: changedMetrics + }); }); }); socket.on('screen-getCursorScreenPoint', () => { @@ -35,11 +38,21 @@ module.exports = (socket) => { electronSocket.emit('screen-getAllDisplaysCompleted', display); }); socket.on('screen-getDisplayNearestPoint', (point) => { - const display = electron_1.screen.getDisplayNearestPoint(point); + let display; + try { + display = electron_1.screen.getDisplayNearestPoint(point); + } catch { + display = electron_1.screen.getPrimaryDisplay(); + } electronSocket.emit('screen-getDisplayNearestPointCompleted', display); }); socket.on('screen-getDisplayMatching', (rectangle) => { - const display = electron_1.screen.getDisplayMatching(rectangle); + let display; + try { + display = electron_1.screen.getDisplayMatching(rectangle); + } catch { + display = electron_1.screen.getPrimaryDisplay(); + } electronSocket.emit('screen-getDisplayMatchingCompleted', display); }); }; diff --git a/ElectronNET.Host/api/screen.js.map b/ElectronNET.Host/api/screen.js.map index 1514a5e9..65ae35b8 100644 --- a/ElectronNET.Host/api/screen.js.map +++ b/ElectronNET.Host/api/screen.js.map @@ -1 +1 @@ -{"version":3,"file":"screen.js","sourceRoot":"","sources":["screen.ts"],"names":[],"mappings":";AACA,uCAAkC;AAClC,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,+BAA+B,EAAE,CAAC,EAAE,EAAE,EAAE;QAC9C,iBAAM,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC1C,cAAc,CAAC,IAAI,CAAC,4BAA4B,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,CAAC,EAAE,EAAE,EAAE;QAChD,iBAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC5C,cAAc,CAAC,IAAI,CAAC,8BAA8B,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yCAAyC,EAAE,CAAC,EAAE,EAAE,EAAE;QACxD,iBAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE;YACpE,cAAc,CAAC,IAAI,CAAC,sCAAsC,GAAG,EAAE,EAAE,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC,CAAC;QAChG,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QAC1C,MAAM,KAAK,GAAG,iBAAM,CAAC,oBAAoB,EAAE,CAAC;QAC5C,cAAc,CAAC,IAAI,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACtC,MAAM,MAAM,GAAG,iBAAM,CAAC,iBAAiB,EAAE,CAAC,QAAQ,CAAC;QACnD,cAAc,CAAC,IAAI,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QACvC,MAAM,OAAO,GAAG,iBAAM,CAAC,iBAAiB,EAAE,CAAC;QAC3C,cAAc,CAAC,IAAI,CAAC,mCAAmC,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACpC,MAAM,OAAO,GAAG,iBAAM,CAAC,cAAc,EAAE,CAAC;QACxC,cAAc,CAAC,IAAI,CAAC,gCAAgC,EAAE,OAAO,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,+BAA+B,EAAE,CAAC,KAAK,EAAE,EAAE;QACjD,MAAM,OAAO,GAAG,iBAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;QACrD,cAAc,CAAC,IAAI,CAAC,wCAAwC,EAAE,OAAO,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,2BAA2B,EAAE,CAAC,SAAS,EAAE,EAAE;QACjD,MAAM,OAAO,GAAG,iBAAM,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QACrD,cAAc,CAAC,IAAI,CAAC,oCAAoC,EAAE,OAAO,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"screen.js","sourceRoot":"","sources":["screen.ts"],"names":[],"mappings":";AACA,uCAAgC;AAEhC,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,+BAA+B,EAAE,CAAC,EAAE,EAAE,EAAE;QAC9C,iBAAM,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC1C,cAAc,CAAC,IAAI,CAAC,4BAA4B,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,CAAC,EAAE,EAAE,EAAE;QAChD,iBAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;YAC5C,cAAc,CAAC,IAAI,CAAC,8BAA8B,GAAG,EAAE,EAAE,OAAO,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yCAAyC,EAAE,CAAC,EAAE,EAAE,EAAE;QACxD,iBAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,EAAE;YACpE,cAAc,CAAC,IAAI,CAAC,sCAAsC,GAAG,EAAE,EAAE;gBAC7D,OAAO,EAAE,OAAO;gBAChB,cAAc,EAAE,cAAc;aACjC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,6BAA6B,EAAE,GAAG,EAAE;QAC1C,MAAM,KAAK,GAAG,iBAAM,CAAC,oBAAoB,EAAE,CAAC;QAC5C,cAAc,CAAC,IAAI,CAAC,sCAAsC,EAAE,KAAK,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QACtC,MAAM,MAAM,GAAG,iBAAM,CAAC,iBAAiB,EAAE,CAAC,QAAQ,CAAC;QACnD,cAAc,CAAC,IAAI,CAAC,kCAAkC,EAAE,MAAM,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QACvC,MAAM,OAAO,GAAG,iBAAM,CAAC,iBAAiB,EAAE,CAAC;QAC3C,cAAc,CAAC,IAAI,CAAC,mCAAmC,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QACpC,MAAM,OAAO,GAAG,iBAAM,CAAC,cAAc,EAAE,CAAC;QACxC,cAAc,CAAC,IAAI,CAAC,gCAAgC,EAAE,OAAO,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,+BAA+B,EAAE,CAAC,KAAK,EAAE,EAAE;QACjD,MAAM,OAAO,GAAG,iBAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;QACrD,cAAc,CAAC,IAAI,CAAC,wCAAwC,EAAE,OAAO,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,2BAA2B,EAAE,CAAC,SAAS,EAAE,EAAE;QACjD,MAAM,OAAO,GAAG,iBAAM,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QACrD,cAAc,CAAC,IAAI,CAAC,oCAAoC,EAAE,OAAO,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file diff --git a/ElectronNET.Host/api/screen.ts b/ElectronNET.Host/api/screen.ts index 3a8b91cc..37854f71 100644 --- a/ElectronNET.Host/api/screen.ts +++ b/ElectronNET.Host/api/screen.ts @@ -1,5 +1,6 @@ -import { Socket } from 'net'; -import { screen } from 'electron'; +import {Socket} from 'net'; +import {screen} from 'electron'; + let electronSocket; export = (socket: Socket) => { @@ -18,7 +19,10 @@ export = (socket: Socket) => { socket.on('register-screen-display-metrics-changed', (id) => { screen.on('display-metrics-changed', (event, display, changedMetrics) => { - electronSocket.emit('screen-display-metrics-changed-event' + id, [display, changedMetrics]); + electronSocket.emit('screen-display-metrics-changed-event' + id, { + display: display, + changedMetrics: changedMetrics + }); }); }); @@ -43,12 +47,22 @@ export = (socket: Socket) => { }); socket.on('screen-getDisplayNearestPoint', (point) => { - const display = screen.getDisplayNearestPoint(point); + let display; + try { + display = screen.getDisplayNearestPoint(point); + } catch { + display = screen.getPrimaryDisplay(); + } electronSocket.emit('screen-getDisplayNearestPointCompleted', display); }); socket.on('screen-getDisplayMatching', (rectangle) => { - const display = screen.getDisplayMatching(rectangle); + let display; + try { + display = screen.getDisplayMatching(rectangle); + } catch { + display = screen.getPrimaryDisplay(); + } electronSocket.emit('screen-getDisplayMatchingCompleted', display); }); }; diff --git a/ElectronNET.Host/api/shell.js.map b/ElectronNET.Host/api/shell.js.map index 83dbfa2b..6f610dc8 100644 --- a/ElectronNET.Host/api/shell.js.map +++ b/ElectronNET.Host/api/shell.js.map @@ -1 +1 @@ -{"version":3,"file":"shell.js","sourceRoot":"","sources":["shell.ts"],"names":[],"mappings":";AACA,uCAAiC;AACjC,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,wBAAwB,EAAE,CAAC,QAAQ,EAAE,EAAE;QAC7C,gBAAK,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAEjC,cAAc,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACvC,MAAM,YAAY,GAAG,MAAM,gBAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEhD,cAAc,CAAC,IAAI,CAAC,yBAAyB,EAAE,YAAY,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QACnD,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,OAAO,EAAE;YACT,MAAM,gBAAK,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;gBAC7C,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC;YACvB,CAAC,CAAC,CAAC;SACN;aAAM;YACH,MAAM,gBAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;gBACtC,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC;YACvB,CAAC,CAAC,CAAC;SACN;QAED,cAAc,CAAC,IAAI,CAAC,6BAA6B,EAAE,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE;QAC1D,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,IAAI;YACA,MAAM,gBAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAChC,OAAO,GAAG,IAAI,CAAC;SAClB;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,GAAG,KAAK,CAAC;SACnB;QAED,cAAc,CAAC,IAAI,CAAC,2BAA2B,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;QACzB,gBAAK,CAAC,IAAI,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE;QACtE,MAAM,OAAO,GAAG,gBAAK,CAAC,iBAAiB,CAAC,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAE1E,cAAc,CAAC,IAAI,CAAC,kCAAkC,EAAE,OAAO,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,wBAAwB,EAAE,CAAC,YAAY,EAAE,EAAE;QACjD,MAAM,eAAe,GAAG,gBAAK,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;QAE7D,cAAc,CAAC,IAAI,CAAC,iCAAiC,EAAE,eAAe,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file +{"version":3,"file":"shell.js","sourceRoot":"","sources":["shell.ts"],"names":[],"mappings":";AACA,uCAA+B;AAE/B,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,wBAAwB,EAAE,CAAC,QAAQ,EAAE,EAAE;QAC7C,gBAAK,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAEjC,cAAc,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QACvC,MAAM,YAAY,GAAG,MAAM,gBAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEhD,cAAc,CAAC,IAAI,CAAC,yBAAyB,EAAE,YAAY,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QACnD,IAAI,MAAM,GAAG,EAAE,CAAC;QAEhB,IAAI,OAAO,EAAE;YACT,MAAM,gBAAK,CAAC,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;gBAC7C,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC;YACvB,CAAC,CAAC,CAAC;SACN;aAAM;YACH,MAAM,gBAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE;gBACtC,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC;YACvB,CAAC,CAAC,CAAC;SACN;QAED,cAAc,CAAC,IAAI,CAAC,6BAA6B,EAAE,MAAM,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE;QAC1D,IAAI,OAAO,GAAG,KAAK,CAAC;QAEpB,IAAI;YACA,MAAM,gBAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAChC,OAAO,GAAG,IAAI,CAAC;SAClB;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,GAAG,KAAK,CAAC;SACnB;QAED,cAAc,CAAC,IAAI,CAAC,2BAA2B,EAAE,OAAO,CAAC,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;QACzB,gBAAK,CAAC,IAAI,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE;QACtE,MAAM,OAAO,GAAG,gBAAK,CAAC,iBAAiB,CAAC,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAE1E,cAAc,CAAC,IAAI,CAAC,kCAAkC,EAAE,OAAO,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,wBAAwB,EAAE,CAAC,YAAY,EAAE,EAAE;QACjD,MAAM,eAAe,GAAG,gBAAK,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;QAE7D,cAAc,CAAC,IAAI,CAAC,iCAAiC,EAAE,eAAe,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;AACP,CAAC,CAAC"} \ No newline at end of file diff --git a/ElectronNET.Host/api/shell.ts b/ElectronNET.Host/api/shell.ts index 9a0dfd7f..d091a725 100644 --- a/ElectronNET.Host/api/shell.ts +++ b/ElectronNET.Host/api/shell.ts @@ -1,5 +1,6 @@ -import { Socket } from 'net'; -import { shell } from 'electron'; +import {Socket} from 'net'; +import {shell} from 'electron'; + let electronSocket; export = (socket: Socket) => { @@ -39,7 +40,7 @@ export = (socket: Socket) => { await shell.trashItem(fullPath); success = true; } catch (error) { - success = false; + success = false; } electronSocket.emit('shell-trashItem-completed', success); diff --git a/ElectronNET.Host/api/tray.js b/ElectronNET.Host/api/tray.js index 0f3a9c97..a239892a 100644 --- a/ElectronNET.Host/api/tray.js +++ b/ElectronNET.Host/api/tray.js @@ -5,42 +5,45 @@ let electronSocket; module.exports = (socket) => { electronSocket = socket; socket.on('register-tray-click', (id) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.on('click', (event, bounds) => { electronSocket.emit('tray-click-event' + id, { eventArgs: event.__proto__, bounds: bounds }); }); } }); socket.on('register-tray-right-click', (id) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.on('right-click', (event, bounds) => { electronSocket.emit('tray-right-click-event' + id, { eventArgs: event.__proto__, bounds: bounds }); }); } }); socket.on('register-tray-double-click', (id) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.on('double-click', (event, bounds) => { - electronSocket.emit('tray-double-click-event' + id, { eventArgs: event.__proto__, bounds: bounds }); + electronSocket.emit('tray-double-click-event' + id, { + eventArgs: event.__proto__, + bounds: bounds + }); }); } }); socket.on('register-tray-balloon-show', (id) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.on('balloon-show', () => { electronSocket.emit('tray-balloon-show-event' + id); }); } }); socket.on('register-tray-balloon-click', (id) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.on('balloon-click', () => { electronSocket.emit('tray-balloon-click-event' + id); }); } }); socket.on('register-tray-balloon-closed', (id) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.on('balloon-closed', () => { electronSocket.emit('tray-balloon-closed-event' + id); }); @@ -58,33 +61,33 @@ module.exports = (socket) => { } }); socket.on('tray-destroy', () => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.destroy(); } }); socket.on('tray-setImage', (image) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.setImage(image); } }); socket.on('tray-setPressedImage', (image) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { const img = electron_1.nativeImage.createFromPath(image); tray.value.setPressedImage(img); } }); socket.on('tray-setToolTip', (toolTip) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.setToolTip(toolTip); } }); socket.on('tray-setTitle', (title) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.setTitle(title); } }); socket.on('tray-displayBalloon', (options) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.displayBalloon(options); } }); @@ -95,7 +98,7 @@ module.exports = (socket) => { } }); socket.on('register-tray-on-event', (eventName, listenerName) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.on(eventName, (...args) => { if (args.length > 1) { electronSocket.emit(listenerName, args[1]); @@ -107,7 +110,7 @@ module.exports = (socket) => { } }); socket.on('register-tray-once-event', (eventName, listenerName) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.once(eventName, (...args) => { if (args.length > 1) { electronSocket.emit(listenerName, args[1]); @@ -124,7 +127,9 @@ module.exports = (socket) => { addMenuItemClickConnector(item.submenu.items, callback); } if ('id' in item && item.id) { - item.click = () => { callback(item.id); }; + item.click = () => { + callback(item.id); + }; } }); } diff --git a/ElectronNET.Host/api/tray.js.map b/ElectronNET.Host/api/tray.js.map index 6a84a7ad..9af4fbc8 100644 --- a/ElectronNET.Host/api/tray.js.map +++ b/ElectronNET.Host/api/tray.js.map @@ -1 +1 @@ -{"version":3,"file":"tray.js","sourceRoot":"","sources":["tray.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"tray.js","sourceRoot":"","sources":["tray.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/ElectronNET.Host/api/tray.ts b/ElectronNET.Host/api/tray.ts index af9f6cf2..bb2fe793 100644 --- a/ElectronNET.Host/api/tray.ts +++ b/ElectronNET.Host/api/tray.ts @@ -1,36 +1,40 @@ -import { Socket } from 'net'; -import { Menu, Tray, nativeImage } from 'electron'; -let tray: { value: Electron.Tray } = (global['$tray'] = global['tray'] || { value: null }); +import {Socket} from 'net'; +import {Menu, nativeImage, Tray} from 'electron'; + +let tray: { value: Electron.Tray } = (global['$tray'] = global['tray'] || {value: null}); let electronSocket; export = (socket: Socket) => { electronSocket = socket; socket.on('register-tray-click', (id) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.on('click', (event, bounds) => { - electronSocket.emit('tray-click-event' + id, [(event).__proto__, bounds]); + electronSocket.emit('tray-click-event' + id, {eventArgs: (event).__proto__, bounds: bounds}); }); } }); socket.on('register-tray-right-click', (id) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.on('right-click', (event, bounds) => { - electronSocket.emit('tray-right-click-event' + id, [(event).__proto__, bounds]); + electronSocket.emit('tray-right-click-event' + id, {eventArgs: (event).__proto__, bounds: bounds}); }); } }); socket.on('register-tray-double-click', (id) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.on('double-click', (event, bounds) => { - electronSocket.emit('tray-double-click-event' + id, [(event).__proto__, bounds]); + electronSocket.emit('tray-double-click-event' + id, { + eventArgs: (event).__proto__, + bounds: bounds + }); }); } }); socket.on('register-tray-balloon-show', (id) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.on('balloon-show', () => { electronSocket.emit('tray-balloon-show-event' + id); }); @@ -38,7 +42,7 @@ export = (socket: Socket) => { }); socket.on('register-tray-balloon-click', (id) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.on('balloon-click', () => { electronSocket.emit('tray-balloon-click-event' + id); }); @@ -46,7 +50,7 @@ export = (socket: Socket) => { }); socket.on('register-tray-balloon-closed', (id) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.on('balloon-closed', () => { electronSocket.emit('tray-balloon-closed-event' + id); }); @@ -69,38 +73,38 @@ export = (socket: Socket) => { }); socket.on('tray-destroy', () => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.destroy(); } }); socket.on('tray-setImage', (image) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.setImage(image); } }); socket.on('tray-setPressedImage', (image) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { const img = nativeImage.createFromPath(image); tray.value.setPressedImage(img); } }); socket.on('tray-setToolTip', (toolTip) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.setToolTip(toolTip); } }); socket.on('tray-setTitle', (title) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.setTitle(title); } }); socket.on('tray-displayBalloon', (options) => { - if (tray.value) { + if (tray.value && !tray.value.isDestroyed()) { tray.value.displayBalloon(options); } }); @@ -113,7 +117,7 @@ export = (socket: Socket) => { }); socket.on('register-tray-on-event', (eventName, listenerName) => { - if (tray.value){ + if (tray.value && !tray.value.isDestroyed()) { tray.value.on(eventName, (...args) => { if (args.length > 1) { electronSocket.emit(listenerName, args[1]); @@ -125,7 +129,7 @@ export = (socket: Socket) => { }); socket.on('register-tray-once-event', (eventName, listenerName) => { - if (tray.value){ + if (tray.value && !tray.value.isDestroyed()) { tray.value.once(eventName, (...args) => { if (args.length > 1) { electronSocket.emit(listenerName, args[1]); @@ -143,7 +147,9 @@ export = (socket: Socket) => { } if ('id' in item && item.id) { - item.click = () => { callback(item.id); }; + item.click = () => { + callback(item.id); + }; } }); } diff --git a/ElectronNET.Host/api/webContents.js b/ElectronNET.Host/api/webContents.js index 334e7739..bab9f036 100644 --- a/ElectronNET.Host/api/webContents.js +++ b/ElectronNET.Host/api/webContents.js @@ -29,20 +29,20 @@ module.exports = (socket) => { }); socket.on('webContents-getPrinters', async (id) => { const printers = await getWindowById(id).webContents.getPrinters(); - electronSocket.emit('webContents-getPrinters-completed' + Id, printers); + electronSocket.emit('webContents-getPrinters-completed' + id, printers); }); socket.on('webContents-print', async (id, options = {}) => { await getWindowById(id).webContents.print(options); - electronSocket.emit('webContents-print-completed' + Id, true); + electronSocket.emit('webContents-print-completed' + id, true); }); socket.on('webContents-printToPDF', async (id, options = {}, path) => { const buffer = await getWindowById(id).webContents.printToPDF(options); fs.writeFile(path, buffer, (error) => { if (error) { - electronSocket.emit('webContents-printToPDF-completed' + Id, false); + electronSocket.emit('webContents-printToPDF-completed' + id, false); } else { - electronSocket.emit('webContents-printToPDF-completed' + Id, true); + electronSocket.emit('webContents-printToPDF-completed' + id, true); } }); }); @@ -141,7 +141,11 @@ module.exports = (socket) => { const browserWindow = getWindowById(id); browserWindow.webContents.session.cookies.removeAllListeners('changed'); browserWindow.webContents.session.cookies.on('changed', (event, cookie, cause, removed) => { - electronSocket.emit('webContents-session-cookies-changed' + id, { cookie: cookie, cause: cause, removed: removed }); + electronSocket.emit('webContents-session-cookies-changed' + id, { + cookie: cookie, + cause: cause, + removed: removed + }); }); }); socket.on('webContents-session-cookies-get', async (id, filter, guid) => { @@ -201,7 +205,7 @@ module.exports = (socket) => { Object.keys(extensionsList).forEach(key => { chromeExtensionInfo.push(extensionsList[key]); }); - electronSocket.emit('webContents-session-getAllExtensions-completed' + Id, chromeExtensionInfo); + electronSocket.emit('webContents-session-getAllExtensions-completed' + id, chromeExtensionInfo); }); socket.on('webContents-session-removeExtension', (id, name) => { const browserWindow = getWindowById(id); @@ -210,11 +214,11 @@ module.exports = (socket) => { socket.on('webContents-session-loadExtension', async (id, path, allowFileAccess = false) => { const browserWindow = getWindowById(id); const extension = await browserWindow.webContents.session.loadExtension(path, { allowFileAccess: allowFileAccess }); - electronSocket.emit('webContents-session-loadExtension-completed' + Id, extension); + electronSocket.emit('webContents-session-loadExtension-completed' + id, extension); }); function getWindowById(id) { if (id >= 1000) { - return browserView_1.browserViewMediateService(id - 1000); + return (0, browserView_1.browserViewMediateService)(id - 1000); } return electron_1.BrowserWindow.fromId(id); } diff --git a/ElectronNET.Host/api/webContents.js.map b/ElectronNET.Host/api/webContents.js.map index 7e6eed71..57e62b40 100644 --- a/ElectronNET.Host/api/webContents.js.map +++ b/ElectronNET.Host/api/webContents.js.map @@ -1 +1 @@ -{"version":3,"file":"webContents.js","sourceRoot":"","sources":["webContents.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"webContents.js","sourceRoot":"","sources":["webContents.ts"],"names":[],"mappings":";AACA,uCAAoD;AACpD,+CAAwD;AAExD,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AACzB,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,EAAE;IACxB,cAAc,GAAG,MAAM,CAAC;IACxB,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,CAAC,EAAE,EAAE,EAAE;QAC7C,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QACxD,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YACtD,cAAc,CAAC,IAAI,CAAC,qBAAqB,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,oCAAoC,EAAE,CAAC,EAAE,EAAE,EAAE;QACnD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,iBAAiB,CAAC,CAAC;QAChE,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC,iBAAiB,EAAE,GAAG,EAAE;YACjD,cAAc,CAAC,IAAI,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE;QACjD,IAAI,OAAO,EAAE;YACT,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;SACvD;aAAM;YACH,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;SAChD;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;QAC9C,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;QACnE,cAAc,CAAC,IAAI,CAAC,mCAAmC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,mBAAmB,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,EAAE;QACtD,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnD,cAAc,CAAC,IAAI,CAAC,6BAA6B,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,wBAAwB,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE;QACjE,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAEvE,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACjC,IAAI,KAAK,EAAE;gBACP,cAAc,CAAC,IAAI,CAAC,kCAAkC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;aACvE;iBAAM;gBACH,cAAc,CAAC,IAAI,CAAC,kCAAkC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;aACtE;QACL,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,UAAU,EAAE;QACxC,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,cAAc,CAAC,IAAI,CAAC,oBAAoB,GAAG,EAAE,EAAE,aAAa,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,oDAAoD,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE;QAC5E,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,8BAA8B,CAAC,OAAO,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,oCAAoC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;QAC/D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAEzD,cAAc,CAAC,IAAI,CAAC,8CAA8C,GAAG,IAAI,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gCAAgC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;QAC3D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAErD,cAAc,CAAC,IAAI,CAAC,0CAA0C,GAAG,IAAI,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,4CAA4C,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;QACvE,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,sBAAsB,EAAE,CAAC;QAEjE,cAAc,CAAC,IAAI,CAAC,sDAAsD,GAAG,IAAI,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,sCAAsC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;QACjE,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;QAE7D,cAAc,CAAC,IAAI,CAAC,gDAAgD,GAAG,IAAI,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8CAA8C,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAClF,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAElE,cAAc,CAAC,IAAI,CAAC,wDAAwD,GAAG,IAAI,CAAC,CAAC;IACzF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,+CAA+C,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE;QACvE,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,6CAA6C,EAAE,CAAC,EAAE,EAAE,EAAE;QAC5D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,4CAA4C,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE;QACpE,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,sCAAsC,EAAE,CAAC,EAAE,EAAE,EAAE;QACrD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE;QACxE,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAE/E,cAAc,CAAC,IAAI,CAAC,2CAA2C,GAAG,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IAC3F,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;QAC7D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,IAAI,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QAEpE,cAAc,CAAC,IAAI,CAAC,4CAA4C,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;QACtD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,QAAQ,GAAG,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QAEjE,cAAc,CAAC,IAAI,CAAC,2CAA2C,GAAG,IAAI,EAAE,QAAQ,CAAC,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;QACvD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC;QAEnE,cAAc,CAAC,IAAI,CAAC,4CAA4C,GAAG,IAAI,EAAE,SAAS,CAAC,CAAC;IACxF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QAClE,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,KAAK,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;QAExE,cAAc,CAAC,IAAI,CAAC,4CAA4C,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC;IACpF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,qCAAqC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;QAC1D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE;QAC1D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE;QACxE,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAEhE,cAAc,CAAC,IAAI,CAAC,wCAAwC,GAAG,IAAI,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,EAAE;QAC7E,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,YAAY,CAAC,SAAS,EAAE,eAAe,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8CAA8C,EAAE,CAAC,EAAE,EAAE,EAAE;QAC7D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QACxE,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACtF,cAAc,CAAC,IAAI,CAAC,qCAAqC,GAAG,EAAE,EAAE;gBAC5D,MAAM,EAAE,MAAM;gBACd,KAAK,EAAE,KAAK;gBACZ,OAAO,EAAE,OAAO;aACnB,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;QACpE,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAE5E,cAAc,CAAC,IAAI,CAAC,2CAA2C,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QACrE,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAE7D,cAAc,CAAC,IAAI,CAAC,2CAA2C,GAAG,IAAI,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,oCAAoC,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QAC1E,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAElE,cAAc,CAAC,IAAI,CAAC,8CAA8C,GAAG,IAAI,CAAC,CAAC;IAC/E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,wCAAwC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;QACnE,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC;QAE7D,cAAc,CAAC,IAAI,CAAC,kDAAkD,GAAG,IAAI,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,qBAAqB,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QAClD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;YACtD,cAAc,CAAC,IAAI,CAAC,8BAA8B,GAAG,EAAE,CAAC,CAAC;QAC7D,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACrB,cAAc,CAAC,IAAI,CAAC,2BAA2B,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,uBAAuB,EAAE,CAAC,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,EAAE;QAC7D,IAAI,eAAe,EAAE;YACjB,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;YACxC,IAAI,aAAa,EAAE;gBACf,aAAa,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;aACtE;SACJ;aAAM;YACH,MAAM,YAAY,GAAkB,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,CAAkB,CAAC;YAC7G,IAAI,IAAI,GAAgB,IAAI,CAAC;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;gBAC1C,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,EAAE,EAAE;oBACrC,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;oBACvB,MAAM;iBACT;aACJ;YACD,IAAI,IAAI,EAAE;gBACN,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;aAC7D;SACJ;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,sCAAsC,EAAE,CAAC,EAAE,EAAE,EAAE;QACrD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,cAAc,GAAG,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC5E,MAAM,mBAAmB,GAAG,EAAE,CAAC;QAE/B,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;YACtC,mBAAmB,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;QAClD,CAAC,CAAC,CAAC;QAEH,cAAc,CAAC,IAAI,CAAC,gDAAgD,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAC;IACpG,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,qCAAqC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;QAC1D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,mCAAmC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,GAAG,KAAK,EAAE,EAAE;QACvF,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,aAAa,CAAC,IAAI,EAAE,EAAC,eAAe,EAAE,eAAe,EAAC,CAAC,CAAC;QAElH,cAAc,CAAC,IAAI,CAAC,6CAA6C,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;IACvF,CAAC,CAAC,CAAC;IAEH,SAAS,aAAa,CAAC,EAAU;QAE7B,IAAI,EAAE,IAAI,IAAI,EAAE;YACZ,OAAO,IAAA,uCAAyB,EAAC,EAAE,GAAG,IAAI,CAAC,CAAC;SAC/C;QAED,OAAO,wBAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IACpC,CAAC;AACL,CAAC,CAAC"} \ No newline at end of file diff --git a/ElectronNET.Host/api/webContents.ts b/ElectronNET.Host/api/webContents.ts index c306bdba..f66fe5a6 100644 --- a/ElectronNET.Host/api/webContents.ts +++ b/ElectronNET.Host/api/webContents.ts @@ -1,6 +1,7 @@ -import { Socket } from 'net'; -import { BrowserWindow, BrowserView } from 'electron'; -import { browserViewMediateService } from './browserView'; +import {Socket} from 'net'; +import {BrowserView, BrowserWindow} from 'electron'; +import {browserViewMediateService} from './browserView'; + const fs = require('fs'); let electronSocket; @@ -34,12 +35,12 @@ export = (socket: Socket) => { socket.on('webContents-getPrinters', async (id) => { const printers = await getWindowById(id).webContents.getPrinters(); - electronSocket.emit('webContents-getPrinters-completed' + Id, printers); + electronSocket.emit('webContents-getPrinters-completed' + id, printers); }); socket.on('webContents-print', async (id, options = {}) => { await getWindowById(id).webContents.print(options); - electronSocket.emit('webContents-print-completed' + Id, true); + electronSocket.emit('webContents-print-completed' + id, true); }); socket.on('webContents-printToPDF', async (id, options = {}, path) => { @@ -47,9 +48,9 @@ export = (socket: Socket) => { fs.writeFile(path, buffer, (error) => { if (error) { - electronSocket.emit('webContents-printToPDF-completed' + Id, false); + electronSocket.emit('webContents-printToPDF-completed' + id, false); } else { - electronSocket.emit('webContents-printToPDF-completed' + Id, true); + electronSocket.emit('webContents-printToPDF-completed' + id, true); } }); }); @@ -181,7 +182,11 @@ export = (socket: Socket) => { browserWindow.webContents.session.cookies.removeAllListeners('changed'); browserWindow.webContents.session.cookies.on('changed', (event, cookie, cause, removed) => { - electronSocket.emit('webContents-session-cookies-changed' + id, [cookie, cause, removed]); + electronSocket.emit('webContents-session-cookies-changed' + id, { + cookie: cookie, + cause: cause, + removed: removed + }); }); }); @@ -253,7 +258,7 @@ export = (socket: Socket) => { chromeExtensionInfo.push(extensionsList[key]); }); - electronSocket.emit('webContents-session-getAllExtensions-completed' + Id, chromeExtensionInfo); + electronSocket.emit('webContents-session-getAllExtensions-completed' + id, chromeExtensionInfo); }); socket.on('webContents-session-removeExtension', (id, name) => { @@ -263,9 +268,9 @@ export = (socket: Socket) => { socket.on('webContents-session-loadExtension', async (id, path, allowFileAccess = false) => { const browserWindow = getWindowById(id); - const extension = await browserWindow.webContents.session.loadExtension(path, { allowFileAccess: allowFileAccess }); + const extension = await browserWindow.webContents.session.loadExtension(path, {allowFileAccess: allowFileAccess}); - electronSocket.emit('webContents-session-loadExtension-completed' + Id, extension); + electronSocket.emit('webContents-session-loadExtension-completed' + id, extension); }); function getWindowById(id: number): Electron.BrowserWindow | Electron.BrowserView { diff --git a/ElectronNET.Host/main.js b/ElectronNET.Host/main.js index 862871b4..402cbdb7 100644 --- a/ElectronNET.Host/main.js +++ b/ElectronNET.Host/main.js @@ -1,24 +1,32 @@ -const { app } = require('electron'); -const { BrowserWindow } = require('electron'); -const { protocol } = require('electron'); +const { app, nativeTheme, BrowserWindow, protocol } = require('electron'); const path = require('path'); -const cProcess = require('child_process').spawn; +const cProcess = require('child_process'); +const process = require('process'); const portscanner = require('portscanner'); const { imageSize } = require('image-size'); +const { connect } = require('http2'); +const crypto = require('crypto'); + +fixPath(); //For macOS and Linux packaged-apps, the path variable might be missing + +let auth = crypto.randomBytes(32).toString('hex'); let io, server, browserWindows, ipc, apiProcess, loadURL; let appApi, menu, dialogApi, notification, tray, webContents; let globalShortcut, shellApi, screen, clipboard, autoUpdater; -let commandLine, browserView; +let commandLine, browserView, desktopCapturer; let powerMonitor; let splashScreen, hostHook; -let mainWindowId, nativeTheme; +let mainWindowId, nativeThemeApi; let dock; let launchFile; let launchUrl; +let ignoreApiProcessClosed = false; let manifestJsonFileName = 'electron.manifest.json'; let watchable = false; +let development = false; + if (app.commandLine.hasSwitch('manifest')) { manifestJsonFileName = app.commandLine.getSwitchValue('manifest'); }; @@ -27,6 +35,10 @@ if (app.commandLine.hasSwitch('watch')) { watchable = true; }; +if (app.commandLine.hasSwitch('development')) { + development = true; +}; + let currentBinPath = path.join(__dirname.replace('app.asar', ''), 'bin'); let manifestJsonFilePath = path.join(currentBinPath, manifestJsonFileName); @@ -36,6 +48,10 @@ if (watchable) { manifestJsonFilePath = path.join(currentBinPath, manifestJsonFileName); } +if (development) { + auth = app.commandLine.getSwitchValue("devauth"); +} + // handle macOS events for opening the app with a file, etc app.on('will-finish-launching', () => { app.on('open-file', (evt, file) => { @@ -48,34 +64,76 @@ app.on('will-finish-launching', () => { }) }); +function prepareForUpdate() { + try { console.log('closing all windows before update'); } catch { } + + ignoreApiProcessClosed = true; + + app.removeAllListeners("window-all-closed"); + + const windows = BrowserWindow.getAllWindows(); + + if (windows.length) { + windows.forEach(w => { + try { + w.removeAllListeners("close"); + w.hide(); + w.destroy(); + } + catch { + //ignore, probably already destroyed + } + }); + } +} + +app.on('before-quit-for-update', () => { prepareForUpdate(); }); + const manifestJsonFile = require(manifestJsonFilePath); + if (manifestJsonFile.singleInstance || manifestJsonFile.aspCoreBackendPort) { const mainInstance = app.requestSingleInstanceLock(); app.on('second-instance', (events, args = []) => { - args.forEach(parameter => { - const words = parameter.split('='); - if(words.length > 1) { - app.commandLine.appendSwitch(words[0].replace('--', ''), words[1]); - } else { - app.commandLine.appendSwitch(words[0].replace('--', '')); - } - }); + let socket = global['electronsocket']; - const windows = BrowserWindow.getAllWindows(); - if (windows.length) { - if (windows[0].isMinimized()) { - windows[0].restore(); - } - windows[0].focus(); + if (socket) { + socket.emit('app-activate-from-second-instance', args); } + + //args.forEach(parameter => { + // const words = parameter.split('='); + + // if(words.length > 1) { + // app.commandLine.appendSwitch(words[0].replace('--', ''), words[1]); + // } else { + // app.commandLine.appendSwitch(words[0].replace('--', '')); + // } + //}); + + //const windows = BrowserWindow.getAllWindows(); + //if (windows.length) { + // if (windows[0].isMinimized()) { + // windows[0].restore(); + // } + // windows[0].focus(); + //} }); if (!mainInstance) { app.quit(); + return; } } +//Some flags need to be set before app is ready +if (manifestJsonFile.hasOwnProperty('cliFlags') && manifestJsonFile.cliFlags.length > 0) { + manifestJsonFile.cliFlags.forEach(flag => { + app.commandLine.appendSwitch(flag); + }); +} + + app.on('ready', () => { // Fix ERR_UNKNOWN_URL_SCHEME using file protocol @@ -88,16 +146,27 @@ app.on('ready', () => { if (isSplashScreenEnabled()) { startSplashScreen(); } - // Added default port as configurable for port restricted environments. - let defaultElectronPort = 8000; - if (manifestJsonFile.electronPort) { - defaultElectronPort = (manifestJsonFile.electronPort) - } - // hostname needs to be localhost, otherwise Windows Firewall will be triggered. - portscanner.findAPortNotInUse(defaultElectronPort, 65535, 'localhost', function (error, port) { - console.log('Electron Socket IO Port: ' + port); + + if (development) { + let port = parseInt(app.commandLine.getSwitchValue('devport')); + try { console.log('Electron Socket IO Port: ' + port); } catch { } startSocketApiBridge(port); - }); + } else { + + // Added default port as configurable for port restricted environments. + let defaultElectronPort = 8000; + if (manifestJsonFile.electronPort) { + defaultElectronPort = (manifestJsonFile.electronPort) + if (defaultElectronPort == 'random') { + defaultElectronPort = (Math.floor(Math.random() * 2000 + 8000)); //Use random port to reduce risk of race conditions between when we find a free port here, and when the app locks on the port + } + } + // hostname needs to be localhost, otherwise Windows Firewall will be triggered. + portscanner.findAPortNotInUse(defaultElectronPort, 65535, 'localhost', function (error, port) { + try { console.log('Electron Socket IO Port: ' + port); } catch { } + startSocketApiBridge(port); + }); + } }); app.on('quit', async (event, exitCode) => { @@ -126,10 +195,17 @@ function isSplashScreenEnabled() { function startSplashScreen() { let imageFile = path.join(currentBinPath, manifestJsonFile.splashscreen.imageFile); + + if (manifestJsonFile.splashscreen.imageFileDark && nativeTheme.shouldUseDarkColors) { + imageFile = path.join(currentBinPath, manifestJsonFile.splashscreen.imageFileDark); + } + imageSize(imageFile, (error, dimensions) => { if (error) { - console.log('load splashscreen error:'); - console.error(error); + try { + console.log('load splashscreen error:'); + console.error(error); + } catch { } throw new Error(error.message); } @@ -158,12 +234,13 @@ function startSplashScreen() { } } - - splashScreen.setIgnoreMouseEvents(true); + //Removed as we want to be able to drag the splash screen: splashScreen.setIgnoreMouseEvents(true); app.once('browser-window-created', () => { - splashScreen.destroy(); - splashScreen = null; + if (splashScreen) { + splashScreen.hide(); + } + //We cannot destroy the window here as this triggers an electron freeze bug (https://github.com/electron/electron/issues/29050) }); const loadSplashscreenUrl = path.join(__dirname, 'splashscreen', 'index.html') + '?imgPath=' + imageFile; @@ -182,14 +259,38 @@ function startSocketApiBridge(port) { // otherwise the Windows Firewall will be triggered server = require('http').createServer(); io = require('socket.io')(); - io.attach(server); + + let socketBufferSize = 1e8; + let pingTimeout = 10000; + let pingInterval = 5000; + + if (manifestJsonFile.hasOwnProperty('socket')) { + + if (manifestJsonFile.socket.hasOwnProperty('socketBufferSize') && manifestJsonFile.socket.bufferSize > 0) { + socketBufferSize = manifestJsonFile.bufferSize * 1e8; + } + + if (manifestJsonFile.socket.hasOwnProperty('socketPingTimeout') && manifestJsonFile.socket.pingTimeout > 0) { + pingTimeout = manifestJsonFile.pingTimeout * 1000; + } + + if (manifestJsonFile.socket.hasOwnProperty('socketPingInterval') && manifestJsonFile.socket.pingInterval > 0) { + pingInterval = manifestJsonFile.pingInterval * 1000; + } + } + + io.attach(server, { pingTimeout: pingTimeout, pingInterval: pingInterval, maxHttpBufferSize: socketBufferSize }); server.listen(port, 'localhost'); + server.on('listening', function () { - console.log('Electron Socket started on port %s at %s', server.address().port, server.address().address); + try { console.log('Electron Socket started on port %s at %s', server.address().port, server.address().address); } catch { } // Now that socket connection is established, we can guarantee port will not be open for portscanner + if (watchable) { startAspCoreBackendWithWatch(port); + } else if (development) { + //Nothing else to do } else { startAspCoreBackend(port); } @@ -199,97 +300,126 @@ function startSocketApiBridge(port) { app['mainWindowURL'] = ""; app['mainWindow'] = null; + let isConnected = false; + let checkReconnectTimeout = 0; // @ts-ignore io.on('connection', (socket) => { + try { console.log('Socket ' + socket.id + ' connected from .NET'); } catch { } + + isConnected = true; + clearTimeout(checkReconnectTimeout); socket.on('disconnect', function (reason) { - console.log('Got disconnect! Reason: ' + reason); + try { console.log('Socket ' + socket.id + ' disconnected from .NET with reason: ' + reason); } catch { } try { if (hostHook) { const hostHookScriptFilePath = path.join(__dirname, 'ElectronHostHook', 'index.js'); delete require.cache[require.resolve(hostHookScriptFilePath)]; hostHook = undefined; } - } catch (error) { - console.error(error.message); + try { console.error(error.message); } catch { } } - }); + clearTimeout(checkReconnectTimeout); - if (global['electronsocket'] === undefined) { - global['electronsocket'] = socket; - global['electronsocket'].setMaxListeners(0); - } + //Give the server 60 seconds to reconnect, otherwise exits + checkReconnectTimeout = setTimeout((_) => { + if (!isConnected) { + app.exit(57005); //0xDEAD + } + }, 60000); - console.log('ASP.NET Core Application connected...', 'global.electronsocket', global['electronsocket'].id, new Date()); - - if (appApi === undefined) appApi = require('./api/app')(socket, app); - if (browserWindows === undefined) browserWindows = require('./api/browserWindows')(socket, app); - if (commandLine === undefined) commandLine = require('./api/commandLine')(socket, app); - if (autoUpdater === undefined) autoUpdater = require('./api/autoUpdater')(socket); - if (ipc === undefined) ipc = require('./api/ipc')(socket); - if (menu === undefined) menu = require('./api/menu')(socket); - if (dialogApi === undefined) dialogApi = require('./api/dialog')(socket); - if (notification === undefined) notification = require('./api/notification')(socket); - if (tray === undefined) tray = require('./api/tray')(socket); - if (webContents === undefined) webContents = require('./api/webContents')(socket); - if (globalShortcut === undefined) globalShortcut = require('./api/globalShortcut')(socket); - if (shellApi === undefined) shellApi = require('./api/shell')(socket); - if (screen === undefined) screen = require('./api/screen')(socket); - if (clipboard === undefined) clipboard = require('./api/clipboard')(socket); - if (browserView === undefined) browserView = require('./api/browserView').browserViewApi(socket); - if (powerMonitor === undefined) powerMonitor = require('./api/powerMonitor')(socket); - if (nativeTheme === undefined) nativeTheme = require('./api/nativeTheme')(socket); - if (dock === undefined) dock = require('./api/dock')(socket); - - socket.on('register-app-open-file-event', (id) => { - global['electronsocket'] = socket; + }); + + socket.on("auth", function (authKey) { + if (authKey != auth) { + throw new Error("Invalid auth key"); + } - app.on('open-file', (event, file) => { - event.preventDefault(); + //We only hook to events on app on the first initialization of each component + let firstTime = (global['electronsocket'] == undefined); - global['electronsocket'].emit('app-open-file' + id, file); + global['electronsocket'] = socket; + socket.setMaxListeners(0); + + try { console.log('.NET connected on socket ' + socket.id + ' on ' + new Date()); } catch { } + + appApi = require('./api/app')(socket, app, firstTime); + browserWindows = require('./api/browserWindows')(socket, app, firstTime); + commandLine = require('./api/commandLine')(socket, app); + autoUpdater = require('./api/autoUpdater')(socket, app); + ipc = require('./api/ipc')(socket); + menu = require('./api/menu')(socket); + dialogApi = require('./api/dialog')(socket); + notification = require('./api/notification')(socket); + tray = require('./api/tray')(socket); + webContents = require('./api/webContents')(socket); + globalShortcut = require('./api/globalShortcut')(socket); + shellApi = require('./api/shell')(socket); + screen = require('./api/screen')(socket); + desktopCapturer = require('./api/desktopCapturer')(socket); + clipboard = require('./api/clipboard')(socket); + browserView = require('./api/browserView').browserViewApi(socket); + powerMonitor = require('./api/powerMonitor')(socket); + nativeThemeApi = require('./api/nativeTheme')(socket); + dock = require('./api/dock')(socket); + + socket.on('splashscreen-destroy', () => { + if (splashScreen) { + splashScreen.destroy(); + splashScreen = null; + } }); - if (launchFile) { - global['electronsocket'].emit('app-open-file' + id, launchFile); - } - }); + socket.on('prepare-for-update', () => { prepareForUpdate(); }); - socket.on('register-app-open-url-event', (id) => { - global['electronsocket'] = socket; + socket.on('register-app-open-file-event', (id) => { + global['electronsocket'] = socket; - app.on('open-url', (event, url) => { - event.preventDefault(); + app.on('open-file', (event, file) => { + event.preventDefault(); + global['electronsocket'].emit('app-open-file' + id, file); + }); - global['electronsocket'].emit('app-open-url' + id, url); + if (launchFile) { + socket.emit('app-open-file' + id, launchFile); + } }); - if (launchUrl) { - global['electronsocket'].emit('app-open-url' + id, launchUrl); - } - }); + socket.on('register-app-open-url-event', (id) => { + global['electronsocket'] = socket; - socket.on('console-stdout', (data) => { - console.log(`stdout: ${data.toString()}`); - }); + app.on('open-url', (event, url) => { + event.preventDefault(); + global['electronsocket'].emit('app-open-url' + id, url); + }); - socket.on('console-stderr', (data) => { - console.log(`stderr: ${data.toString()}`); - }); + if (launchUrl) { + socket.emit('app-open-url' + id, launchUrl); + } + }); + + socket.on('console-stdout', (data) => { + try { console.log(`stdout: ${data.toString()}`); } catch { } + }); - try { - const hostHookScriptFilePath = path.join(__dirname, 'ElectronHostHook', 'index.js'); + socket.on('console-stderr', (data) => { + try { console.log(`stderr: ${data.toString()}`); } catch { } + }); + + try { + const hostHookScriptFilePath = path.join(__dirname, 'ElectronHostHook', 'index.js'); - if (isModuleAvailable(hostHookScriptFilePath) && hostHook === undefined) { - const { HookService } = require(hostHookScriptFilePath); - hostHook = new HookService(socket, app); - hostHook.onHostReady(); + if (isModuleAvailable(hostHookScriptFilePath) && hostHook === undefined) { + const { HookService } = require(hostHookScriptFilePath); + hostHook = new HookService(socket, app); + hostHook.onHostReady(); + } + } catch (error) { + try { console.error(error.message); } catch { } } - } catch (error) { - console.error(error.message); - } + }); }); } @@ -312,7 +442,7 @@ function startAspCoreBackend(electronPort) { } function startBackend(aspCoreBackendPort) { - console.log('ASP.NET Core Port: ' + aspCoreBackendPort); + console.log('.NET Core Port: ' + aspCoreBackendPort); loadURL = `http://localhost:${aspCoreBackendPort}`; const parameters = [getEnvironmentParameter(), `/electronPort=${electronPort}`, `/electronWebPort=${aspCoreBackendPort}`, `/electronPID=${process.pid}`]; let binaryFile = manifestJsonFile.executable; @@ -328,15 +458,21 @@ function startAspCoreBackend(electronPort) { if (manifestJsonFile.hasOwnProperty('detachedProcess')) { detachedProcess = manifestJsonFile.detachedProcess; if (detachedProcess) { - stdioopt = 'ignore'; + stdioopt = ['pipe', 'ignore', 'ignore']; } } + let env = process.env; + + if (manifestJsonFile.hasOwnProperty('variables')) { + env = { ...env, ...manifestJsonFile.variables }; + } + let binFilePath = path.join(currentBinPath, binaryFile); - var options = { cwd: currentBinPath, detached: detachedProcess, stdio: stdioopt }; + var options = { cwd: currentBinPath, env : env, detached: detachedProcess, stdio: stdioopt }; - apiProcess = cProcess(binFilePath, parameters, options); + apiProcess = cProcess.spawn(binFilePath, parameters, options); if (!detachedProcess) { apiProcess.stdout.on('data', (data) => { @@ -349,15 +485,27 @@ function startAspCoreBackend(electronPort) { } apiProcess.on('close', (code) => { - console.log(`ASP.NET Process exited with code ${code}`); - if (code != 0) { - console.log(`Will quit Electron, as exit code != 0 (got ${code})`); + console.log(`.NET process exited with code ${code}`); + if (!ignoreApiProcessClosed) { + if (code != 0) { + console.log(`Will quit Electron, as exit code != 0 (got ${code})`); + } app.exit(code); } + else if (os.platform() === 'darwin') { + //There is a bug on the updater on macOS never quiting and starting the update process + //We give Squirrel.Mac enough time to access the update file, and then just force-exit here + setTimeout(() => app.exit(0), 30_000); + } }); + + apiProcess.stdin.setEncoding = 'utf-8'; + apiProcess.stdin.write('Auth=' + auth + '\n'); + apiProcess.stdin.end(); + if (detachedProcess) { - console.log('Detached from ASP.NET process'); + console.log('Detached from .NET process'); apiProcess.unref(); } } @@ -374,7 +522,7 @@ function startAspCoreBackendWithWatch(electronPort) { } function startBackend(aspCoreBackendPort) { - console.log('ASP.NET Core Watch Port: ' + aspCoreBackendPort); + console.log('.NET watch Port: ' + aspCoreBackendPort); loadURL = `http://localhost:${aspCoreBackendPort}`; const parameters = ['watch', 'run', getEnvironmentParameter(), `/electronPort=${electronPort}`, `/electronWebPort=${aspCoreBackendPort}`, `/electronPID=${process.pid}`]; @@ -388,9 +536,15 @@ function startAspCoreBackendWithWatch(electronPort) { } } - var options = { cwd: currentBinPath, env: process.env, detached: detachedProcess, stdio: stdioopt }; + let env = process.env; + + if (manifestJsonFile.hasOwnProperty('variables')) { + env = { ...env, ...manifestJsonFile.variables }; + } + + var options = { cwd: currentBinPath, env: env, detached: detachedProcess, stdio: stdioopt }; - apiProcess = cProcess('dotnet', parameters, options); + apiProcess = cProcess.spawn('dotnet', parameters, options); if (!detachedProcess) { apiProcess.stdout.on('data', (data) => { @@ -403,11 +557,24 @@ function startAspCoreBackendWithWatch(electronPort) { } apiProcess.on('close', (code) => { - console.log(`ASP.NET Process exited with code ${code}`); - if (code != 0) { - console.log(`Will quit Electron, as exit code != 0 (got ${code})`); + console.log(`.NET process exited with code ${code}`); + if (!ignoreApiProcessClosed) { + if (code != 0) { + console.log(`Will quit Electron, as exit code != 0 (got ${code})`); + } + console.log('Will quit Electron now'); + app.exit(code); } + else if (os.platform() === 'darwin') { + console.log('.NET process and Electron has a pending update, will force quit in 10s...'); + //There is a bug on the updater on macOS never quiting and starting the update process + //We give Squirrel.Mac enough time to access the update file, and then just force-exit here + setTimeout(() => app.exit(0), 10_000); + } + else { + console.log('.NET process and Electron has a pending update...'); + } }); if (detachedProcess) { @@ -424,3 +591,84 @@ function getEnvironmentParameter() { return ''; } + + +//This code is derived from gh/sindresorhus/shell-path/, gh/sindresorhus/shell-env/, gh/sindresorhus/default-shell/, gh/chalk/ansi-regex, all under MIT license +function fixPath() { + if (process.platform === 'win32') { + return; + } + const shellFromEnv = shellEnvSync(); + + if (process.env.PATH) { + console.log("Started with PATH = " + process.env.PATH); + } + + if (shellFromEnv) { + process.env.PATH = shellFromEnv; + } else { + process.env.PATH = [ + './node_modules/.bin', + '/.nodebrew/current/bin', + '/usr/local/bin', + process.env.PATH, + ].join(':'); //macOS and Linux path separator is ':' + } + console.log("Using PATH = " + process.env.PATH); +} + +function shellEnvSync() { + const args = [ + '-ilc', + 'echo -n "_SHELL_ENV_DELIMITER_"; env; echo -n "_SHELL_ENV_DELIMITER_"; exit', + ]; + + const env = { + // Disables Zsh auto-update that can block the process. + DISABLE_AUTO_UPDATE: 'true', + }; + + let shell = process.env.SHELL || '/bin/sh'; + + if (process.platform === 'darwin') { + shell = process.env.SHELL || '/bin/zsh'; + } + + try { + let { stdout } = cProcess.spawnSync(shell, args, { env }); + if (Buffer.isBuffer(stdout)) { + stdout = stdout.toString(); + } + return parseEnv(stdout); + } catch (error) { + if (shell) { + throw error; + } else { + return process.env; + } + } +} + +function parseEnv(envString) { + const returnValue = {}; + + if (envString) { + envString = envString.split('_SHELL_ENV_DELIMITER_')[1]; + for (const line of envString.replace(ansiRegex(), '').split('\n').filter(line => Boolean(line))) { + const [key, ...values] = line.split('='); + returnValue[key.toUpperCase()] = values.join('='); + } + } + + return returnValue["PATH"]; + + + function ansiRegex() { + const pattern = [ + '[\\u001B\\u009B][[\\]()#;?]*(?:(?:(?:(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]+)*|[a-zA-Z\\d]+(?:;[-a-zA-Z\\d\\/#&.:=?%@~_]*)*)?\\u0007)', + '(?:(?:\\d{1,4}(?:;\\d{0,4})*)?[\\dA-PR-TZcf-ntqry=><~]))' + ].join('|'); + + return new RegExp(pattern, 'g'); + } +} diff --git a/ElectronNET.Host/package-lock.json b/ElectronNET.Host/package-lock.json index 0f24a4ac..7fabdffa 100644 --- a/ElectronNET.Host/package-lock.json +++ b/ElectronNET.Host/package-lock.json @@ -31,15 +31,15 @@ } }, "@electron/get": { - "version": "1.12.4", - "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.12.4.tgz", - "integrity": "sha512-6nr9DbJPUR9Xujw6zD3y+rS95TyItEVM0NVjt1EehY2vUWfIgPiIPVHxCvaTS0xr2B+DRxovYVKbuOWqC35kjg==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-1.14.1.tgz", + "integrity": "sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==", "dev": true, "requires": { "debug": "^4.1.1", "env-paths": "^2.2.0", "fs-extra": "^8.1.0", - "global-agent": "^2.0.2", + "global-agent": "^3.0.0", "global-tunnel-ng": "^2.7.1", "got": "^9.6.0", "progress": "^2.0.3", @@ -61,6 +61,11 @@ "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", "dev": true }, + "@socket.io/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@socket.io/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-dOlCBKnDw4iShaIsH/bxujKTM18+2TOAsYz+KSc11Am38H4q5Xw8Bbz97ZYdrVNM+um3p7w86Bvvmcn9q+5+eQ==" + }, "@szmarczak/http-timer": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", @@ -70,31 +75,40 @@ "defer-to-connect": "^1.0.1" } }, + "@types/component-emitter": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.11.tgz", + "integrity": "sha512-SRXjM+tfsSlA9VuG8hGO2nft2p8zjXCK1VcC6N4NXbBbYbSia9kzCChYQajIjzIqOOOuh5Ock6MmV2oux4jDZQ==" + }, + "@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==" + }, + "@types/cors": { + "version": "2.8.12", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.12.tgz", + "integrity": "sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==" + }, "@types/node": { - "version": "15.14.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.0.tgz", - "integrity": "sha512-um/+/ip3QZmwLfIkWZSNtQIJNVAqrJ92OkLMeuZrjZMTAJniI7fh8N8OICyDhAJ2mzgk/fmYFo72jRr5HyZ1EQ==", - "dev": true + "version": "16.11.45", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.45.tgz", + "integrity": "sha512-3rKg/L5x0rofKuuUt5zlXzOnKyIHXmIu5R8A0TuNDMF2062/AOIDBciFIjToLEJ/9F9DzkHNot+BpNsMI1OLdQ==" }, "@types/semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-0caWDWmpCp0uifxFh+FaqK3CuZ2SkRR/ZRxAV5+zNdC3QVUi6wyOJnefhPvtNt8NQWXB5OA93BUvZsXpWat2Xw==" + "version": "7.3.9", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.9.tgz", + "integrity": "sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==" }, "accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "requires": { - "mime-types": "~2.1.24", - "negotiator": "0.6.2" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" } }, - "after": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/after/-/after-0.8.2.tgz", - "integrity": "sha1-/ts5T58OAqqXaOcCvaI7UF+ufh8=" - }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -113,11 +127,6 @@ "sprintf-js": "~1.0.2" } }, - "arraybuffer.slice": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.7.tgz", - "integrity": "sha512-wGUIVQXuehL5TCqQun8OW81jGzAWycqzFF8lFp+GOM5BXLYj3bKNsYC4daB7n6XjCqxQA/qgTJ+8ANR3acjrog==" - }, "async": { "version": "2.6.3", "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", @@ -126,10 +135,11 @@ "lodash": "^4.17.14" } }, - "backo2": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", - "integrity": "sha1-MasayLEpNjRj41s+u2n038+6eUc=" + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true }, "balanced-match": { "version": "1.0.2", @@ -137,25 +147,15 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, - "base64-arraybuffer": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", - "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=" - }, "base64id": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" }, - "blob": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.5.tgz", - "integrity": "sha512-gaqbzQPqOoamawKg0LGVd7SzLgXS+JH61oWprSLH+P+abTczqJbhTR8CmJ2u9/bUYNmHTGJx/UEmn6doAvvuig==" - }, "boolean": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.1.2.tgz", - "integrity": "sha512-YN6UmV0FfLlBVvRvNPx3pz5W/mUoYB24J4WSXOKP/OOJpi+Oq6WYqPaNTHzjI0QzwWtnvEd5CGYyQPgp1jFxnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", "dev": true, "optional": true }, @@ -172,32 +172,22 @@ "buffer-crc32": { "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", "dev": true }, "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true }, "builder-util-runtime": { - "version": "8.7.5", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.7.5.tgz", - "integrity": "sha512-fgUFHKtMNjdvH6PDRFntdIGUPgwZ69sXsAqEulCtoiqgWes5agrMq/Ud274zjJRTbckYh2PHh8/1CpFc6dpsbQ==", + "version": "8.9.2", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.9.2.tgz", + "integrity": "sha512-rhuKm5vh7E0aAmT6i8aoSfEjxzdYEFX7zDApK+eNgOhjofnWb74d9SRJv0H/8nsgOkos0TZ4zxW0P8J4N7xQ2A==", "requires": { "debug": "^4.3.2", "sax": "^1.2.4" - }, - "dependencies": { - "debug": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", - "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", - "requires": { - "ms": "2.1.2" - } - } } }, "builtin-modules": { @@ -258,9 +248,9 @@ } }, "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", "dev": true, "requires": { "mimic-response": "^1.0.0" @@ -287,21 +277,11 @@ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true }, - "component-bind": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", - "integrity": "sha1-AMYIq33Nk4l8AAllGx06jh5zu9E=" - }, "component-emitter": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==" }, - "component-inherit": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz", - "integrity": "sha1-ZF/ErfWLcrZJ1crmUTVhnbJv8UM=" - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -332,33 +312,34 @@ } }, "cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" - }, - "core-js": { - "version": "3.15.2", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.15.2.tgz", - "integrity": "sha512-tKs41J7NJVuaya8DxIOCnl8QuPHx5/ZVbFo1oKgVl1qHFBBrDctzQGtuLjPpRdNTWmKPH6oEvgN/MUID+l485Q==", - "dev": true, - "optional": true + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" }, "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", "dev": true }, + "cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "requires": { + "object-assign": "^4", + "vary": "^1" + } + }, "dasherize": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz", "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg=" }, "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", "requires": { "ms": "2.1.2" } @@ -366,7 +347,7 @@ "decompress-response": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", "dev": true, "requires": { "mimic-response": "^1.0.0" @@ -379,13 +360,14 @@ "dev": true }, "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", + "integrity": "sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA==", "dev": true, "optional": true, "requires": { - "object-keys": "^1.0.12" + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" } }, "detect-node": { @@ -401,41 +383,79 @@ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", "dev": true }, + "dotenv": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.1.tgz", + "integrity": "sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ==", + "dev": true + }, "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.5.tgz", + "integrity": "sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==", "dev": true }, "electron": { - "version": "13.1.5", - "resolved": "https://registry.npmjs.org/electron/-/electron-13.1.5.tgz", - "integrity": "sha512-ZoMCcPQNs/zO/Zdb5hq5H+rwRaKrdI3/sfXEwBVMx7f5jwa9jPQB3dZ2+7t59uD9VcFAWsH/pozr8nPPlv0tyw==", + "version": "19.0.9", + "resolved": "https://registry.npmjs.org/electron/-/electron-19.0.9.tgz", + "integrity": "sha512-ooEwrv8Y7NSzdhKcl6kPCYecnzcg5nFWuS5ryG+VFH3MMBR8zXh9nW2wLsZrBz6OGUxXrcc5BKBC7dA8C6RhGQ==", "dev": true, "requires": { - "@electron/get": "^1.0.1", - "@types/node": "^14.6.2", + "@electron/get": "^1.14.1", + "@types/node": "^16.11.26", "extract-zip": "^1.0.3" + } + }, + "electron-notarize": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/electron-notarize/-/electron-notarize-1.2.1.tgz", + "integrity": "sha512-u/ECWhIrhkSQpZM4cJzVZ5TsmkaqrRo5LDC/KMbGF0sPkm53Ng59+M0zp8QVaql0obfJy9vlVT+4iOkAi2UDlA==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "fs-extra": "^9.0.1" }, "dependencies": { - "@types/node": { - "version": "14.17.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.17.4.tgz", - "integrity": "sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==", + "fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true } } }, "electron-updater": { - "version": "4.3.9", - "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-4.3.9.tgz", - "integrity": "sha512-LCNfedSwZfS4Hza+pDyPR05LqHtGorCStaBgVpRnfKxOlZcvpYEX0AbMeH5XUtbtGRoH2V8osbbf2qKPNb7AsA==", + "version": "4.6.5", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-4.6.5.tgz", + "integrity": "sha512-kdTly8O9mSZfm9fslc1mnCY+mYOeaYRy7ERa2Fed240u01BKll3aiupzkd07qKw69KvhBSzuHroIW3mF0D8DWA==", "requires": { - "@types/semver": "^7.3.5", - "builder-util-runtime": "8.7.5", + "@types/semver": "^7.3.6", + "builder-util-runtime": "8.9.2", "fs-extra": "^10.0.0", "js-yaml": "^4.1.0", - "lazy-val": "^1.0.4", + "lazy-val": "^1.0.5", "lodash.escaperegexp": "^4.1.2", "lodash.isequal": "^4.5.0", "semver": "^7.3.5" @@ -483,7 +503,7 @@ "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", "dev": true, "optional": true }, @@ -497,71 +517,28 @@ } }, "engine.io": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-3.5.0.tgz", - "integrity": "sha512-21HlvPUKaitDGE4GXNtQ7PLP0Sz4aWLddMPw2VTyFz1FVZqu/kZsJUO8WNpKuE/OCL7nkfRaOui2ZCJloGznGA==", + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", + "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", "requires": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", "accepts": "~1.3.4", "base64id": "2.0.0", "cookie": "~0.4.1", - "debug": "~4.1.0", - "engine.io-parser": "~2.2.0", - "ws": "~7.4.2" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "engine.io-client": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-3.5.2.tgz", - "integrity": "sha512-QEqIp+gJ/kMHeUun7f5Vv3bteRHppHH/FMBQX/esFj/fuYfjyUKWGMo3VCvIP/V8bE9KcjHmRZrhIz2Z9oNsDA==", - "requires": { - "component-emitter": "~1.3.0", - "component-inherit": "0.0.3", - "debug": "~3.1.0", - "engine.io-parser": "~2.2.0", - "has-cors": "1.1.0", - "indexof": "0.0.1", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "ws": "~7.4.2", - "xmlhttprequest-ssl": "~1.6.2", - "yeast": "0.1.2" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - } + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.2.3" } }, "engine.io-parser": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-2.2.1.tgz", - "integrity": "sha512-x+dN/fBH8Ro8TFwJ+rkB2AmuVw9Yu2mockR/p3W8f8YtExwFgDvBDi0GWyb4ZLkpahtDGZgtr3zLovanJghPqg==", + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", + "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", "requires": { - "after": "0.8.2", - "arraybuffer.slice": "~0.0.7", - "base64-arraybuffer": "0.1.4", - "blob": "0.0.5", - "has-binary2": "~1.0.2" + "@socket.io/base64-arraybuffer": "~1.0.2" } }, "env-paths": { @@ -614,7 +591,7 @@ "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "dev": true } } @@ -622,7 +599,7 @@ "fd-slicer": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", "dev": true, "requires": { "pend": "~1.2.0" @@ -651,6 +628,18 @@ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", "dev": true }, + "get-intrinsic": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.2.tgz", + "integrity": "sha512-Jfm3OyCxHh9DJyc28qGk+JmfkpO41A4XkneDSujN9MDXrm4oDKdHvndhZ2dN94+ERNfkYJWDclW6k2L/ZGHjXA==", + "dev": true, + "optional": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.3" + } + }, "get-stream": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", @@ -675,14 +664,13 @@ } }, "global-agent": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-2.2.0.tgz", - "integrity": "sha512-+20KpaW6DDLqhG7JDiJpD1JvNvb8ts+TNl7BPOYcURqCrXqnN1Vf+XVOrkKJAFPqfX+oEhsdzOj1hLWkBTdNJg==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", "dev": true, "optional": true, "requires": { "boolean": "^3.0.1", - "core-js": "^3.6.5", "es6-error": "^4.1.1", "matcher": "^3.0.0", "roarr": "^2.15.3", @@ -704,9 +692,9 @@ } }, "globalthis": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz", - "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", "dev": true, "optional": true, "requires": { @@ -746,25 +734,29 @@ "function-bind": "^1.1.1" } }, - "has-binary2": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-binary2/-/has-binary2-1.0.3.tgz", - "integrity": "sha512-G1LWKhDSvhGeAQ8mPVQlqNcOB2sJdwATtZKl2pDKKHfpf/rYj24lkinxf69blJbnsvtqqNU+L3SL50vzZhXOnw==", - "requires": { - "isarray": "2.0.1" - } - }, - "has-cors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", - "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" - }, "has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, + "has-property-descriptors": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", + "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "dev": true, + "optional": true, + "requires": { + "get-intrinsic": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "optional": true + }, "http-cache-semantics": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", @@ -772,18 +764,13 @@ "dev": true }, "image-size": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.0.tgz", - "integrity": "sha512-JLJ6OwBfO1KcA+TvJT+v8gbE6iWbj24LyDNFgFEN0lzegn6cC6a/p3NIDaepMsJjQjlUWqIC7wJv8lBFxPNjcw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.1.tgz", + "integrity": "sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ==", "requires": { "queue": "6.0.2" } }, - "indexof": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz", - "integrity": "sha1-gtwzbSMrkGIXnQWrMpOmYFn9Q10=" - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", @@ -824,9 +811,10 @@ } }, "isarray": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.1.tgz", - "integrity": "sha1-o32U7ZzaLVmGXJ92/llu4fM4dB4=" + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true }, "js-tokens": { "version": "4.0.0", @@ -847,20 +835,20 @@ "json-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "integrity": "sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==", "dev": true }, "json-stringify-safe": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", "dev": true, "optional": true }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, "requires": { "graceful-fs": "^4.1.6" @@ -925,16 +913,16 @@ } }, "mime-db": { - "version": "1.48.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", - "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==" + "version": "1.51.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", + "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" }, "mime-types": { - "version": "2.1.31", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", - "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", + "version": "2.1.34", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", + "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", "requires": { - "mime-db": "1.48.0" + "mime-db": "1.51.0" } }, "mimic-response": { @@ -973,9 +961,9 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, "normalize-url": { "version": "4.5.1", @@ -994,6 +982,11 @@ "pify": "^3.0.0" } }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -1016,16 +1009,6 @@ "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", "dev": true }, - "parseqs": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseqs/-/parseqs-0.0.6.tgz", - "integrity": "sha512-jeAGzMDbfSHHA091hr0r31eYfTig+29g3GKKE/PPbEQ65X0lmMwlEoqmhzu0iztID5uJpZsFlUPDP8ThPL7M8w==" - }, - "parseuri": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", - "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" - }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -1041,13 +1024,13 @@ "pend": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", "dev": true }, "pify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", "dev": true, "optional": true }, @@ -1063,7 +1046,7 @@ "prepend-http": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "integrity": "sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==", "dev": true }, "process-nextick-args": { @@ -1081,7 +1064,7 @@ "proto-list": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", "dev": true, "optional": true }, @@ -1116,14 +1099,6 @@ "safe-buffer": "~5.1.1", "string_decoder": "~1.1.1", "util-deprecate": "~1.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } } }, "resolve": { @@ -1139,7 +1114,7 @@ "responselike": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "integrity": "sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==", "dev": true, "requires": { "lowercase-keys": "^1.0.0" @@ -1191,7 +1166,7 @@ "semver-compare": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", "dev": true, "optional": true }, @@ -1206,99 +1181,31 @@ } }, "socket.io": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-2.4.1.tgz", - "integrity": "sha512-Si18v0mMXGAqLqCVpTxBa8MGqriHGQh8ccEOhmsmNS3thNCGBwO8WGrwMibANsWtQQ5NStdZwHqZR3naJVFc3w==", - "requires": { - "debug": "~4.1.0", - "engine.io": "~3.5.0", - "has-binary2": "~1.0.2", - "socket.io-adapter": "~1.1.0", - "socket.io-client": "2.4.0", - "socket.io-parser": "~3.4.0" - }, - "dependencies": { - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - } + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", + "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", + "requires": { + "accepts": "~1.3.4", + "base64id": "~2.0.0", + "debug": "~4.3.2", + "engine.io": "~6.1.0", + "socket.io-adapter": "~2.3.3", + "socket.io-parser": "~4.0.4" } }, "socket.io-adapter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-1.1.2.tgz", - "integrity": "sha512-WzZRUj1kUjrTIrUKpZLEzFZ1OLj5FwLlAFQs9kuZJzJi5DKdU7FsWc36SNmA8iDOtwBQyT8FkrriRM8vXLYz8g==" - }, - "socket.io-client": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-2.4.0.tgz", - "integrity": "sha512-M6xhnKQHuuZd4Ba9vltCLT9oa+YvTsP8j9NcEiLElfIg8KeYPyhWOes6x4t+LTAC8enQbE/995AdTem2uNyKKQ==", - "requires": { - "backo2": "1.0.2", - "component-bind": "1.0.0", - "component-emitter": "~1.3.0", - "debug": "~3.1.0", - "engine.io-client": "~3.5.0", - "has-binary2": "~1.0.2", - "indexof": "0.0.1", - "parseqs": "0.0.6", - "parseuri": "0.0.6", - "socket.io-parser": "~3.3.0", - "to-array": "0.1.4" - }, - "dependencies": { - "debug": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" - }, - "socket.io-parser": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.3.2.tgz", - "integrity": "sha512-FJvDBuOALxdCI9qwRrO/Rfp9yfndRtc1jSgVgV8FDraihmSP/MLGD5PEuJrNfjALvcQ+vMDM/33AWOYP/JSjDg==", - "requires": { - "component-emitter": "~1.3.0", - "debug": "~3.1.0", - "isarray": "2.0.1" - } - } - } + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-2.3.3.tgz", + "integrity": "sha512-Qd/iwn3VskrpNO60BeRyCyr8ZWw9CPZyitW4AQwmRZ8zCiyDiL+znRnWX6tDHXnWn1sJrM1+b6Mn6wEDJJ4aYQ==" }, "socket.io-parser": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-3.4.1.tgz", - "integrity": "sha512-11hMgzL+WCLWf1uFtHSNvliI++tcRUWdoeYuwIl+Axvwy9z2gQM+7nJyN3STj1tLj5JyIUH8/gpDGxzAlDdi0A==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.0.4.tgz", + "integrity": "sha512-t+b0SS+IxG7Rxzda2EVvyBZbvFPBCjJoyHuE0P//7OAsN23GItzDRdWa6ALxZI/8R5ygK7jAR6t028/z+7295g==", "requires": { - "component-emitter": "1.2.1", - "debug": "~4.1.0", - "isarray": "2.0.1" - }, - "dependencies": { - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=" - }, - "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", - "requires": { - "ms": "^2.1.1" - } - } + "@types/component-emitter": "^1.2.10", + "component-emitter": "~1.3.0", + "debug": "~4.3.1" } }, "sprintf-js": { @@ -1334,11 +1241,6 @@ "has-flag": "^3.0.0" } }, - "to-array": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/to-array/-/to-array-0.1.4.tgz", - "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=" - }, "to-readable-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", @@ -1406,13 +1308,13 @@ "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "dev": true }, "typescript": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", - "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", + "version": "4.7.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz", + "integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==", "dev": true }, "universalify": { @@ -1424,7 +1326,7 @@ "url-parse-lax": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", - "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "integrity": "sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==", "dev": true, "requires": { "prepend-http": "^2.0.0" @@ -1433,9 +1335,14 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -1443,14 +1350,9 @@ "dev": true }, "ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==" - }, - "xmlhttprequest-ssl": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-1.6.3.tgz", - "integrity": "sha512-3XfeQE/wNkvrIktn2Kf0869fC0BN6UpydVasGIeSm2B1Llihf7/0UfZM+eCkOw3P7bP4+qPgqhm7ZoxuJtFU0Q==" + "version": "8.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", + "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==" }, "yallist": { "version": "4.0.0", @@ -1460,17 +1362,12 @@ "yauzl": { "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", "dev": true, "requires": { "buffer-crc32": "~0.2.3", "fd-slicer": "~1.1.0" } - }, - "yeast": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/yeast/-/yeast-0.1.2.tgz", - "integrity": "sha1-AI4G2AlDIMNy28L47XagymyKxBk=" } } } diff --git a/ElectronNET.Host/package.json b/ElectronNET.Host/package.json index 628c1525..73234c51 100644 --- a/ElectronNET.Host/package.json +++ b/ElectronNET.Host/package.json @@ -13,15 +13,17 @@ }, "dependencies": { "dasherize": "^2.0.0", - "electron-updater": "^4.3.9", - "image-size": "^1.0.0", + "electron-updater": "^4.6.2", + "image-size": "^1.0.1", "portscanner": "^2.2.0", - "socket.io": "^2.4.0" + "socket.io": "^4.4.1" }, "devDependencies": { - "@types/node": "^15.14.0", - "electron": "^13.1.5", + "@types/node": "^16.11.45", + "dotenv": "^16.0.1", + "electron": "19.0.9", + "electron-notarize": "^1.2.1", "tslint": "^6.1.3", - "typescript": "^4.3.5" + "typescript": "^4.7.4" } } diff --git a/ElectronNET.Host/splashscreen/index.html b/ElectronNET.Host/splashscreen/index.html index ddd85e22..bafd72a4 100644 --- a/ElectronNET.Host/splashscreen/index.html +++ b/ElectronNET.Host/splashscreen/index.html @@ -10,9 +10,10 @@ splashscreen diff --git a/ElectronNET.Host/tsconfig.json b/ElectronNET.Host/tsconfig.json index ea3d493d..6454beb9 100644 --- a/ElectronNET.Host/tsconfig.json +++ b/ElectronNET.Host/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "module": "commonjs", - "target": "ES2019", + "target": "ES2020", "sourceMap": true, "skipLibCheck": true }, diff --git a/ElectronNET.WebApp/Controllers/AppSysInformationController.cs b/ElectronNET.WebApp/Controllers/AppSysInformationController.cs index f184e14c..b7a7bbc0 100644 --- a/ElectronNET.WebApp/Controllers/AppSysInformationController.cs +++ b/ElectronNET.WebApp/Controllers/AppSysInformationController.cs @@ -11,28 +11,34 @@ public IActionResult Index() { if(HybridSupport.IsElectronActive) { - Electron.IpcMain.On("app-info", async (args) => + Electron.IpcMain.OnWithId("app-info", async (info) => { string appPath = await Electron.App.GetAppPathAsync(); - var mainWindow = Electron.WindowManager.BrowserWindows.First(); - Electron.IpcMain.Send(mainWindow, "got-app-path", appPath); + if (Electron.WindowManager.TryGetBrowserWindows(info.browserId, out var window)) + { + Electron.IpcMain.Send(window, "got-app-path", appPath); + } }); - Electron.IpcMain.On("sys-info", async (args) => + Electron.IpcMain.OnWithId("sys-info", async (info) => { string homePath = await Electron.App.GetPathAsync(PathName.Home); - var mainWindow = Electron.WindowManager.BrowserWindows.First(); - Electron.IpcMain.Send(mainWindow, "got-sys-info", homePath); + if (Electron.WindowManager.TryGetBrowserWindows(info.browserId, out var window)) + { + Electron.IpcMain.Send(window, "got-sys-info", homePath); + } }); - Electron.IpcMain.On("screen-info", async (args) => + Electron.IpcMain.OnWithId("screen-info", async (info) => { var display = await Electron.Screen.GetPrimaryDisplayAsync(); - var mainWindow = Electron.WindowManager.BrowserWindows.First(); - Electron.IpcMain.Send(mainWindow, "got-screen-info", display.Size); + if (Electron.WindowManager.TryGetBrowserWindows(info.browserId, out var window)) + { + Electron.IpcMain.Send(window, "got-screen-info", display.Size); + } }); } diff --git a/ElectronNET.WebApp/Controllers/MenusController.cs b/ElectronNET.WebApp/Controllers/MenusController.cs index a279774e..5bb39b08 100644 --- a/ElectronNET.WebApp/Controllers/MenusController.cs +++ b/ElectronNET.WebApp/Controllers/MenusController.cs @@ -70,9 +70,11 @@ public IActionResult Index() { Label = "App Menu Demo", Click = async () => { - var options = new MessageBoxOptions("This demo is for the Menu section, showing how to create a clickable menu item in the application menu."); - options.Type = MessageBoxType.info; - options.Title = "Application Menu Demo"; + var options = new MessageBoxOptions("This demo is for the Menu section, showing how to create a clickable menu item in the application menu.") + { + Type = MessageBoxType.info, + Title = "Application Menu Demo" + }; await Electron.Dialog.ShowMessageBoxAsync(options); } } diff --git a/ElectronNET.WebApp/ElectronNET.WebApp.csproj b/ElectronNET.WebApp/ElectronNET.WebApp.csproj index e9fe1c20..add73e84 100644 --- a/ElectronNET.WebApp/ElectronNET.WebApp.csproj +++ b/ElectronNET.WebApp/ElectronNET.WebApp.csproj @@ -1,6 +1,6 @@  - net5.0 + net6.0 win-x64 4.2 diff --git a/ElectronNET.WebApp/Program.cs b/ElectronNET.WebApp/Program.cs index 54512d2c..77ced2fa 100644 --- a/ElectronNET.WebApp/Program.cs +++ b/ElectronNET.WebApp/Program.cs @@ -2,23 +2,49 @@ using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Logging; +using System; using System.Diagnostics; +using System.IO; +using Microsoft.Extensions.DependencyInjection; +using System.Threading.Tasks; namespace ElectronNET.WebApp { public class Program { - public static void Main(string[] args) + public static async Task Main(string[] args) { - //Debugger.Launch(); - CreateWebHostBuilder(args).Build().Run(); + IWebHostBuilder builder; + +#if DEBUG + var webPort = Electron.Experimental.FreeTcpPort(); + + await Electron.Experimental.StartElectronForDevelopment(webPort); + + builder = CreateWebHostBuilder(args); + // check for the content folder if its exists in base director otherwise no need to include + // It was used before because we are publishing the project which copies everything to bin folder and contentroot wwwroot was folder there. + // now we have implemented the live reload if app is run using /watch then we need to use the default project path. + if (Directory.Exists($"{AppDomain.CurrentDomain.BaseDirectory}\\wwwroot")) + { + builder.UseContentRoot(AppDomain.CurrentDomain.BaseDirectory); + } + + builder.UseUrls("http://localhost:" + webPort); +#else + builder = CreateWebHostBuilder(args); + Debugger.Launch(); + Electron.ReadAuth(); + builder.UseElectron(args); +#endif + + await builder.Build().RunAsync(); } public static IWebHostBuilder CreateWebHostBuilder(string[] args) { return WebHost.CreateDefaultBuilder(args) .ConfigureLogging((hostingContext, logging) => { logging.AddConsole(); }) - .UseElectron(args) .UseStartup(); } } diff --git a/ElectronNET.WebApp/Properties/launchSettings.json b/ElectronNET.WebApp/Properties/launchSettings.json index 32efbcd1..ae9cd85d 100644 --- a/ElectronNET.WebApp/Properties/launchSettings.json +++ b/ElectronNET.WebApp/Properties/launchSettings.json @@ -1,32 +1,35 @@ { - "iisSettings": { - "windowsAuthentication": false, - "anonymousAuthentication": true, - "iisExpress": { - "applicationUrl": "http://localhost:50394/", - "sslPort": 0 - } - }, "profiles": { - "Electron.NET App": { + "WSL": { + "commandName": "WSL2", + "launchUrl": "http://localhost:50395/", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_URLS": "http://localhost:50395/" + }, + "distributionName": "" + }, + "run with electronize": { "commandName": "Executable", - "executablePath": "$(SolutionDir)ElectronNET.CLI\\bin\\Debug\\net5.0\\dotnet-electronize-h5.exe", - "commandLineArgs": "start /from-build-output $(SolutionDir)ElectronNET.WebApp\\bin\\$(Configuration)\\net5.0", + "executablePath": "$(SolutionDir)ElectronNET.CLI\\bin\\Debug\\net6.0\\dotnet-electronize-h5.exe", + "commandLineArgs": "start /from-build-output $(SolutionDir)ElectronNET.WebApp\\bin\\$(Configuration)\\net6.0", "workingDirectory": "$(SolutionDir)ElectronNET.WebApp" }, - "IIS Express": { - "commandName": "IISExpress", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, - "ElectronNET.WebApp": { + "run from csharp": { "commandName": "Project", - "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" }, - "applicationUrl": "http://localhost:50395/" + "applicationUrl": "http://localhost:50395/", + "hotReloadEnabled": false + } + }, + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:50394/", + "sslPort": 0 } } } \ No newline at end of file diff --git a/ElectronNET.WebApp/Startup.cs b/ElectronNET.WebApp/Startup.cs index f6c0c338..34a10050 100644 --- a/ElectronNET.WebApp/Startup.cs +++ b/ElectronNET.WebApp/Startup.cs @@ -5,6 +5,7 @@ using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using System.Threading.Tasks; namespace ElectronNET.WebApp { @@ -43,11 +44,11 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env) if (HybridSupport.IsElectronActive) { - ElectronBootstrap(); + Task.Run(() => ElectronBootstrap()); } } - public async void ElectronBootstrap() + public async Task ElectronBootstrap() { //AddDevelopmentTests(); diff --git a/ElectronNET.WebApp/Views/DesktopCapturer/Index.cshtml b/ElectronNET.WebApp/Views/DesktopCapturer/Index.cshtml index 5e22c04d..ca7941be 100644 --- a/ElectronNET.WebApp/Views/DesktopCapturer/Index.cshtml +++ b/ElectronNET.WebApp/Views/DesktopCapturer/Index.cshtml @@ -22,104 +22,46 @@ +

This demo uses the desktopCapturer module to gather screens in use and select the entire screen and take a snapshot of what is visible.

Clicking the demo button will take a screenshot of your current screen and open it in your default viewer.

Renderer Process (JavaScript)
-
const electron = require('electron');
-const desktopCapturer = electron.desktopCapturer;
-const electronScreen = electron.screen;
-const shell = electron.shell;
-
-const fs = require('fs');
-const os = require('os');
-const path = require('path');
-
-const screenshot = document.getElementById('screen-shot');
-const screenshotMsg = document.getElementById('screenshot-path');
-
-screenshot.addEventListener('click', function (event) {
-    screenshotMsg.textContent = 'Gathering screens...';
-    const thumbSize = determineScreenShotSize();
-    let options = { types: ['screen'], thumbnailSize: thumbSize }
-
-    desktopCapturer.getSources(options, function (error, sources) {
-        if (error) return console.log(error);
-
-        sources.forEach(function (source) {
-            if (source.name === 'Entire screen' || source.name === 'Screen 1') {
-                const screenshotPath = path.join(os.tmpdir(), 'screenshot.png');
-
-                fs.writeFile(screenshotPath, source.thumbnail.toPng(), function (error) {
-                if (error) return console.log(error);
-                shell.openExternal('file://' + screenshotPath);
-                const message = `Saved screenshot to: ${screenshotPath}`;
-                screenshotMsg.textContent = message;
-                });
+          

+                  const screenshot = document.getElementById('screen-shot');
+    screenshot.addEventListener('click', function (event) {
+        const { desktopCapturer } = require('electron')
+
+        desktopCapturer.getSources({ types: ['screen'], thumbnailSize: {
+            width: window.screen.width,
+            height: window.screen.height
+        }}).then(async sources => {
+            for (const source of sources) {
+                document.getElementById('screenshot-image').src = source.thumbnail.toDataURL();
+                return;
             }
-        })
-    })
-})
-
-function determineScreenShotSize () {
-    const screenSize = electronScreen.getPrimaryDisplay().workAreaSize;
-    const maxDimension = Math.max(screenSize.width, screenSize.height);
-    return {
-        width: maxDimension * window.devicePixelRatio,
-        height: maxDimension * window.devicePixelRatio
-    }
+        });
+    });
 }
+ diff --git a/ElectronNET.sln b/ElectronNET.sln index 08a1a850..ea9c6e95 100644 --- a/ElectronNET.sln +++ b/ElectronNET.sln @@ -1,6 +1,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31112.23 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ElectronNET.WebApp", "ElectronNET.WebApp\ElectronNET.WebApp.csproj", "{7C048379-401C-4345-B5E7-BE232DEA8157}" ProjectSection(ProjectDependencies) = postProject @@ -13,7 +13,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ElectronNET.CLI", "Electron EndProject Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "ElectronNET.Host", "ElectronNET.Host\", "{B33E9B82-B6B4-4DB0-B6EE-61CC34641518}" ProjectSection(WebsiteProperties) = preProject - TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0" + TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.8" Debug.AspNetCompiler.VirtualPath = "/localhost_56840" Debug.AspNetCompiler.PhysicalPath = "ElectronNET.Host\" Debug.AspNetCompiler.TargetPath = "PrecompiledWeb\localhost_56840\" @@ -44,6 +44,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution start.sh = start.sh EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Releaser", "Releaser\Releaser.csproj", "{8209F641-B8AA-413A-8523-25ACF1BAD55D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -66,6 +68,10 @@ Global {B33E9B82-B6B4-4DB0-B6EE-61CC34641518}.Debug|Any CPU.Build.0 = Debug|Any CPU {B33E9B82-B6B4-4DB0-B6EE-61CC34641518}.Release|Any CPU.ActiveCfg = Debug|Any CPU {B33E9B82-B6B4-4DB0-B6EE-61CC34641518}.Release|Any CPU.Build.0 = Debug|Any CPU + {8209F641-B8AA-413A-8523-25ACF1BAD55D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8209F641-B8AA-413A-8523-25ACF1BAD55D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8209F641-B8AA-413A-8523-25ACF1BAD55D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8209F641-B8AA-413A-8523-25ACF1BAD55D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/README.md b/README.md index e6e1533a..55cf1bdc 100644 --- a/README.md +++ b/README.md @@ -137,10 +137,11 @@ There are additional platforms available: ``` electronize build /target win electronize build /target osx +electronize build /target osx-arm64 electronize build /target linux ``` -Those three "default" targets will produce x64 packages for those platforms. +Those four "default" targets will produce packages for those platforms. Note that the `osx-arm64` is for Apple Silicon Macs. For certain NuGet packages or certain scenarios you may want to build a pure x86 application. To support those things you can define the desired [.NET Core runtime](https://docs.microsoft.com/en-us/dotnet/core/rid-catalog), the [electron platform](https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#platform) and [electron architecture](https://github.com/electron-userland/electron-packager/blob/master/docs/api.md#arch) like this: diff --git a/Releaser/Program.cs b/Releaser/Program.cs new file mode 100644 index 00000000..79085b82 --- /dev/null +++ b/Releaser/Program.cs @@ -0,0 +1,69 @@ +using System.Diagnostics; +using System.Text.RegularExpressions; + +var version = args[0]; + +if (!Version.TryParse(version, out _)) +{ + Console.WriteLine($"Invalid version, expected x.x.x: {version}"); + return 0xDEAD; +} + +using var client = new HttpClient(); + +var response = await client.GetAsync($"https://github.com/electron/electron/releases/tag/v{version}"); +if (!response.IsSuccessStatusCode) +{ + Console.WriteLine($"Version not found on GitHub : {version}"); + return 0xDEAD; +} + + +var yamlFile = Path.GetFullPath("../.devops/build-nuget.yaml"); +var csFile = Path.GetFullPath("../ElectronNET.CLI/Commands/BuildCommand.cs"); +var packageFile = Path.GetFullPath("../ElectronNET.Host/package.json"); +var packagePath = Path.GetFullPath("../ElectronNET.Host"); + +if(!File.Exists(yamlFile) || !File.Exists(csFile) || !(File.Exists(packageFile))) +{ + Console.WriteLine($"One of these files was not found:\n{yamlFile}\n{csFile}\n{packageFile}"); + return 0xDEAD; +} + +var reYaml = new Regex(@"PackageVersion: \d{1,2}\.\d{1,2}\.\d{1,2}"); +var reCs = new Regex(@"_defaultElectronVersion = ""\d{1,2}\.\d{1,2}\.\d{1,2}"""); +var rePackage = new Regex(@"""electron"": ""\d{1,2}\.\d{1,2}\.\d{1,2}"""); + + +var yaml = File.ReadAllText(yamlFile); +var cs = File.ReadAllText(csFile); +var package = File.ReadAllText(packageFile); + +if(reYaml.IsMatch(yaml) && reCs.IsMatch(cs) && rePackage.IsMatch(package)) +{ + yaml = reYaml.Replace(yaml, $"PackageVersion: {version}"); + cs = reCs.Replace(cs, $"_defaultElectronVersion = \"{version}\""); + package = rePackage.Replace(package, $"\"electron\": \"{version}\""); + + File.WriteAllText(yamlFile, yaml); + File.WriteAllText(csFile, cs); + File.WriteAllText(packageFile, package); + + Directory.SetCurrentDirectory(packagePath); + + var psi = new ProcessStartInfo(); + psi.FileName = "cmd"; + psi.Arguments = "/c \"npm update -D\""; + + var npmProcess = Process.Start(psi); + + npmProcess.WaitForExit(); + + return 0; +} +else +{ + Console.WriteLine($"Regex didn't match, check source code"); + return 0xDEAD; +} + diff --git a/Releaser/Releaser.csproj b/Releaser/Releaser.csproj new file mode 100644 index 00000000..fb76edd0 --- /dev/null +++ b/Releaser/Releaser.csproj @@ -0,0 +1,9 @@ + + + + Exe + net6.0 + enable + + +