diff --git a/.devops/build-nuget.yaml b/.devops/build-nuget.yaml new file mode 100644 index 0000000..b559186 --- /dev/null +++ b/.devops/build-nuget.yaml @@ -0,0 +1,84 @@ +variables: + PackageVersion: 19.0.9.$(Build.BuildId) + projectAPI: './ElectronNET.API/ElectronNET.API.csproj' + projectCLI: './ElectronNET.CLI/ElectronNET.CLI.csproj' + +trigger: +- master + +pool: + vmImage: windows-latest + +steps: +- checkout: self + submodules: true + fetchDepth: 10 + +- task: NuGetToolInstaller@1 + +- task: UseDotNet@2 + displayName: 'Use .NET Core sdk' + inputs: + packageType: sdk + version: 6.0.100 + installationPath: $(Agent.ToolsDirectory)/dotnet + +- task: DotNetCoreCLI@2 + displayName: 'restore nuget' + inputs: + command: 'restore' + projects: '$(projectAPI)' + +- task: DotNetCoreCLI@2 + displayName: 'restore nuget' + inputs: + command: 'restore' + projects: '$(projectCLI)' + + +- task: DotNetCoreCLI@2 + inputs: + command: 'build' + projects: '$(projectAPI)' + arguments: '--configuration Release --force /property:Version=$(PackageVersion)' + +- task: DotNetCoreCLI@2 + inputs: + command: 'build' + projects: '$(projectCLI)' + arguments: '--configuration Release --force /property:Version=$(PackageVersion)' + +- task: DotNetCoreCLI@2 + inputs: + command: 'pack' + packagesToPack: '$(projectAPI)' + configuration: 'Release' + versioningScheme: 'off' + buildProperties: 'Version=$(PackageVersion)' + arguments: -IncludeReferencedProjects + +- task: DotNetCoreCLI@2 + inputs: + command: 'pack' + packagesToPack: '$(projectCLI)' + configuration: 'Release' + versioningScheme: 'off' + buildProperties: 'Version=$(PackageVersion)' + + + +- task: NuGetCommand@2 + displayName: 'push API to nuget' + inputs: + command: 'push' + packagesToPush: '$(Build.ArtifactStagingDirectory)/h5.ElectronNET.API.$(PackageVersion).nupkg' + nuGetFeedType: 'external' + publishFeedCredentials: 'nuget-curiosity' + +- task: NuGetCommand@2 + displayName: 'push CLI to nuget' + inputs: + command: 'push' + packagesToPush: '$(Build.ArtifactStagingDirectory)/h5.ElectronNET.CLI.$(PackageVersion).nupkg' + nuGetFeedType: 'external' + publishFeedCredentials: 'nuget-curiosity' \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 03e64bf..1a4851e 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,16 +1,21 @@ { - "version": "0.1.0", + "version": "2.0.0", "command": "dotnet", - "isShellCommand": true, "args": [], "tasks": [ { - "taskName": "build", + "label": "build", + "type": "shell", + "command": "dotnet", "args": [ + "build", "${workspaceRoot}/ElectronNET.CLI/ElectronNET.CLI.csproj" ], - "isBuildCommand": true, - "problemMatcher": "$msCompile" + "problemMatcher": "$msCompile", + "group": { + "_id": "build", + "isDefault": false + } } ] } \ No newline at end of file diff --git a/.vscode/tasks.json.old b/.vscode/tasks.json.old new file mode 100644 index 0000000..03e64bf --- /dev/null +++ b/.vscode/tasks.json.old @@ -0,0 +1,16 @@ +{ + "version": "0.1.0", + "command": "dotnet", + "isShellCommand": true, + "args": [], + "tasks": [ + { + "taskName": "build", + "args": [ + "${workspaceRoot}/ElectronNET.CLI/ElectronNET.CLI.csproj" + ], + "isBuildCommand": true, + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/ElectronNET.API/App.cs b/ElectronNET.API/App.cs index 0a41610..ab992df 100755 --- a/ElectronNET.API/App.cs +++ b/ElectronNET.API/App.cs @@ -8,7 +8,11 @@ using System.Threading; using System.Threading.Tasks; using ElectronNET.API.Extensions; using ElectronNET.API.Interfaces; +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 { /// @@ -21,6 +25,90 @@ namespace ElectronNET.API /// 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. /// @@ -338,6 +426,8 @@ namespace ElectronNET.API /// 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 @@ -412,6 +502,7 @@ namespace ElectronNET.API /// /// On Windows, you have to parse the arguments using App.CommandLine to get the filepath. /// + [SupportedOSPlatform("macos")] public event Action OpenFile { add @@ -440,8 +531,7 @@ namespace ElectronNET.API /// - /// 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 { @@ -493,12 +583,16 @@ namespace ElectronNET.API /// should usually also specify a productName field, which is your application's full capitalized name, and /// which will be preferred over name by Electron. /// - public Task GetNameAsync() => BridgeConnector.OnResult("appGetName", "appGetNameCompleted"); + 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 @@ -529,7 +623,7 @@ namespace ElectronNET.API } 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 @@ -600,6 +694,7 @@ namespace ElectronNET.API /// /// 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)); @@ -608,6 +703,7 @@ namespace ElectronNET.API /// /// Hides all application windows without minimizing them. /// + [SupportedOSPlatform("macos")] public void Hide() { BridgeConnector.Emit("appHide"); @@ -616,6 +712,7 @@ namespace ElectronNET.API /// /// Shows application windows after they were hidden. Does not automatically focus them. /// + [SupportedOSPlatform("macos")] public void Show() { BridgeConnector.Emit("appShow"); @@ -689,6 +786,8 @@ namespace ElectronNET.API /// 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); @@ -697,6 +796,8 @@ namespace ElectronNET.API /// /// Clears the recent documents list. /// + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public void ClearRecentDocuments() { BridgeConnector.Emit("appClearRecentDocuments"); @@ -727,6 +828,8 @@ namespace ElectronNET.API /// 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); @@ -758,6 +861,8 @@ namespace ElectronNET.API /// 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); @@ -790,6 +895,8 @@ namespace ElectronNET.API /// 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); /// @@ -799,6 +906,8 @@ namespace ElectronNET.API /// 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); @@ -812,6 +921,8 @@ namespace ElectronNET.API /// 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); @@ -826,6 +937,8 @@ namespace ElectronNET.API /// 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); @@ -842,6 +955,8 @@ namespace ElectronNET.API /// 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); @@ -861,6 +976,8 @@ namespace ElectronNET.API /// 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); @@ -881,6 +998,8 @@ namespace ElectronNET.API /// 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); @@ -892,6 +1011,7 @@ namespace ElectronNET.API /// 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)); /// @@ -899,6 +1019,7 @@ namespace ElectronNET.API /// /// The cancellation token. /// Jump List settings. + [SupportedOSPlatform("windows")] public Task GetJumpListSettingsAsync(CancellationToken cancellationToken = default) => BridgeConnector.OnResult("appGetJumpListSettings", "appGetJumpListSettingsCompleted", cancellationToken); /// @@ -917,6 +1038,7 @@ namespace ElectronNET.API /// 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)); @@ -992,6 +1114,7 @@ namespace ElectronNET.API /// /// 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); @@ -1009,6 +1132,7 @@ namespace ElectronNET.API /// /// 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); @@ -1018,12 +1142,14 @@ namespace ElectronNET.API /// 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"); @@ -1032,6 +1158,7 @@ namespace ElectronNET.API /// /// Marks the current Handoff user activity as inactive without invalidating it. /// + [SupportedOSPlatform("macos")] public void ResignCurrentActivity() { BridgeConnector.Emit("appResignCurrentActivity"); @@ -1041,6 +1168,7 @@ namespace ElectronNET.API /// Changes the Application User Model ID to id. /// /// Model Id. + [SupportedOSPlatform("windows")] public void SetAppUserModelId(string id) { BridgeConnector.Emit("appSetAppUserModelId", id); @@ -1055,6 +1183,7 @@ namespace ElectronNET.API /// /// 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)); /// @@ -1085,12 +1214,16 @@ namespace ElectronNET.API /// 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); /// @@ -1102,12 +1235,15 @@ namespace ElectronNET.API /// 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); @@ -1119,6 +1255,8 @@ namespace ElectronNET.API /// /// /// 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)); @@ -1129,6 +1267,8 @@ namespace ElectronNET.API /// 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)); @@ -1140,6 +1280,8 @@ namespace ElectronNET.API /// 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); @@ -1153,6 +1295,8 @@ namespace ElectronNET.API /// 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); @@ -1183,6 +1327,13 @@ namespace ElectronNET.API 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. /// @@ -1207,7 +1358,7 @@ namespace ElectronNET.API /// custom value as early as possible in your app's initialization to ensure that your overridden value /// is used. /// - public Task GetUserAgentFallbackAsync() => BridgeConnector.OnResult("appGetUserAgentFallback", "appGetUserAgentFallbackCompleted"); + public Task GetUserAgentFallbackAsync => BridgeConnector.OnResult("appGetUserAgentFallback", "appGetUserAgentFallbackCompleted"); internal void PreventQuit() { @@ -1245,7 +1396,14 @@ namespace ElectronNET.API /// 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/ApplicationSocket.cs b/ElectronNET.API/ApplicationSocket.cs deleted file mode 100755 index 7480b80..0000000 --- a/ElectronNET.API/ApplicationSocket.cs +++ /dev/null @@ -1,16 +0,0 @@ -using ElectronNET.API.Interfaces; -using Quobject.SocketIoClientDotNet.Client; - -namespace ElectronNET.API -{ - /// - /// Wrapper for the underlying Socket connection - /// - public class ApplicationSocket : IApplicationSocket - { - /// - /// Socket used to communicate with main.js - /// - public Socket Socket { get; internal set; } - } -} diff --git a/ElectronNET.API/AutoUpdater.cs b/ElectronNET.API/AutoUpdater.cs index c4df3d0..a0fa2a6 100755 --- a/ElectronNET.API/AutoUpdater.cs +++ b/ElectronNET.API/AutoUpdater.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using ElectronNET.API.Interfaces; +using ElectronNET.API; namespace ElectronNET.API { @@ -17,14 +18,14 @@ namespace ElectronNET.API /// /// Whether to automatically download an update when it is found. (Default is true) /// - public Task IsAutoDownloadEnabledAsync() => BridgeConnector.OnResult("autoUpdater-autoDownload-get", "autoUpdater-autoDownload-get-reply"); + public Task IsAutoDownloadEnabledAsync => BridgeConnector.OnResult("autoUpdater-autoDownload-get", "autoUpdater-autoDownload-get-reply"); /// /// Whether to automatically install a downloaded update on app quit (if `QuitAndInstall` was not called before). /// /// Applicable only on Windows and Linux. /// - public Task IsAutoInstallOnAppQuitEnabledAsync() => BridgeConnector.OnResult("autoUpdater-autoInstallOnAppQuit-get", "autoUpdater-autoInstallOnAppQuit-get-reply"); + public Task IsAutoInstallOnAppQuitEnabledAsync => BridgeConnector.OnResult("autoUpdater-autoInstallOnAppQuit-get", "autoUpdater-autoInstallOnAppQuit-get-reply"); /// /// *GitHub provider only.* Whether to allow update to pre-release versions. @@ -32,17 +33,16 @@ namespace ElectronNET.API /// /// If "true", downgrade will be allowed("allowDowngrade" will be set to "true"). /// - public Task IsAllowPrereleaseEnabledAsync() => BridgeConnector.OnResult("autoUpdater-allowPrerelease-get", "autoUpdater-allowPrerelease-get-reply"); + public Task IsAllowPrereleaseEnabledAsync => BridgeConnector.OnResult("autoUpdater-allowPrerelease-get", "autoUpdater-allowPrerelease-get-reply"); /// /// *GitHub provider only.* /// Get all release notes (from current version to latest), not just the latest (Default is false). /// - public Task IsFullChangeLogEnabledAsync() => BridgeConnector.OnResult("autoUpdater-fullChangelog-get", "autoUpdater-fullChangelog-get-reply"); + public Task IsFullChangeLogEnabledAsync => BridgeConnector.OnResult("autoUpdater-fullChangelog-get", "autoUpdater-fullChangelog-get-reply"); - public Task IsAllowDowngradeEnabledAsync() => BridgeConnector.OnResult("autoUpdater-allowDowngrade-get", "autoUpdater-allowDowngrade-get-reply"); + public Task IsAllowDowngradeEnabledAsync => BridgeConnector.OnResult("autoUpdater-allowDowngrade-get", "autoUpdater-allowDowngrade-get-reply"); - /// /// Whether to automatically download an update when it is found. (Default is true) /// @@ -109,23 +109,23 @@ namespace ElectronNET.API /// /// For test only. /// - public Task GetUpdateConfigPathAsync() => BridgeConnector.OnResult("autoUpdater-updateConfigPath-get", "autoUpdater-updateConfigPath-get-reply"); + public Task GetUpdateConfigPathAsync => BridgeConnector.OnResult("autoUpdater-updateConfigPath-get", "autoUpdater-updateConfigPath-get-reply"); /// /// The current application version /// - public Task GetCurrentVersionAsync() => BridgeConnector.OnResult("autoUpdater-updateConcurrentVersionfigPath-get", "autoUpdater-currentVersion-get-reply"); + public Task GetCurrentVersionAsync => BridgeConnector.OnResult("autoUpdater-updateConcurrentVersionfigPath-get", "autoUpdater-currentVersion-get-reply"); /// /// Get the update channel. Not applicable for GitHub. /// Doesn’t return channel from the update configuration, only if was previously set. /// - public Task GetChannelAsync() => BridgeConnector.OnResult("autoUpdater-channel-get", "autoUpdater-channel-get-reply"); + public Task GetChannelAsync => BridgeConnector.OnResult("autoUpdater-channel-get", "autoUpdater-channel-get-reply"); /// /// The request headers. /// - public Task> GetRequestHeadersAsync() => BridgeConnector.OnResult>("autoUpdater-requestHeaders-get", "autoUpdater-requestHeaders-get-reply"); + public Task> GetRequestHeadersAsync => BridgeConnector.OnResult>("autoUpdater-requestHeaders-get", "autoUpdater-requestHeaders-get-reply"); /// /// The request headers. @@ -314,7 +314,7 @@ namespace ElectronNET.API private event Action _updateDownloaded; private static AutoUpdater _autoUpdater; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal AutoUpdater() { } @@ -427,6 +427,7 @@ namespace ElectronNET.API /// 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 95c9e0d..b274e8b 100644 --- a/ElectronNET.API/BridgeConnector.cs +++ b/ElectronNET.API/BridgeConnector.cs @@ -1,14 +1,12 @@ using System; -using System.Collections.Concurrent; using System.Collections.Generic; -using System.Linq; using System.Threading; using System.Threading.Tasks; +using Microsoft.Extensions.Logging; using Newtonsoft.Json; -using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; +using Nito.AsyncEx; using SocketIOClient; -using SocketIOClient.JsonSerializer; using SocketIOClient.Newtonsoft.Json; namespace ElectronNET.API @@ -46,7 +44,7 @@ namespace ElectronNET.API return true; //Was added, so we need to also register the socket events } - if(_eventKeys.TryGetValue(key, out var existingEventKey) && existingEventKey == eventKey) + if (_eventKeys.TryGetValue(key, out var existingEventKey) && existingEventKey == eventKey) { waitThisFirstAndThenTryAgain = null; return false; //No need to register the socket events twice @@ -86,26 +84,63 @@ namespace ElectronNET.API 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(async () => + Task.Run(() => EmitAsync(eventString, args)); + } + + 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}"); + } } /// @@ -117,30 +152,128 @@ namespace ElectronNET.API { 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) @@ -160,7 +293,7 @@ namespace ElectronNET.API // this allow us to wait for previous events first before registering new ones { var hash = new HashCode(); - foreach(var obj in args) + foreach (var obj in args) { hash.Add(obj); } @@ -196,7 +329,7 @@ namespace ElectronNET.API EventTasks.DoneWith(completedEvent, eventKey, taskCompletionSource); }); - Emit(triggerEvent, args); + await EmitAsync(triggerEvent, args); } } @@ -257,166 +390,162 @@ namespace ElectronNET.API return await taskCompletionSource.Task; } - private static SocketIO Socket - { - get - { - if (_socket is null) - { - if (HybridSupport.IsElectronActive) - { - lock (_syncRoot) + internal static void Log(string formatString, params object[] args) + { + if (Logger is object) + { + 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)) + { + throw new Exception("You must call Electron.ReadAuth() first thing on your main entry point."); + } + + 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.ConnectAsync().Wait(); + 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.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 CamelCaseNewtonsoftJsonSerializer() : base() { - } - - public override JsonSerializerSettings CreateOptions() - { - return new JsonSerializerSettings() + OptionsProvider = () => new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver(), NullValueHandling = NullValueHandling.Ignore, - DefaultValueHandling = DefaultValueHandling.Ignore }; } } - public static async Task GetValueOverSocketAsync(string eventString, string eventCompletedString) - { - CancellationToken cancellationToken = new(); - cancellationToken.ThrowIfCancellationRequested(); - - var taskCompletionSource = new TaskCompletionSource(); - using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled())) - { - BridgeConnector.Socket.On(eventCompletedString, (value) => - { - BridgeConnector.Socket.Off(eventCompletedString); - - if (value == null) - { - Console.WriteLine($"ERROR: BridgeConnector (event: '{eventString}') returned null. Socket loop hang."); - taskCompletionSource.SetCanceled(); - return; - } - - try - { - taskCompletionSource.SetResult( new JValue(value).ToObject() ); - } - catch (Exception e) - { - Console.WriteLine($"ERROR: BridgeConnector (event: '{eventString}') exception: {e.Message}. Socket loop hung."); - } - }); - - await BridgeConnector.Socket.EmitAsync(eventString); - - return await taskCompletionSource.Task.ConfigureAwait(false); - } - } - - public static async Task GetObjectOverSocketAsync(string eventString, string eventCompletedString) - { - CancellationToken cancellationToken = new(); - cancellationToken.ThrowIfCancellationRequested(); - - var taskCompletionSource = new TaskCompletionSource(); - using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled())) - { - BridgeConnector.Socket.On(eventCompletedString, (value) => - { - BridgeConnector.Socket.Off(eventCompletedString); - - if (value == null) - { - Console.WriteLine($"ERROR: BridgeConnector (event: '{eventString}') returned null. Socket loop hang."); - taskCompletionSource.SetCanceled(); - return; - } - - try - { - taskCompletionSource.SetResult( ((JObject)value).ToObject() ); - } - catch (Exception e) - { - Console.WriteLine($"ERROR: BridgeConnector (event: '{eventString}') exception: {e.Message}. Socket loop hung."); - } - }); - - await BridgeConnector.Socket.EmitAsync(eventString); - - return await taskCompletionSource.Task.ConfigureAwait(false); - } - } - - public static async Task GetArrayOverSocketAsync(string eventString, string eventCompletedString) - { - CancellationToken cancellationToken = new(); - cancellationToken.ThrowIfCancellationRequested(); - - var taskCompletionSource = new TaskCompletionSource(); - using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled())) - { - BridgeConnector.Socket.On(eventCompletedString, (value) => - { - BridgeConnector.Socket.Off(eventCompletedString); - if (value == null) - { - Console.WriteLine($"ERROR: BridgeConnector (event: '{eventString}') returned null. Socket loop hang."); - taskCompletionSource.SetCanceled(); - return; - } - - try - { - taskCompletionSource.SetResult(((JArray)value).ToObject() ); - } - catch (Exception e) - { - Console.WriteLine($"ERROR: BridgeConnector (event: '{eventString}') exception: {e.Message}. Socket loop hung."); - } - }); - - await BridgeConnector.Socket.EmitAsync(eventString); - - return await taskCompletionSource.Task.ConfigureAwait(false); - } - } } -} +} \ No newline at end of file diff --git a/ElectronNET.API/BrowserView.cs b/ElectronNET.API/BrowserView.cs index 09a44cb..cd29dfe 100644 --- a/ElectronNET.API/BrowserView.cs +++ b/ElectronNET.API/BrowserView.cs @@ -33,6 +33,10 @@ namespace ElectronNET.API /// 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 0b8222c..a39e26b 100644 --- a/ElectronNET.API/BrowserWindow.cs +++ b/ElectronNET.API/BrowserWindow.cs @@ -7,8 +7,11 @@ using System; 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 @@ namespace ElectronNET.API /// /// 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 @@ namespace ElectronNET.API /// /// Emitted when the window is being resized. /// + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public event Action OnResize { add @@ -496,6 +502,8 @@ namespace ElectronNET.API /// /// Note: On macOS this event is just an alias of moved. /// + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public event Action OnMove { add @@ -523,8 +531,10 @@ namespace ElectronNET.API 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// /// Emitted when scroll wheel event phase has begun. /// + [SupportedOSPlatform("macos")] public event Action OnScrollTouchBegin { add @@ -734,6 +747,7 @@ namespace ElectronNET.API /// /// Emitted when scroll wheel event phase has ended. /// + [SupportedOSPlatform("macos")] public event Action OnScrollTouchEnd { add @@ -763,6 +777,7 @@ namespace ElectronNET.API /// /// Emitted when scroll wheel event phase filed upon reaching the edge of element. /// + [SupportedOSPlatform("macos")] public event Action OnScrollTouchEdge { add @@ -792,6 +807,7 @@ namespace ElectronNET.API /// /// Emitted on 3-finger swipe. Possible directions are up, right, down, left. /// + [SupportedOSPlatform("macos")] public event Action OnSwipe { add @@ -821,6 +837,7 @@ namespace ElectronNET.API /// /// Emitted when the window opens a sheet. /// + [SupportedOSPlatform("macos")] public event Action OnSheetBegin { add @@ -850,6 +867,7 @@ namespace ElectronNET.API /// /// Emitted when the window has closed a sheet. /// + [SupportedOSPlatform("macos")] public event Action OnSheetEnd { add @@ -879,6 +897,7 @@ namespace ElectronNET.API /// /// Emitted when the native new tab button is clicked. /// + [SupportedOSPlatform("macos")] public event Action OnNewWindowForTab { add @@ -1056,6 +1075,14 @@ namespace ElectronNET.API { 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 @@ namespace ElectronNET.API 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 @@ namespace ElectronNET.API /// /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// /// Closes the currently open Quick Look panel. /// + [SupportedOSPlatform("macos")] public void CloseFilePreview() { BridgeConnector.Emit("browserWindowCloseFilePreview", Id); @@ -1131,6 +1183,7 @@ namespace ElectronNET.API /// /// /// + [SupportedOSPlatform("macos")] public void SetBounds(Rectangle bounds, bool animate) { BridgeConnector.Emit("browserWindowSetBounds", Id, bounds, animate); @@ -1159,6 +1212,7 @@ namespace ElectronNET.API /// /// /// + [SupportedOSPlatform("macos")] public void SetContentBounds(Rectangle bounds, bool animate) { BridgeConnector.Emit("browserWindowSetContentBounds", Id, bounds, animate); @@ -1189,6 +1243,7 @@ namespace ElectronNET.API /// /// /// + [SupportedOSPlatform("macos")] public void SetSize(int width, int height, bool animate) { BridgeConnector.Emit("browserWindowSetSize", Id, width, height, animate); @@ -1219,6 +1274,7 @@ namespace ElectronNET.API /// /// /// + [SupportedOSPlatform("macos")] public void SetContentSize(int width, int height, bool animate) { BridgeConnector.Emit("browserWindowSetContentSize", Id, width, height, animate); @@ -1293,6 +1349,8 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API // https://github.com/electron/electron/issues/4045 if (isWindows10()) { - x = x - 7; + x -= 7; } BridgeConnector.Emit("browserWindowSetPosition", Id, x, y); @@ -1468,13 +1535,14 @@ namespace ElectronNET.API /// /// /// + [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 @@ namespace ElectronNET.API private bool isWindows10() { - return RuntimeInformation.OSDescription.Contains("Windows 10"); + return OperatingSystem.IsWindowsVersionAtLeast(10); } /// @@ -1520,6 +1588,7 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// /// /// + [SupportedOSPlatform("macos")] public void SetSheetOffset(float offsetY, float offsetX) { BridgeConnector.Emit("browserWindowSetSheetOffset", Id, offsetY, offsetX); @@ -1587,6 +1657,7 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// /// Remove the window's menu bar. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("linux")] public void RemoveMenu() { BridgeConnector.Emit("browserWindowRemoveMenu", Id); @@ -1729,6 +1807,7 @@ namespace ElectronNET.API /// /// /// + [SupportedOSPlatform("windows")] public void SetProgressBar(double progress, ProgressBarOptions progressBarOptions) { BridgeConnector.Emit("browserWindowSetProgressBar", Id, progress, progressBarOptions); @@ -1738,6 +1817,8 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// /// /// Whether the buttons were added successfully. + [SupportedOSPlatform("windows")] public Task SetThumbarButtonsAsync(ThumbarButton[] thumbarButtons) { var taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); @@ -1808,6 +1890,7 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API /// Controls whether to hide cursor when typing. /// /// + [SupportedOSPlatform("macos")] public void SetAutoHideCursor(bool autoHide) { BridgeConnector.Emit("browserWindowSetAutoHideCursor", Id, autoHide); @@ -1983,11 +2091,25 @@ namespace ElectronNET.API /// 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 @@ namespace ElectronNET.API 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 a3c6d75..9d8ba50 100755 --- 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; using ElectronNET.API.Interfaces; @@ -13,7 +14,7 @@ namespace ElectronNET.API public sealed class Clipboard : IClipboard { private static Clipboard _clipboard; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Clipboard() { } @@ -94,6 +95,8 @@ namespace ElectronNET.API /// be empty strings when the bookmark is unavailable. /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public Task ReadBookmarkAsync() => BridgeConnector.OnResult("clipboard-readBookmark", "clipboard-readBookmark-Completed"); /// @@ -106,6 +109,8 @@ namespace ElectronNET.API /// /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public void WriteBookmark(string title, string url, string type = "") { BridgeConnector.Emit("clipboard-writeBookmark", title, url, type); @@ -117,6 +122,7 @@ namespace ElectronNET.API /// find pasteboard whenever the application is activated. /// /// + [SupportedOSPlatform("macos")] public Task ReadFindTextAsync() => BridgeConnector.OnResult("clipboard-readFindText", "clipboard-readFindText-Completed"); /// @@ -124,6 +130,7 @@ namespace ElectronNET.API /// synchronous IPC when called from the renderer process. /// /// + [SupportedOSPlatform("macos")] public void WriteFindText(string text) { BridgeConnector.Emit("clipboard-writeFindText", text); @@ -152,7 +159,7 @@ namespace ElectronNET.API /// public void Write(Data data, string type = "") { - BridgeConnector.Emit("clipboard-write", data, type); + BridgeConnector.Emit("clipboard-write", JObject.FromObject(data, _jsonSerializer), type); } /// @@ -171,5 +178,12 @@ namespace ElectronNET.API { 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 26a116c..6aa1e50 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 @@ namespace ElectronNET.API 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 67f16b0..f5de870 100644 --- a/ElectronNET.API/Cookies.cs +++ b/ElectronNET.API/Cookies.cs @@ -71,7 +71,7 @@ namespace ElectronNET.API 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 @@ namespace ElectronNET.API 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 @@ namespace ElectronNET.API 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 0000000..358b513 --- /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 fce2db0..0b48c11 100755 --- a/ElectronNET.API/Dialog.cs +++ b/ElectronNET.API/Dialog.cs @@ -4,6 +4,7 @@ using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using System; using System.Collections.Generic; +using System.Runtime.Versioning; using System.Threading.Tasks; using System.Web; using ElectronNET.API.Interfaces; @@ -16,7 +17,7 @@ namespace ElectronNET.API public sealed class Dialog : IDialog { private static Dialog _dialog; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Dialog() { } @@ -159,12 +160,12 @@ namespace ElectronNET.API }); - 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; @@ -192,6 +193,8 @@ namespace ElectronNET.API /// /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public Task ShowCertificateTrustDialogAsync(CertificateTrustDialogOptions options) { return ShowCertificateTrustDialogAsync(null, options); @@ -205,6 +208,8 @@ namespace ElectronNET.API /// /// /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public Task ShowCertificateTrustDialogAsync(BrowserWindow browserWindow, CertificateTrustDialogOptions options) { var taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); @@ -220,5 +225,12 @@ namespace ElectronNET.API 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 9133829..8c1f08d 100755 --- 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; @@ -13,10 +14,11 @@ namespace ElectronNET.API /// /// Control your app in the macOS dock. /// + [SupportedOSPlatform("macos")] public sealed class Dock : IDock { private static Dock _dock; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Dock() { @@ -131,7 +133,7 @@ namespace ElectronNET.API /// 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. @@ -164,7 +166,7 @@ namespace ElectronNET.API 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 0000000..75d110e --- /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 5c63616..34faf33 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 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,11 +133,7 @@ /// /// Control your app in the macOS dock. /// + [SupportedOSPlatform("macos")] public static Dock Dock { get { return Dock.Instance; } } - - /// - /// Electeon extensions to the Nodejs process object. - /// - public static Process Process { get { return Process.Instance; } } } } \ No newline at end of file diff --git a/ElectronNET.API/ElectronNET.API.csproj b/ElectronNET.API/ElectronNET.API.csproj index e3a6b03..b253c4c 100755 --- a/ElectronNET.API/ElectronNET.API.csproj +++ b/ElectronNET.API/ElectronNET.API.csproj @@ -1,6 +1,7 @@  + net6.0 true ..\artifacts ElectronNET.API @@ -38,13 +39,16 @@ + all runtime; build; native; contentfiles; analyzers - - + + + + diff --git a/ElectronNET.API/Entities/BrowserWindowOptions.cs b/ElectronNET.API/Entities/BrowserWindowOptions.cs index 61021bb..00f209b 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 @@ namespace ElectronNET.API.Entities /// 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 @@ namespace ElectronNET.API.Entities /// 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 @@ namespace ElectronNET.API.Entities /// 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 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 @@ namespace ElectronNET.API.Entities /// 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 @@ namespace ElectronNET.API.Entities /// '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 @@ namespace ElectronNET.API.Entities /// 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 @@ namespace ElectronNET.API.Entities /// 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 @@ namespace ElectronNET.API.Entities /// 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+. @@ -276,5 +285,13 @@ namespace ElectronNET.API.Entities /// [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 2dcca89..893c55c 100644 --- a/ElectronNET.API/Entities/Data.cs +++ b/ElectronNET.API/Entities/Data.cs @@ -34,5 +34,7 @@ /// 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 0000000..c08dbb9 --- /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 4d44f32..4d8cceb 100644 --- a/ElectronNET.API/Entities/Display.cs +++ b/ElectronNET.API/Entities/Display.cs @@ -26,12 +26,12 @@ /// /// 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 150d0b7..dbd657a 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 @@ /// 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 e4095b7..b592a47 100644 --- a/ElectronNET.API/Entities/NativeImage.cs +++ b/ElectronNET.API/Entities/NativeImage.cs @@ -1,5 +1,8 @@ using System; using System.Collections.Generic; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.Processing; using System.IO; using System.Linq; using System.Text.RegularExpressions; @@ -20,11 +23,11 @@ namespace ElectronNET.API.Entities /// /// public const float DefaultScaleFactor = 1.0f; - private readonly Dictionary _images = new Dictionary(); + 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}, @@ -41,8 +44,7 @@ namespace ElectronNET.API.Entities } private static Image BytesToImage(byte[] bytes) { - var ms = new MemoryStream(bytes); - return Image.Load(ms); + return Image.Load(new MemoryStream(bytes)); } /// @@ -56,11 +58,14 @@ namespace ElectronNET.API.Entities /// /// /// - [Obsolete("System.Drawing.Common is no longer supported. Use NativeImage.CreateFromImage(image, options);", true)] - public static NativeImage CreateFromBitmap(object bitmap, CreateOptions options = null) + public static NativeImage CreateFromImage(Image image, CreateFromBitmapOptions options = null) { - throw new NotImplementedException( - "System.Drawing.Common is no longer supported. Use NativeImage.CreateFromImage(image, options);"); + if (options is null) + { + options = new CreateFromBitmapOptions(); + } + + return new NativeImage(image, options.ScaleFactor); } /// @@ -74,8 +79,12 @@ namespace ElectronNET.API.Entities /// public static NativeImage CreateFromBuffer(byte[] buffer, CreateOptions options = null) { - var ms = new MemoryStream(buffer); - var image = Image.Load(ms); + if (options is null) + { + options = new CreateFromBufferOptions(); + } + + var image = Image.Load(new MemoryStream(buffer)); return new NativeImage(image, options?.ScaleFactor ?? DefaultScaleFactor); } @@ -167,7 +176,7 @@ namespace ElectronNET.API.Entities /// 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)); @@ -217,7 +226,7 @@ namespace ElectronNET.API.Entities var image = GetScale(scaleFactor); if (image != null) { - return Convert.ToSingle(image.Width) / image.Height; + return (float)image.Width / image.Height; } return 0f; @@ -226,9 +235,9 @@ namespace ElectronNET.API.Entities /// /// Returns a byte array that contains the image's raw bitmap pixel data. /// - public byte[] GetBitmap(ImageOptions options) + public byte[] GetBitmap(float scaleFactor) { - return ToBitmap(options); + return ToBitmap(scaleFactor).ToArray(); } /// @@ -236,7 +245,7 @@ namespace ElectronNET.API.Entities /// public byte[] GetNativeHandle() { - return ToBitmap(new ImageOptions()); + return ToBitmap().ToArray(); } /// @@ -269,75 +278,86 @@ namespace ElectronNET.API.Entities /// /// Outputs a bitmap based on the scale factor /// - public byte[] ToBitmap(ImageOptions options) + public MemoryStream ToBitmap(float scaleFactor = 1.0f) { var ms = new MemoryStream(); - _images[options.ScaleFactor].SaveAsBmp(ms); - return ms.ToArray(); + _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(ImageOptions options) => _images.TryGetValue(options.ScaleFactor, out var image) ? $"data:image/png;base64,{image.ToBase64String(PngFormat.Instance)}" : null; - /// - /// Outputs a JPEG for the default scale factor - /// - public byte[] ToJPEG(int quality) + public MemoryStream ToPng(float scaleFactor = 1.0f) { var ms = new MemoryStream(); - _images[1.0f].SaveAsJpeg(ms); - return ms.ToArray(); + _images[scaleFactor].SaveAsPng(ms); + return ms; } /// - /// Outputs a PNG for the specified scale factor + /// Outputs a JPEG for the default scale factor /// - public byte[] ToPNG(ImageOptions options) + public MemoryStream ToJpeg(int quality, float scaleFactor = 1.0f) { - if (_images.TryGetValue(options.ScaleFactor, out var image)) - { - var ms = new MemoryStream(); - image.SaveAsPng(ms); - return ms.ToArray(); - } - return null; + var ms = new MemoryStream(); + _images[scaleFactor].SaveAsJpeg(ms, new SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder() { Quality = quality }); + return ms; } + /// + /// Outputs a data URL based on the scale factor + /// + public string ToDataURL(float scaleFactor = 1.0f) + { + if (!_images.TryGetValue(scaleFactor, out var image)) + { + throw new KeyNotFoundException($"Missing scaleFactor = {scaleFactor}"); + } + + return image.ToBase64String(PngFormat.Instance); + } + + private Image Resize(int? width, int? height, float scaleFactor = 1.0f) { if (!_images.TryGetValue(scaleFactor, out var image) || (width is null && height is null)) { - return null; + throw new KeyNotFoundException($"Missing scaleFactor = {scaleFactor}"); } + + if (width is null && height is null) + { + throw new ArgumentNullException("Missing width or height"); + } + var aspect = GetAspectRatio(scaleFactor); - - width ??= Convert.ToInt32(image.Width * aspect); + width ??= Convert.ToInt32(image.Width * aspect); height ??= Convert.ToInt32(image.Height * aspect); - - width = Convert.ToInt32(width * scaleFactor); - height = Convert.ToInt32(height * scaleFactor); + width = Convert.ToInt32(width * scaleFactor); + height = Convert.ToInt32(height * scaleFactor); return image.Clone(c => c.Resize(new SixLabors.ImageSharp.Processing.ResizeOptions { - Size = new (width.Value, height.Value), + 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)) - { - return null; - } - var image = _images[scaleFactor]; - + + if (!_images.TryGetValue(scaleFactor, out image)) + { + throw new KeyNotFoundException($"Missing scaleFactor = {scaleFactor}"); + } + x ??= 0; y ??= 0; @@ -350,8 +370,7 @@ namespace ElectronNET.API.Entities width = Convert.ToInt32(width * scaleFactor); height = Convert.ToInt32(height * scaleFactor); - return image.Clone(c => - c.Crop(new SixLabors.ImageSharp.Rectangle(x.Value, y.Value, width.Value, height.Value))); + return image.Clone(c => c.Crop(new SixLabors.ImageSharp.Rectangle(x.Value, y.Value, width.Value, height.Value))); } internal Dictionary GetAllScaledImages() @@ -366,7 +385,7 @@ namespace ElectronNET.API.Entities } catch (Exception ex) { - Console.WriteLine(ex); + BridgeConnector.LogError(ex, "Error getting scaled images"); } return dict; @@ -374,17 +393,12 @@ namespace ElectronNET.API.Entities internal Image GetScale(float scaleFactor) { - if (_images.ContainsKey(scaleFactor)) + if (_images.TryGetValue(scaleFactor, out var image)) { - return _images[scaleFactor]; + return image; } return null; } - - /// - /// Utility conversion operator - /// - public static implicit operator NativeImage(Image src) => CreateFromImage(src); } } diff --git a/ElectronNET.API/Entities/NativeImageJsonConverter.cs b/ElectronNET.API/Entities/NativeImageJsonConverter.cs index 1915a5d..853550d 100644 --- a/ElectronNET.API/Entities/NativeImageJsonConverter.cs +++ b/ElectronNET.API/Entities/NativeImageJsonConverter.cs @@ -1,5 +1,8 @@ using System; using System.Collections.Generic; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.Formats.Png; +using SixLabors.ImageSharp.Processing; using System.IO; using Newtonsoft.Json; using SixLabors.ImageSharp; @@ -19,12 +22,15 @@ namespace ElectronNET.API.Entities 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.Load(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 c7194cd..6dd4fa9 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 d191379..5347822 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 @@ namespace ElectronNET.API.Entities /// /// A subtitle for the notification, which will be displayed below the title. /// + [SupportedOSPlatform("macos")] + public string SubTitle { get; set; } /// @@ -38,38 +41,46 @@ namespace ElectronNET.API.Entities /// /// 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 @@ namespace ElectronNET.API.Entities /// The string the user entered into the inline reply field /// [JsonIgnore] + [SupportedOSPlatform("macos")] public Action OnReply { get; set; } /// @@ -142,6 +154,7 @@ namespace ElectronNET.API.Entities /// 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 3f18dff..76b58a8 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 @@ namespace ElectronNET.API.Entities /// /// 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 44a16b1..ec47dad 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 @@ /// /// 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. /// - treatPackageAsDirectory + [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 + /// + [SupportedOSPlatform("windows")] + dontAddToRecent } } \ No newline at end of file diff --git a/ElectronNET.API/Entities/OpenExternalOptions.cs b/ElectronNET.API/Entities/OpenExternalOptions.cs index dba51ca..d913593 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 @@ namespace ElectronNET.API.Entities /// 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 16811d7..2e7ed4e 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 @@ namespace ElectronNET.API /// /// 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 0000000..f6bcac4 --- /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 8fb108e..a166b99 100644 --- a/ElectronNET.API/Entities/TitleBarStyle.cs +++ b/ElectronNET.API/Entities/TitleBarStyle.cs @@ -28,4 +28,11 @@ namespace ElectronNET.API.Entities /// 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/UpdateInfo.cs b/ElectronNET.API/Entities/UpdateInfo.cs index 01dc54b..8acc0bc 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 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 2e8bec8..b496abc 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 @@ namespace ElectronNET.API.Entities /// 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 @@ namespace ElectronNET.API.Entities /// 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 34a6531..c4b0178 100644 --- a/ElectronNET.API/Entities/WebPreferences.cs +++ b/ElectronNET.API/Entities/WebPreferences.cs @@ -171,6 +171,12 @@ namespace ElectronNET.API.Entities /// 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 @@ namespace ElectronNET.API.Entities [DefaultValue(false)] public bool ContextIsolation { get; set; } = false; - /// - /// 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 @@ namespace ElectronNET.API.Entities 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 6c01cdc..2eb65d8 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 4424310..949c1fc 100644 --- a/ElectronNET.API/Extensions/EnumExtensions.cs +++ b/ElectronNET.API/Extensions/EnumExtensions.cs @@ -11,7 +11,7 @@ namespace ElectronNET.API.Extensions 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 37a5b9c..44678a2 100644 --- a/ElectronNET.API/Extensions/MenuItemExtensions.cs +++ b/ElectronNET.API/Extensions/MenuItemExtensions.cs @@ -28,7 +28,7 @@ namespace ElectronNET.API.Extensions 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 3b15554..4d51005 100644 --- a/ElectronNET.API/Extensions/ThumbarButtonExtensions.cs +++ b/ElectronNET.API/Extensions/ThumbarButtonExtensions.cs @@ -23,7 +23,7 @@ namespace ElectronNET.API.Extensions 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 d978eb1..e1ef32c 100755 --- a/ElectronNET.API/GlobalShortcut.cs +++ b/ElectronNET.API/GlobalShortcut.cs @@ -11,7 +11,7 @@ namespace ElectronNET.API public sealed class GlobalShortcut : IGlobalShortcut { private static GlobalShortcut _globalShortcut; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal GlobalShortcut() { } @@ -34,7 +34,7 @@ namespace ElectronNET.API } } - 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 ea62eb1..0c0e04e 100755 --- a/ElectronNET.API/HostHook.cs +++ b/ElectronNET.API/HostHook.cs @@ -17,8 +17,8 @@ namespace ElectronNET.API public sealed class HostHook : IHostHook { 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/Interfaces/IApp.cs b/ElectronNET.API/Interfaces/IApp.cs index abaee74..ff5a305 100755 --- a/ElectronNET.API/Interfaces/IApp.cs +++ b/ElectronNET.API/Interfaces/IApp.cs @@ -95,8 +95,6 @@ namespace ElectronNET.API.Interfaces /// string Name { - [Obsolete("Use the asynchronous version NameAsync instead")] - get; set; } @@ -108,7 +106,7 @@ namespace ElectronNET.API.Interfaces /// should usually also specify a productName field, which is your application's full capitalized name, and /// which will be preferred over name by Electron. /// - Task NameAsync { get; } + Task GetNameAsync { get; } /// /// A object that allows you to read and manipulate the command line arguments that Chromium uses. @@ -125,8 +123,6 @@ namespace ElectronNET.API.Interfaces /// string UserAgentFallback { - [Obsolete("Use the asynchronous version UserAgentFallbackAsync instead")] - get; set; } @@ -138,7 +134,7 @@ namespace ElectronNET.API.Interfaces /// custom value as early as possible in your app's initialization to ensure that your overridden value /// is used. /// - Task UserAgentFallbackAsync { get; } + Task GetUserAgentFallbackAsync { get; } /// /// Emitted when a MacOS user wants to open a file with the application. The open-file event is usually emitted diff --git a/ElectronNET.API/Interfaces/IApplicationSocket.cs b/ElectronNET.API/Interfaces/IApplicationSocket.cs deleted file mode 100755 index 8d4044b..0000000 --- a/ElectronNET.API/Interfaces/IApplicationSocket.cs +++ /dev/null @@ -1,15 +0,0 @@ -using Quobject.SocketIoClientDotNet.Client; - -namespace ElectronNET.API.Interfaces -{ - /// - /// Wrapper for the underlying Socket connection - /// - public interface IApplicationSocket - { - /// - /// Socket used to communicate with main.js - /// - Socket Socket { get; } - } -} \ No newline at end of file diff --git a/ElectronNET.API/Interfaces/IAutoUpdater.cs b/ElectronNET.API/Interfaces/IAutoUpdater.cs index 4ff3637..1cc7ddb 100755 --- a/ElectronNET.API/Interfaces/IAutoUpdater.cs +++ b/ElectronNET.API/Interfaces/IAutoUpdater.cs @@ -13,14 +13,26 @@ namespace ElectronNET.API.Interfaces /// /// Whether to automatically download an update when it is found. (Default is true) /// - bool AutoDownload { get; set; } + bool AutoDownload { set; } + + /// + /// Whether to automatically download an update when it is found. (Default is true) + /// + Task IsAutoDownloadEnabledAsync { get; } /// /// Whether to automatically install a downloaded update on app quit (if `QuitAndInstall` was not called before). /// /// Applicable only on Windows and Linux. /// - bool AutoInstallOnAppQuit { get; set; } + bool AutoInstallOnAppQuit { set; } + + /// + /// Whether to automatically install a downloaded update on app quit (if `QuitAndInstall` was not called before). + /// + /// Applicable only on Windows and Linux. + /// + Task IsAutoInstallOnAppQuitEnabledAsync { get; } /// /// *GitHub provider only.* Whether to allow update to pre-release versions. @@ -28,47 +40,57 @@ namespace ElectronNET.API.Interfaces /// /// If "true", downgrade will be allowed("allowDowngrade" will be set to "true"). /// - bool AllowPrerelease { get; set; } + bool AllowPrerelease { set; } + + /// + /// *GitHub provider only.* Whether to allow update to pre-release versions. + /// Defaults to "true" if application version contains prerelease components (e.g. "0.12.1-alpha.1", here "alpha" is a prerelease component), otherwise "false". + /// + /// If "true", downgrade will be allowed("allowDowngrade" will be set to "true"). + /// + Task IsAllowPrereleaseEnabledAsync { get; } /// /// *GitHub provider only.* /// Get all release notes (from current version to latest), not just the latest (Default is false). /// - bool FullChangelog { get; set; } + bool FullChangelog { set; } + + /// + /// *GitHub provider only.* + /// Get all release notes (from current version to latest), not just the latest (Default is false). + /// + Task IsFullChangeLogEnabledAsync { get; } /// /// Whether to allow version downgrade (when a user from the beta channel wants to go back to the stable channel). /// Taken in account only if channel differs (pre-release version component in terms of semantic versioning). /// Default is false. /// - bool AllowDowngrade { get; set; } + bool AllowDowngrade { set; } + + Task IsAllowDowngradeEnabledAsync { get; } /// /// For test only. /// - string UpdateConfigPath { get; } + Task GetUpdateConfigPathAsync { get; } /// /// The current application version /// - Task CurrentVersionAsync { get; } + Task GetCurrentVersionAsync { get; } /// /// Get the update channel. Not applicable for GitHub. /// Doesn’t return channel from the update configuration, only if was previously set. /// - string Channel { get; } - - /// - /// Get the update channel. Not applicable for GitHub. - /// Doesn’t return channel from the update configuration, only if was previously set. - /// - Task ChannelAsync { get; } + Task GetChannelAsync { get; } /// /// The request headers. /// - Task> RequestHeadersAsync { get; } + Task> GetRequestHeadersAsync { get; } /// /// The request headers. diff --git a/ElectronNET.API/Interfaces/IProcess.cs b/ElectronNET.API/Interfaces/IProcess.cs deleted file mode 100644 index dc2c352..0000000 --- a/ElectronNET.API/Interfaces/IProcess.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System.Threading.Tasks; - -namespace ElectronNET.API.Interfaces -{ - /// - /// Electron's process object is extended from the Node.js process object. It adds the - /// events, properties, and methods. - /// - public interface IProcess - { - /// - /// The process.execPath property returns the absolute pathname of the executable that - /// started the Node.js process. Symbolic links, if any, are resolved. - /// - Task ExecPathAsync { get; } - - /// - /// The process.argv property returns an array containing the command-line arguments passed - /// when the Node.js process was launched. The first element will be process.execPath. See - /// process.argv0 if access to the original value of argv[0] is needed. The second element - /// will be the path to the JavaScript file being executed. The remaining elements will be - /// any additional command-line arguments - /// - Task ArgvAsync { get; } - - /// - /// The process.execPath property returns the absolute pathname of the executable that - /// started the Node.js process. Symbolic links, if any, are resolved. - /// - Task TypeAsync { get; } - - /// - /// The process.versions property returns an object listing the version strings of - /// chrome and electron. - /// - Task VersionsAsync { get; } - - /// - /// A Boolean. When app is started by being passed as parameter to the default app, this - /// property is true in the main process, otherwise it is false. - /// - Task DefaultAppAsync { get; } - - /// - /// A Boolean, true when the current renderer context is the "main" renderer frame. If you - /// want the ID of the current frame you should use webFrame.routingId - /// - Task IsMainFrameAsync { get; } - - /// - /// A String representing the path to the resources directory. - /// - Task ResourcesPathAsync { get; } - - /// - /// The number of seconds the current Node.js process has been running. The return value - /// includes fractions of a second. Use Math.floor() to get whole seconds. - /// - Task UpTimeAsync { get; } - - /// - /// The PID of the electron process - /// - Task PidAsync { get; } - - /// - /// The operating system CPU architecture for which the Node.js binary was compiled - /// - Task ArchAsync { get; } - - /// - /// A string identifying the operating system platform on which the Node.js process is running - /// - Task PlatformAsync { get; } - } -} \ No newline at end of file diff --git a/ElectronNET.API/IpcMain.cs b/ElectronNET.API/IpcMain.cs index e84e46d..7adbc10 100755 --- a/ElectronNET.API/IpcMain.cs +++ b/ElectronNET.API/IpcMain.cs @@ -15,7 +15,7 @@ namespace ElectronNET.API public sealed class IpcMain : IIpcMain { private static IpcMain _ipcMain; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal IpcMain() { } @@ -38,6 +38,8 @@ namespace ElectronNET.API } } + public static bool IsConnected => BridgeConnector.IsConnected; + /// /// Listens to channel, when a new message arrives listener would be called with /// listener(event, args...). @@ -48,11 +50,11 @@ namespace ElectronNET.API { 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()); } @@ -63,6 +65,38 @@ namespace ElectronNET.API }); } + /// + /// 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(); @@ -106,7 +140,7 @@ namespace ElectronNET.API public void Once(string channel, Action listener) { BridgeConnector.Emit("registerOnceIpcMainChannel", channel); - BridgeConnector.On(channel, (args) => + BridgeConnector.Once(channel, (args) => { var objectArray = FormatArguments(args); @@ -141,32 +175,29 @@ namespace ElectronNET.API /// 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()); } /// @@ -180,9 +211,9 @@ namespace ElectronNET.API /// 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) { @@ -229,7 +260,7 @@ namespace ElectronNET.API 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 c99392a..cadca65 100644 --- a/ElectronNET.API/LifetimeServiceHost.cs +++ b/ElectronNET.API/LifetimeServiceHost.cs @@ -1,8 +1,6 @@ -using System; -using System.Threading; +using System.Threading; using System.Threading.Tasks; using Microsoft.Extensions.Hosting; -using Quobject.SocketIoClientDotNet.Client; namespace ElectronNET.API { @@ -13,15 +11,11 @@ namespace ElectronNET.API { public LifetimeServiceHost(IHostApplicationLifetime lifetime) { - lifetime.ApplicationStarted.Register(async () => + lifetime.ApplicationStarted.Register(() => { - // wait till the socket is open before setting app to ready - while(BridgeConnector.Socket.Io().ReadyState != Manager.ReadyStateEnum.OPEN) { - await Task.Delay(50).ConfigureAwait(false); - } - 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 170655a..22d94c3 100755 --- a/ElectronNET.API/Menu.cs +++ b/ElectronNET.API/Menu.cs @@ -16,7 +16,7 @@ namespace ElectronNET.API public sealed class Menu : IMenu { private static Menu _menu; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Menu() { } @@ -46,7 +46,7 @@ namespace ElectronNET.API /// The menu items. /// public IReadOnlyCollection MenuItems { get { return _menuItems.AsReadOnly(); } } - private List _menuItems = new List(); + private readonly List _menuItems = new(); /// /// Sets the application menu. @@ -76,7 +76,7 @@ namespace ElectronNET.API /// The context menu items. /// public IReadOnlyDictionary> ContextMenuItems { get; internal set; } - private Dictionary> _contextMenuItems = new Dictionary>(); + private readonly Dictionary> _contextMenuItems = new(); /// /// Sets the context menu. @@ -114,7 +114,7 @@ namespace ElectronNET.API 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 d67ffd3..5e0acaa 100755 --- 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; @@ -12,7 +13,7 @@ namespace ElectronNET.API public sealed class NativeTheme : INativeTheme { private static NativeTheme _nativeTheme; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal NativeTheme() { } @@ -115,12 +116,16 @@ namespace ElectronNET.API /// 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 dc4d2b1..8f3859b 100755 --- a/ElectronNET.API/Notification.cs +++ b/ElectronNET.API/Notification.cs @@ -16,7 +16,7 @@ namespace ElectronNET.API public sealed class Notification : INotification { private static Notification _notification; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Notification() { } @@ -39,7 +39,7 @@ namespace ElectronNET.API } } - private static List _notificationOptions = new List(); + private static readonly List _notificationOptions = new(); /// /// Create OS desktop notifications @@ -49,7 +49,7 @@ namespace ElectronNET.API { GenerateIDsForDefinedActions(notificationOptions); - BridgeConnector.Emit("createNotification", notificationOptions); + BridgeConnector.Emit("createNotification", JObject.FromObject(notificationOptions, _jsonSerializer)); } private static void GenerateIDsForDefinedActions(NotificationOptions notificationOptions) @@ -135,5 +135,12 @@ namespace ElectronNET.API 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 b5ec6c1..f1d1754 100755 --- a/ElectronNET.API/PowerMonitor.cs +++ b/ElectronNET.API/PowerMonitor.cs @@ -1,4 +1,5 @@ using System; +using System.Runtime.Versioning; using System.Threading.Tasks; using ElectronNET.API.Interfaces; @@ -12,6 +13,8 @@ namespace ElectronNET.API /// /// Emitted when the system is about to lock the screen. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnLockScreen { add @@ -41,6 +44,8 @@ namespace ElectronNET.API /// /// Emitted when the system is about to unlock the screen. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnUnLockScreen { add @@ -70,6 +75,8 @@ namespace ElectronNET.API /// /// Emitted when the system is suspending. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnSuspend { add @@ -99,6 +106,8 @@ namespace ElectronNET.API /// /// Emitted when system is resuming. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnResume { add @@ -128,6 +137,8 @@ namespace ElectronNET.API /// /// Emitted when the system changes to AC power. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnAC { add @@ -157,6 +168,8 @@ namespace ElectronNET.API /// /// Emitted when system changes to battery power. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnBattery { add @@ -190,6 +203,9 @@ namespace ElectronNET.API /// 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 @@ -217,7 +233,7 @@ namespace ElectronNET.API 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/Process.cs b/ElectronNET.API/Process.cs deleted file mode 100644 index 34cd72a..0000000 --- a/ElectronNET.API/Process.cs +++ /dev/null @@ -1,186 +0,0 @@ -using System.Threading; -using System.Threading.Tasks; -using ElectronNET.API.Interfaces; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace ElectronNET.API -{ - /// - /// Electron's process object is extended from the Node.js process object. It adds the - /// events, properties, and methods. - /// - public sealed class Process : IProcess - { - internal Process() { } - - internal static Process Instance - { - get - { - if (_process == null) - { - lock (_syncRoot) - { - if (_process == null) - { - _process = new Process(); - } - } - } - - return _process; - } - } - - private static Process _process; - - private static readonly object _syncRoot = new(); - - /// - /// The process.execPath property returns the absolute pathname of the executable that - /// started the Node.js process. Symbolic links, if any, are resolved. - /// - public Task ExecPathAsync - { - get - { - return BridgeConnector.GetValueOverSocketAsync( - "process-execPath", "process-execPath-Completed"); - } - } - - /// - /// The process.argv property returns an array containing the command-line arguments passed - /// when the Node.js process was launched. The first element will be process.execPath. See - /// process.argv0 if access to the original value of argv[0] is needed. The second element - /// will be the path to the JavaScript file being executed. The remaining elements will be - /// any additional command-line arguments - /// - public Task ArgvAsync - { - get - { - return BridgeConnector.GetArrayOverSocketAsync( - "process-argv", "process-argv-Completed"); - } - } - - /// - /// The process.execPath property returns the absolute pathname of the executable that - /// started the Node.js process. Symbolic links, if any, are resolved. - /// - public Task TypeAsync - { - get - { - return BridgeConnector.GetValueOverSocketAsync( - "process-type", "process-type-Completed"); - } - } - - - /// - /// The process.versions property returns an object listing the version strings of - /// chrome and electron. - /// - public Task VersionsAsync - { - get - { - return BridgeConnector.GetObjectOverSocketAsync( - "process-versions", "process-versions-Completed"); - } - } - - - /// - /// A Boolean. When app is started by being passed as parameter to the default app, this - /// property is true in the main process, otherwise it is false. - /// - public Task DefaultAppAsync - { - get - { - return BridgeConnector.GetValueOverSocketAsync( - "process-defaultApp", "process-defaultApp-Completed"); - } - } - - /// - /// A Boolean, true when the current renderer context is the "main" renderer frame. If you - /// want the ID of the current frame you should use webFrame.routingId - /// - public Task IsMainFrameAsync - { - get - { - return BridgeConnector.GetValueOverSocketAsync( - "process-isMainFrame", "process-isMainFrame-Completed"); - } - } - - /// - /// A String representing the path to the resources directory. - /// - public Task ResourcesPathAsync - { - get - { - return BridgeConnector.GetValueOverSocketAsync( - "process-resourcesPath", "process-resourcesPath-Completed"); - } - } - - /// - /// The number of seconds the current Node.js process has been running. The return value - /// includes fractions of a second. Use Math.floor() to get whole seconds. - /// - public Task UpTimeAsync - { - get - { - return BridgeConnector.GetValueOverSocketAsync( - "process-uptime", "process-uptime-Completed"); - } - } - - /// - /// The PID of the electron process - /// - public Task PidAsync - { - get - { - return BridgeConnector.GetValueOverSocketAsync( - "process-pid", "process-pid-Completed"); - } - } - - - /// - /// The operating system CPU architecture for which the Node.js binary was compiled - /// - public Task ArchAsync - { - get - { - return BridgeConnector.GetValueOverSocketAsync( - "process-arch", "process-arch-Completed"); - } - } - - /// - /// A string identifying the operating system platform on which the Node.js process is running - /// - public Task PlatformAsync - { - get - { - return BridgeConnector.GetValueOverSocketAsync( - "process-platform", "process-platform-Completed"); - } - } - - } -} diff --git a/ElectronNET.API/ProcessHelper.cs b/ElectronNET.API/ProcessHelper.cs new file mode 100644 index 0000000..08fedc2 --- /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 1fa13d2..1e092c8 100755 --- a/ElectronNET.API/Screen.cs +++ b/ElectronNET.API/Screen.cs @@ -103,7 +103,7 @@ namespace ElectronNET.API 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/ServiceCollectionExtensions.cs b/ElectronNET.API/ServiceCollectionExtensions.cs index d9a5974..b9210e6 100755 --- a/ElectronNET.API/ServiceCollectionExtensions.cs +++ b/ElectronNET.API/ServiceCollectionExtensions.cs @@ -31,7 +31,6 @@ namespace ElectronNET.API .AddSingleton(provider => PowerMonitor.Instance) .AddSingleton(provider => NativeTheme.Instance) .AddSingleton(provider => Dock.Instance) - .AddSingleton(provider => new ApplicationSocket { Socket = BridgeConnector.Socket, }) // this set for proper dependency injection .AddSingleton(_ => IpcMain.Instance) .AddSingleton(_ => App.Instance) @@ -48,8 +47,6 @@ namespace ElectronNET.API .AddSingleton(_ => HostHook.Instance) .AddSingleton(_ => PowerMonitor.Instance) .AddSingleton(_ => NativeTheme.Instance) - .AddSingleton(_ => Dock.Instance) - .AddSingleton(_ => Process.Instance) - .AddSingleton(provider => provider.GetService()); + .AddSingleton(_ => Dock.Instance); } } diff --git a/ElectronNET.API/Shell.cs b/ElectronNET.API/Shell.cs index cfb843d..ff01830 100755 --- a/ElectronNET.API/Shell.cs +++ b/ElectronNET.API/Shell.cs @@ -5,6 +5,7 @@ using Newtonsoft.Json.Serialization; using System.Threading.Tasks; using ElectronNET.API.Extensions; using ElectronNET.API.Interfaces; +using System.Runtime.Versioning; namespace ElectronNET.API { @@ -14,7 +15,7 @@ namespace ElectronNET.API public sealed class Shell : IShell { private static Shell _shell; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Shell() { } @@ -94,6 +95,7 @@ namespace ElectronNET.API /// 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); @@ -142,6 +144,7 @@ namespace ElectronNET.API /// 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); @@ -153,6 +156,7 @@ namespace ElectronNET.API /// /// 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 0000000..206b266 --- /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 0000000..ed66d95 --- /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 0000000..48d5f02 --- /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 0000000..ff5ae99 --- /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 0000000..a0f8722 --- /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 0000000..b05b8f3 --- /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 0000000..a03fadf --- /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 0000000..30bc704 --- /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 0000000..8cfe4b8 --- /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 0000000..c4bc1e8 --- /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 0000000..9a90981 --- /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 0000000..c0584dd --- /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 0000000..df2a7c0 --- /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 0000000..2b4dcda --- /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 0000000..f151268 --- /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 0000000..0663ad5 --- /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 0000000..4bceba9 --- /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 0000000..f36d78b --- /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 0000000..522bd20 --- /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 0000000..c7f0e25 --- /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 0000000..227a6f7 --- /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 0000000..345c98f --- /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 0000000..df297ea --- /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 0000000..fa2b134 --- /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 0000000..fb4ccfa --- /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 0000000..ce8ce1a --- /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 0000000..199f309 --- /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 0000000..9691ffc --- /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 0000000..edf2f1c --- /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 0000000..dc154bb --- /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 0000000..42d979c --- /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 0000000..efbdc64 --- /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 0000000..8134c3f --- /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 0000000..a8b1208 --- /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 0000000..48147dc --- /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 0000000..4e7c6bf --- /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 0000000..a3f75fd --- /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 0000000..f117010 --- /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 0000000..e906f67 --- /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 0000000..5a49dbd --- /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 0000000..24f9aeb --- /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 0000000..50ad89b --- /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 0000000..532ac66 --- /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 0000000..923f813 --- /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 0000000..922ee9d --- /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 b891401..8f9d115 100755 --- a/ElectronNET.API/Tray.cs +++ b/ElectronNET.API/Tray.cs @@ -5,6 +5,7 @@ using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using System; using System.Collections.Generic; +using System.Runtime.Versioning; using System.Threading.Tasks; using ElectronNET.API.Interfaces; @@ -13,6 +14,8 @@ namespace ElectronNET.API /// /// Add icons and context menus to the system's notification area. /// + [SupportedOSPlatform("macos")] + [SupportedOSPlatform("windows")] public sealed class Tray : ITray { /// @@ -47,6 +50,8 @@ namespace ElectronNET.API /// /// macOS, Windows: Emitted when the tray icon is right clicked. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnRightClick { add @@ -76,6 +81,8 @@ namespace ElectronNET.API /// /// macOS, Windows: Emitted when the tray icon is double clicked. /// + [SupportedOSPlatform("windows")] + [SupportedOSPlatform("macos")] public event Action OnDoubleClick { add @@ -105,6 +112,7 @@ namespace ElectronNET.API /// /// Windows: Emitted when the tray balloon shows. /// + [SupportedOSPlatform("windows")] public event Action OnBalloonShow { add @@ -134,6 +142,7 @@ namespace ElectronNET.API /// /// Windows: Emitted when the tray balloon is clicked. /// + [SupportedOSPlatform("windows")] public event Action OnBalloonClick { add @@ -164,6 +173,8 @@ namespace ElectronNET.API /// Windows: Emitted when the tray balloon is closed /// because of timeout or user manually closes it. /// + + [SupportedOSPlatform("windows")] public event Action OnBalloonClosed { add @@ -193,7 +204,7 @@ namespace ElectronNET.API // TODO: Implement macOS Events private static Tray _tray; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal Tray() { } @@ -223,7 +234,7 @@ namespace ElectronNET.API /// The menu items. /// public IReadOnlyCollection MenuItems { get { return _items.AsReadOnly(); } } - private List _items = new List(); + private readonly List _items = new(); /// /// Shows the Traybar. @@ -286,6 +297,7 @@ namespace ElectronNET.API /// Sets the image associated with this tray icon when pressed on macOS. /// /// + [SupportedOSPlatform("macos")] public void SetPressedImage(string image) { BridgeConnector.Emit("tray-setPressedImage", image); @@ -304,6 +316,7 @@ namespace ElectronNET.API /// 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); @@ -313,6 +326,7 @@ namespace ElectronNET.API /// Windows: Displays a tray balloon. /// /// + [SupportedOSPlatform("windows")] public void DisplayBalloon(DisplayBalloonOptions options) { BridgeConnector.Emit("tray-displayBalloon", options); @@ -354,7 +368,7 @@ namespace ElectronNET.API /// 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 af7cf91..6c5735f 100644 --- a/ElectronNET.API/WebHostBuilderExtensions.cs +++ b/ElectronNET.API/WebHostBuilderExtensions.cs @@ -23,7 +23,7 @@ namespace ElectronNET.API 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 c8e3ae9..f165627 100755 --- a/ElectronNET.API/WindowManager.cs +++ b/ElectronNET.API/WindowManager.cs @@ -3,10 +3,12 @@ using Newtonsoft.Json; 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.Text.RegularExpressions; +using System.Threading; using System.Threading.Tasks; using ElectronNET.API.Interfaces; @@ -18,7 +20,7 @@ namespace ElectronNET.API public sealed class WindowManager : IWindowManager { private static WindowManager _windowManager; - private static object _syncRoot = new object(); + private static readonly object _syncRoot = new(); internal WindowManager() { } @@ -64,8 +66,18 @@ namespace ElectronNET.API /// /// 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. @@ -73,8 +85,16 @@ namespace ElectronNET.API /// /// 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. @@ -92,90 +112,92 @@ namespace ElectronNET.API /// The options. /// The load URL. /// - public Task CreateWindowAsync(BrowserWindowOptions options, string loadUrl = "/") + public async Task CreateWindowAsync(BrowserWindowOptions options, string loadUrl = "http://localhost") { + BootstrapUpdateOpenIDsEvent(); + var taskCompletionSource = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - BridgeConnector.On("BrowserWindowCreated", (id) => - { - BridgeConnector.Off("BrowserWindowCreated"); + var guid = Guid.NewGuid().ToString(); - BrowserWindow browserWindow = new BrowserWindow(id); - _browserWindows.Add(browserWindow); + BridgeConnector.Once("BrowserWindowCreated" + guid, (id) => + { + var browserWindow = new BrowserWindow(id); + + _browserWindows[id] = browserWindow; taskCompletionSource.SetResult(browserWindow); }); - BridgeConnector.Off("BrowserWindowClosed"); - BridgeConnector.On("BrowserWindowClosed", (browserWindowIds) => + if (string.Equals(loadUrl, "HTTP://LOCALHOST", StringComparison.InvariantCultureIgnoreCase)) { - for (int index = 0; index < _browserWindows.Count; index++) - { - if (!browserWindowIds.Contains(_browserWindows[index].Id)) - { - _browserWindows.RemoveAt(index); - } - } - }); - - if(!TryParseLoadUrl(loadUrl, out loadUrl)) - { - throw new ArgumentException($"Unable to parse {loadUrl}", nameof(loadUrl)); + 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() + BridgeConnector.Emit("createBrowserWindow", guid, JObject.FromObject(options, _keepDefaultValuesSerializer), loadUrl); + } + + return await taskCompletionSource.Task; + } + + + private bool _hasClosedEvent = false; + private readonly object _hasClosedEventLock = new(); + private void BootstrapUpdateOpenIDsEvent() + { + if (!_hasClosedEvent) + { + lock(_hasClosedEventLock) { - ContractResolver = new CamelCasePropertyNamesContractResolver(), - NullValueHandling = NullValueHandling.Ignore - }; - - BridgeConnector.Emit("createBrowserWindow", JObject.FromObject(options, ownjsonSerializer), loadUrl); + 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; + } + } } - - return taskCompletionSource.Task; } - - private bool TryParseLoadUrl(string loadUrl, out string parsedUrl) + private bool IsWindows10() { - Uri BaseUri = new Uri($"http://localhost:{BridgeSettings.WebPort}"); - if (Uri.TryCreate(loadUrl, UriKind.Absolute, out var url) || - Uri.TryCreate(BaseUri, loadUrl, out url)) { - var uri = new UriBuilder(url.ToString()); - parsedUrl = uri.ToString(); - return true; - } - parsedUrl = loadUrl; - return false; - } - - private bool isWindows10() - { - return RuntimeInformation.OSDescription.Contains("Windows 10"); + return OperatingSystem.IsWindowsVersionAtLeast(10); } /// @@ -196,30 +218,41 @@ namespace ElectronNET.API /// /// /// - 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 taskCompletionSource.Task; + return await 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 b2aa7b4..462a449 100644 --- a/ElectronNET.CLI/Commands/Actions/DeployEmbeddedElectronFiles.cs +++ b/ElectronNET.CLI/Commands/Actions/DeployEmbeddedElectronFiles.cs @@ -30,6 +30,7 @@ namespace ElectronNET.CLI.Commands.Actions 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 39ded69..2509f54 100644 --- a/ElectronNET.CLI/Commands/Actions/DirectoryCopy.cs +++ b/ElectronNET.CLI/Commands/Actions/DirectoryCopy.cs @@ -8,16 +8,14 @@ namespace ElectronNET.CLI.Commands.Actions 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 @@ namespace ElectronNET.CLI.Commands.Actions } 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 @@ namespace ElectronNET.CLI.Commands.Actions // 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 @@ namespace ElectronNET.CLI.Commands.Actions // 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 1496264..addf567 100644 --- a/ElectronNET.CLI/Commands/Actions/GetTargetPlatformInformation.cs +++ b/ElectronNET.CLI/Commands/Actions/GetTargetPlatformInformation.cs @@ -60,7 +60,7 @@ namespace ElectronNET.CLI.Commands.Actions netCorePublishRid = $"win-x{(Environment.Is64BitOperatingSystem ? "64" : "86")}"; electronPackerPlatform = "win"; } - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { if (RuntimeInformation.OSArchitecture.Equals(Architecture.Arm64) && Dotnet6Installed()) { @@ -71,13 +71,14 @@ namespace ElectronNET.CLI.Commands.Actions netCorePublishRid = "osx-arm64"; electronPackerPlatform = "mac"; } - else{ + 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 cbfb0dd..9d00240 100644 --- a/ElectronNET.CLI/Commands/AddCommand.cs +++ b/ElectronNET.CLI/Commands/AddCommand.cs @@ -16,14 +16,14 @@ namespace ElectronNET.CLI.Commands 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 @@ namespace ElectronNET.CLI.Commands 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 f1f9f73..1d210b1 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,6 +10,8 @@ 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 + @@ -32,7 +35,7 @@ namespace ElectronNET.CLI.Commands public static IList CommandOptions { get; set; } = new List(); - private string[] _args; + private readonly string[] _args; public BuildCommand(string[] args) { @@ -193,21 +196,45 @@ namespace ElectronNET.CLI.Commands string electronArch = "x64"; - //Somewhat janky fix for Apple Silicon: - if (platformInfo.NetCorePublishRid == "osx-arm64") + + if (platformInfo.NetCorePublishRid == "osx-arm64") //Apple Silicon Mac { - electronArch = "arm64"; + 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 projectFile in Directory.GetFiles(Directory.GetCurrentDirectory(), "*.csproj")) + { + var projectXML = File.ReadAllText(projectFile); + 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 {projectFile}"); + 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 c253920..88e7bd5 100644 --- a/ElectronNET.CLI/Commands/InitCommand.cs +++ b/ElectronNET.CLI/Commands/InitCommand.cs @@ -25,8 +25,8 @@ namespace ElectronNET.CLI.Commands _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 8bfb402..98c2fcd 100644 --- a/ElectronNET.CLI/Commands/StartElectronCommand.cs +++ b/ElectronNET.CLI/Commands/StartElectronCommand.cs @@ -15,7 +15,7 @@ namespace ElectronNET.CLI.Commands 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 c8f60f8..0d2637c 100644 --- a/ElectronNET.CLI/Commands/VersionCommand.cs +++ b/ElectronNET.CLI/Commands/VersionCommand.cs @@ -12,7 +12,7 @@ namespace ElectronNET.CLI.Commands 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 c7e1287..c1de09c 100755 --- a/ElectronNET.CLI/ElectronNET.CLI.csproj +++ b/ElectronNET.CLI/ElectronNET.CLI.csproj @@ -2,9 +2,9 @@ Exe + net6.0 dotnet-electronize electronize - DotnetCliTool true ..\artifacts @@ -65,6 +65,7 @@ + diff --git a/ElectronNET.CLI/ProcessHelper.cs b/ElectronNET.CLI/ProcessHelper.cs index 5f7d6cc..9ac02f9 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 891b15e..8621efc 100644 --- a/ElectronNET.CLI/Program.cs +++ b/ElectronNET.CLI/Program.cs @@ -42,7 +42,7 @@ namespace ElectronNET.CLI 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 @@ namespace ElectronNET.CLI 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 @@ namespace ElectronNET.CLI StringBuilder stringBuilder = new StringBuilder(); if (option.ShortSwitch != null) { - stringBuilder.Append($"{option.ShortSwitch.PadRight(6)} | "); + stringBuilder.Append($"{option.ShortSwitch,-6} | "); } stringBuilder.Append($"{option.Switch}"); @@ -184,7 +184,7 @@ namespace ElectronNET.CLI stringBuilder.Append(option.Description); - Console.WriteLine($"{new string(' ', INDENT * 2)}{stringBuilder.ToString()}"); + Console.WriteLine($"{new string(' ', INDENT * 2)}{stringBuilder}"); } } diff --git a/ElectronNET.CLI/Properties/launchSettings.json b/ElectronNET.CLI/Properties/launchSettings.json index 5adf9cd..3662f46 100644 --- a/ElectronNET.CLI/Properties/launchSettings.json +++ b/ElectronNET.CLI/Properties/launchSettings.json @@ -1,6 +1,11 @@ { "profiles": { - "ElectronNET.CLI": { + "Build Test App": { + "commandName": "Project", + "commandLineArgs": "build /target win /PublishSingleFile false /PublishReadyToRun false", + "workingDirectory": "$(SolutionDir)ElectronNET.WebApp" + }, + "Start Test App": { "commandName": "Project", "commandLineArgs": "start /project-path \"$(SolutionDir)ElectronNET.WebApp\" /watch" } diff --git a/ElectronNET.CLI/SimpleCommandLineParser.cs b/ElectronNET.CLI/SimpleCommandLineParser.cs index 9da5d73..2391951 100644 --- a/ElectronNET.CLI/SimpleCommandLineParser.cs +++ b/ElectronNET.CLI/SimpleCommandLineParser.cs @@ -20,14 +20,20 @@ namespace ElectronNET.CLI if (arg.StartsWith("/")) { if (currentName != "") + { Arguments[currentName] = values.ToArray(); + } values.Clear(); currentName = arg.Substring(1); } else if (currentName == "") - Arguments[arg] = new string[0]; + { + Arguments[arg] = Array.Empty(); + } else + { values.Add(arg); + } } if (currentName != "") Arguments[currentName] = values.ToArray(); diff --git a/ElectronNET.Host/.gitignore b/ElectronNET.Host/.gitignore index 9e87c05..b03314c 100644 --- a/ElectronNET.Host/.gitignore +++ b/ElectronNET.Host/.gitignore @@ -1,2 +1,3 @@ node_modules -bin \ No newline at end of file +bin +package-lock.json \ No newline at end of file diff --git a/ElectronNET.Host/Web.config b/ElectronNET.Host/Web.config new file mode 100644 index 0000000..46ac13b --- /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 e9fb535..5e5a669 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 de9eed0..53ce132 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 4d8df78..d715dd4 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]); } diff --git a/ElectronNET.Host/api/autoUpdater.js b/ElectronNET.Host/api/autoUpdater.js index 3ba69ca..f87b56a 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,29 @@ 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 3e9bdd2..bb09672 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":"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"} \ No newline at end of file +{"version":3,"file":"autoUpdater.js","sourceRoot":"","sources":["autoUpdater.ts"],"names":[],"mappings":";AACA,uDAA6C;AAC7C,uCAAuC;AAEvC,IAAI,cAAc,CAAC;AAEnB,iBAAS,CAAC,MAAc,EAAE,GAAiB,EAAE,EAAE;IAC3C,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,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;QAEjD,GAAG,CAAC,kBAAkB,CAAC,mBAAmB,CAAC,CAAC;QAC5C,MAAM,OAAO,GAAG,wBAAa,CAAC,aAAa,EAAE,CAAC;QAC9C,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE;YAC3B,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;gBAChB,IAAI;oBACA,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;oBAC9B,CAAC,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;oBAC/B,CAAC,CAAC,OAAO,EAAE,CAAC;iBACf;gBAAC,MAAM;oBACJ,oCAAoC;iBACvC;YACL,CAAC,CAAC,CAAC;SACN;QAED,+DAA+D;QAC/D,8EAA8E;QAC9E,UAAU,CAAC,GAAG,EAAE;YACZ,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,WAAW,GAAG,QAAQ,CAAC,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,eAAe,CAAC,CAAC;YAClD,8BAAW,CAAC,cAAc,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;QAC1D,CAAC,EAAE,GAAG,CAAC,CAAC;IACZ,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 diff --git a/ElectronNET.Host/api/autoUpdater.ts b/ElectronNET.Host/api/autoUpdater.ts index f72c5d1..34715a2 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 ad31d0e..c06b795 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 75ebd06..33a2237 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 fe7746e..a4c96bf 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 965f9da..8950fa9 100644 --- a/ElectronNET.Host/api/browserWindows.js +++ b/ElectronNET.Host/api/browserWindows.js @@ -1,213 +1,189 @@ "use strict"; const electron_1 = require("electron"); const browserView_1 = require("./browserView"); -const path = require("path"); +const path = require('path'); const windows = (global['browserWindows'] = global['browserWindows'] || []); -const readyToShowWindowsIds = (global['readyToShowWindowsIds'] = global['readyToShowWindowsIds'] || []); +let readyToShowWindowsIds = []; +let window, electronSocket; +let mainWindowURL; const proxyToCredentialsMap = (global['proxyToCredentialsMap'] = global['proxyToCredentialsMap'] || []); -let window, lastOptions, electronSocket; -module.exports = (socket, app) => { +module.exports = (socket, app, firstTime) => { electronSocket = socket; - app.on('login', (event, webContents, request, authInfo, callback) => { - if (authInfo.isProxy) { - const proxy = `${authInfo.host}:${authInfo.port}`; - if (proxy in proxyToCredentialsMap && proxyToCredentialsMap[proxy].split(':').length === 2) { - event.preventDefault(); - const user = proxyToCredentialsMap[proxy].split(':')[0]; - const 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) => { - var _a; const index = readyToShowWindowsIds.indexOf(id); if (index > -1) { readyToShowWindowsIds.splice(index, 1); electronSocket.emit('browserWindow-ready-to-show' + id); } - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('ready-to-show', () => { + getWindowById(id)?.on('ready-to-show', () => { readyToShowWindowsIds.push(id); electronSocket.emit('browserWindow-ready-to-show' + id); }); }); socket.on('register-browserWindow-page-title-updated', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('page-title-updated', (event, title) => { + getWindowById(id)?.on('page-title-updated', (event, title) => { electronSocket.emit('browserWindow-page-title-updated' + id, title); }); }); socket.on('register-browserWindow-close', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('close', () => { + getWindowById(id)?.on('close', () => { electronSocket.emit('browserWindow-close' + id); }); }); socket.on('register-browserWindow-closed', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('closed', () => { + getWindowById(id)?.on('closed', () => { electronSocket.emit('browserWindow-closed' + id); }); }); socket.on('register-browserWindow-session-end', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('session-end', () => { + getWindowById(id)?.on('session-end', () => { electronSocket.emit('browserWindow-session-end' + id); }); }); socket.on('register-browserWindow-unresponsive', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('unresponsive', () => { + getWindowById(id)?.on('unresponsive', () => { electronSocket.emit('browserWindow-unresponsive' + id); }); }); socket.on('register-browserWindow-responsive', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('responsive', () => { + getWindowById(id)?.on('responsive', () => { electronSocket.emit('browserWindow-responsive' + id); }); }); socket.on('register-browserWindow-blur', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('blur', () => { + getWindowById(id)?.on('blur', () => { electronSocket.emit('browserWindow-blur' + id); }); }); socket.on('register-browserWindow-focus', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('focus', () => { + getWindowById(id)?.on('focus', () => { electronSocket.emit('browserWindow-focus' + id); }); }); socket.on('register-browserWindow-show', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('show', () => { + getWindowById(id)?.on('show', () => { electronSocket.emit('browserWindow-show' + id); }); }); socket.on('register-browserWindow-hide', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('hide', () => { + getWindowById(id)?.on('hide', () => { electronSocket.emit('browserWindow-hide' + id); }); }); socket.on('register-browserWindow-maximize', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('maximize', () => { + getWindowById(id)?.on('maximize', () => { electronSocket.emit('browserWindow-maximize' + id); }); }); socket.on('register-browserWindow-unmaximize', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('unmaximize', () => { + getWindowById(id)?.on('unmaximize', () => { electronSocket.emit('browserWindow-unmaximize' + id); }); }); socket.on('register-browserWindow-minimize', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('minimize', () => { + getWindowById(id)?.on('minimize', () => { electronSocket.emit('browserWindow-minimize' + id); }); }); socket.on('register-browserWindow-restore', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('restore', () => { + getWindowById(id)?.on('restore', () => { electronSocket.emit('browserWindow-restore' + id); }); }); socket.on('register-browserWindow-resize', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('resize', () => { + getWindowById(id)?.on('resize', () => { electronSocket.emit('browserWindow-resize' + id); }); }); socket.on('register-browserWindow-move', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('move', () => { + getWindowById(id)?.on('move', () => { electronSocket.emit('browserWindow-move' + id); }); }); socket.on('register-browserWindow-moved', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('moved', () => { + getWindowById(id)?.on('moved', () => { electronSocket.emit('browserWindow-moved' + id); }); }); socket.on('register-browserWindow-enter-full-screen', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('enter-full-screen', () => { + getWindowById(id)?.on('enter-full-screen', () => { electronSocket.emit('browserWindow-enter-full-screen' + id); }); }); socket.on('register-browserWindow-leave-full-screen', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('leave-full-screen', () => { + getWindowById(id)?.on('leave-full-screen', () => { electronSocket.emit('browserWindow-leave-full-screen' + id); }); }); socket.on('register-browserWindow-enter-html-full-screen', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('enter-html-full-screen', () => { + getWindowById(id)?.on('enter-html-full-screen', () => { electronSocket.emit('browserWindow-enter-html-full-screen' + id); }); }); socket.on('register-browserWindow-leave-html-full-screen', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('leave-html-full-screen', () => { + getWindowById(id)?.on('leave-html-full-screen', () => { electronSocket.emit('browserWindow-leave-html-full-screen' + id); }); }); socket.on('register-browserWindow-app-command', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('app-command', (event, command) => { + getWindowById(id)?.on('app-command', (event, command) => { electronSocket.emit('browserWindow-app-command' + id, command); }); }); socket.on('register-browserWindow-scroll-touch-begin', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('scroll-touch-begin', () => { + getWindowById(id)?.on('scroll-touch-begin', () => { electronSocket.emit('browserWindow-scroll-touch-begin' + id); }); }); socket.on('register-browserWindow-scroll-touch-end', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('scroll-touch-end', () => { + getWindowById(id)?.on('scroll-touch-end', () => { electronSocket.emit('browserWindow-scroll-touch-end' + id); }); }); socket.on('register-browserWindow-scroll-touch-edge', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('scroll-touch-edge', () => { + getWindowById(id)?.on('scroll-touch-edge', () => { electronSocket.emit('browserWindow-scroll-touch-edge' + id); }); }); socket.on('register-browserWindow-swipe', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('swipe', (event, direction) => { + getWindowById(id)?.on('swipe', (event, direction) => { electronSocket.emit('browserWindow-swipe' + id, direction); }); }); socket.on('register-browserWindow-sheet-begin', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('sheet-begin', () => { + getWindowById(id)?.on('sheet-begin', () => { electronSocket.emit('browserWindow-sheet-begin' + id); }); }); socket.on('register-browserWindow-sheet-end', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('sheet-end', () => { + getWindowById(id)?.on('sheet-end', () => { electronSocket.emit('browserWindow-sheet-end' + id); }); }); socket.on('register-browserWindow-new-window-for-tab', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.on('new-window-for-tab', () => { + getWindowById(id)?.on('new-window-for-tab', () => { 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 } }; @@ -215,15 +191,20 @@ module.exports = (socket, app) => { 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; + } + if (options.parent) { + options.parent = electron_1.BrowserWindow.fromId(options.parent.id); + } // 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(); - if (windows.findIndex(i => i.id == window.id) == -1) { - windows.push(window); - } - electronSocket.emit('BrowserWindowCreated', window.id); + windows.push(window); + electronSocket.emit('BrowserWindowCreated' + guid, window.id); return; } } @@ -237,18 +218,24 @@ module.exports = (socket, app) => { if (options.proxy && options.proxyCredentials) { proxyToCredentialsMap[options.proxy] = options.proxyCredentials; } - thisWindow.on('ready-to-show', () => { - const index = readyToShowWindowsIds.indexOf(thisWindow.id); - if (index > -1) { - readyToShowWindowsIds.splice(index, 1); + 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 { readyToShowWindowsIds.push(thisWindow.id); } }); - lastOptions = options; - thisWindow.on('closed', (sender) => { - for (let index = 0; index < windows.length; index++) { + window.on('closed', (sender) => { + again: for (let index = 0; index < windows.length; index++) { const windowItem = windows[index]; try { windowItem.id; @@ -256,20 +243,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; } } } - }); - // this seems dangerous to assume - 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) { thisWindow.loadURL(loadUrl); @@ -284,28 +264,41 @@ module.exports = (socket, app) => { app['mainWindowURL'] = loadUrl; app['mainWindow'] = thisWindow; } - windows.push(thisWindow); - electronSocket.emit('BrowserWindowCreated', thisWindow.id); + windows.push(window); + electronSocket.emit('BrowserWindowCreated' + guid, window.id); }); socket.on('browserWindowDestroy', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.destroy(); + 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) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.close(); + getWindowById(id)?.close(); }); socket.on('browserWindowFocus', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.focus(); + getWindowById(id)?.focus(); }); socket.on('browserWindowBlur', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.blur(); + getWindowById(id)?.blur(); }); socket.on('browserWindowIsFocused', (id) => { - var _a, _b; - const isFocused = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isFocused()) !== null && _b !== void 0 ? _b : null; + const isFocused = getWindowById(id)?.isFocused() ?? null; electronSocket.emit('browserWindow-isFocused-completed' + id, isFocused); }); socket.on('browserWindowIsDestroyed', (id) => { @@ -316,284 +309,224 @@ module.exports = (socket, app) => { } }); socket.on('browserWindowShow', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.show(); + getWindowById(id)?.show(); }); socket.on('browserWindowShowInactive', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.showInactive(); + getWindowById(id)?.showInactive(); }); socket.on('browserWindowHide', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.hide(); + getWindowById(id)?.hide(); }); socket.on('browserWindowIsVisible', (id) => { - var _a, _b; - const isVisible = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isVisible()) !== null && _b !== void 0 ? _b : null; + const isVisible = getWindowById(id)?.isVisible() ?? null; electronSocket.emit('browserWindow-isVisible-completed' + id, isVisible); }); socket.on('browserWindowIsModal', (id) => { - var _a, _b; - const isModal = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isModal()) !== null && _b !== void 0 ? _b : null; + const isModal = getWindowById(id)?.isModal() ?? null; electronSocket.emit('browserWindow-isModal-completed' + id, isModal); }); socket.on('browserWindowMaximize', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.maximize(); + getWindowById(id)?.maximize(); }); socket.on('browserWindowUnmaximize', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.unmaximize(); + getWindowById(id)?.unmaximize(); }); socket.on('browserWindowIsMaximized', (id) => { - var _a, _b; - const isMaximized = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isMaximized()) !== null && _b !== void 0 ? _b : null; + const isMaximized = getWindowById(id)?.isMaximized() ?? null; electronSocket.emit('browserWindow-isMaximized-completed' + id, isMaximized); }); socket.on('browserWindowMinimize', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.minimize(); + getWindowById(id)?.minimize(); }); socket.on('browserWindowRestore', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.restore(); + getWindowById(id)?.restore(); }); socket.on('browserWindowIsMinimized', (id) => { - var _a, _b; - const isMinimized = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isMinimized()) !== null && _b !== void 0 ? _b : null; + const isMinimized = getWindowById(id)?.isMinimized() ?? null; electronSocket.emit('browserWindow-isMinimized-completed' + id, isMinimized); }); socket.on('browserWindowSetFullScreen', (id, fullscreen) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setFullScreen(fullscreen); + getWindowById(id)?.setFullScreen(fullscreen); + }); + socket.on('browserWindowSetBackgroundColor', (id, color) => { + getWindowById(id)?.setBackgroundColor(color); }); socket.on('browserWindowIsFullScreen', (id) => { - var _a, _b; - const isFullScreen = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isFullScreen()) !== null && _b !== void 0 ? _b : null; + const isFullScreen = getWindowById(id)?.isFullScreen() ?? null; electronSocket.emit('browserWindow-isFullScreen-completed' + id, isFullScreen); }); socket.on('browserWindowSetAspectRatio', (id, aspectRatio, extraSize) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setAspectRatio(aspectRatio, extraSize); + getWindowById(id)?.setAspectRatio(aspectRatio, extraSize); }); socket.on('browserWindowPreviewFile', (id, path, displayname) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.previewFile(path, displayname); + getWindowById(id)?.previewFile(path, displayname); }); socket.on('browserWindowCloseFilePreview', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.closeFilePreview(); + getWindowById(id)?.closeFilePreview(); }); socket.on('browserWindowSetBounds', (id, bounds, animate) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setBounds(bounds, animate); + getWindowById(id)?.setBounds(bounds, animate); }); socket.on('browserWindowGetBounds', (id) => { - var _a, _b; - const rectangle = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.getBounds()) !== null && _b !== void 0 ? _b : null; + const rectangle = getWindowById(id)?.getBounds() ?? null; electronSocket.emit('browserWindow-getBounds-completed' + id, rectangle); }); socket.on('browserWindowSetContentBounds', (id, bounds, animate) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setContentBounds(bounds, animate); + getWindowById(id)?.setContentBounds(bounds, animate); }); socket.on('browserWindowGetContentBounds', (id) => { - var _a, _b; - const rectangle = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.getContentBounds()) !== null && _b !== void 0 ? _b : null; + const rectangle = getWindowById(id)?.getContentBounds() ?? null; electronSocket.emit('browserWindow-getContentBounds-completed' + id, rectangle); }); socket.on('browserWindowSetSize', (id, width, height, animate) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setSize(width, height, animate); + getWindowById(id)?.setSize(width, height, animate); }); socket.on('browserWindowGetSize', (id) => { - var _a, _b; - const size = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.getSize()) !== null && _b !== void 0 ? _b : null; + const size = getWindowById(id)?.getSize() ?? null; electronSocket.emit('browserWindow-getSize-completed' + id, size); }); socket.on('browserWindowSetContentSize', (id, width, height, animate) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setContentSize(width, height, animate); + getWindowById(id)?.setContentSize(width, height, animate); }); socket.on('browserWindowGetContentSize', (id) => { - var _a, _b; - const size = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.getContentSize()) !== null && _b !== void 0 ? _b : null; + const size = getWindowById(id)?.getContentSize() ?? null; electronSocket.emit('browserWindow-getContentSize-completed' + id, size); }); socket.on('browserWindowSetMinimumSize', (id, width, height) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setMinimumSize(width, height); + getWindowById(id)?.setMinimumSize(width, height); }); socket.on('browserWindowGetMinimumSize', (id) => { - var _a, _b; - const size = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.getMinimumSize()) !== null && _b !== void 0 ? _b : null; + const size = getWindowById(id)?.getMinimumSize() ?? null; electronSocket.emit('browserWindow-getMinimumSize-completed' + id, size); }); socket.on('browserWindowSetMaximumSize', (id, width, height) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setMaximumSize(width, height); + getWindowById(id)?.setMaximumSize(width, height); }); socket.on('browserWindowGetMaximumSize', (id) => { - var _a, _b; - const size = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.getMaximumSize()) !== null && _b !== void 0 ? _b : null; + const size = getWindowById(id)?.getMaximumSize() ?? null; electronSocket.emit('browserWindow-getMaximumSize-completed' + id, size); }); socket.on('browserWindowSetResizable', (id, resizable) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setResizable(resizable); + getWindowById(id)?.setResizable(resizable); }); socket.on('browserWindowIsResizable', (id) => { - var _a, _b; - const resizable = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isResizable()) !== null && _b !== void 0 ? _b : null; + const resizable = getWindowById(id)?.isResizable() ?? null; electronSocket.emit('browserWindow-isResizable-completed' + id, resizable); }); socket.on('browserWindowSetMovable', (id, movable) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setMovable(movable); + getWindowById(id)?.setMovable(movable); }); socket.on('browserWindowIsMovable', (id) => { - var _a, _b; - const movable = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isMovable()) !== null && _b !== void 0 ? _b : null; + const movable = getWindowById(id)?.isMovable() ?? null; electronSocket.emit('browserWindow-isMovable-completed' + id, movable); }); socket.on('browserWindowSetMinimizable', (id, minimizable) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setMinimizable(minimizable); + getWindowById(id)?.setMinimizable(minimizable); }); socket.on('browserWindowIsMinimizable', (id) => { - var _a, _b; - const minimizable = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isMinimizable()) !== null && _b !== void 0 ? _b : null; + const minimizable = getWindowById(id)?.isMinimizable() ?? null; electronSocket.emit('browserWindow-isMinimizable-completed' + id, minimizable); }); socket.on('browserWindowSetMaximizable', (id, maximizable) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setMaximizable(maximizable); + getWindowById(id)?.setMaximizable(maximizable); }); socket.on('browserWindowIsMaximizable', (id) => { - var _a, _b; - const maximizable = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isMaximizable()) !== null && _b !== void 0 ? _b : null; + const maximizable = getWindowById(id)?.isMaximizable() ?? null; electronSocket.emit('browserWindow-isMaximizable-completed' + id, maximizable); }); socket.on('browserWindowSetFullScreenable', (id, fullscreenable) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setFullScreenable(fullscreenable); + getWindowById(id)?.setFullScreenable(fullscreenable); }); socket.on('browserWindowIsFullScreenable', (id) => { - var _a, _b; - const fullscreenable = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isFullScreenable()) !== null && _b !== void 0 ? _b : null; + const fullscreenable = getWindowById(id)?.isFullScreenable() ?? null; electronSocket.emit('browserWindow-isFullScreenable-completed' + id, fullscreenable); }); socket.on('browserWindowSetClosable', (id, closable) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setClosable(closable); + getWindowById(id)?.setClosable(closable); }); socket.on('browserWindowIsClosable', (id) => { - var _a, _b; - const closable = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isClosable()) !== null && _b !== void 0 ? _b : null; + const closable = getWindowById(id)?.isClosable() ?? null; electronSocket.emit('browserWindow-isClosable-completed' + id, closable); }); socket.on('browserWindowSetAlwaysOnTop', (id, flag, level, relativeLevel) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setAlwaysOnTop(flag, level, relativeLevel); + getWindowById(id)?.setAlwaysOnTop(flag, level, relativeLevel); }); socket.on('browserWindowIsAlwaysOnTop', (id) => { - var _a, _b; - const isAlwaysOnTop = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isAlwaysOnTop()) !== null && _b !== void 0 ? _b : null; + const isAlwaysOnTop = getWindowById(id)?.isAlwaysOnTop() ?? null; electronSocket.emit('browserWindow-isAlwaysOnTop-completed' + id, isAlwaysOnTop); }); socket.on('browserWindowCenter', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.center(); + getWindowById(id)?.center(); }); socket.on('browserWindowSetPosition', (id, x, y, animate) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setPosition(x, y, animate); + getWindowById(id)?.setPosition(x, y, animate); }); socket.on('browserWindowGetPosition', (id) => { - var _a, _b; - const position = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.getPosition()) !== null && _b !== void 0 ? _b : null; + const position = getWindowById(id)?.getPosition() ?? null; electronSocket.emit('browserWindow-getPosition-completed' + id, position); }); socket.on('browserWindowSetTitle', (id, title) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setTitle(title); + getWindowById(id)?.setTitle(title); }); socket.on('browserWindowGetTitle', (id) => { - var _a, _b; - const title = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.getTitle()) !== null && _b !== void 0 ? _b : null; + const title = getWindowById(id)?.getTitle() ?? null; electronSocket.emit('browserWindow-getTitle-completed' + id, title); }); socket.on('browserWindowSetTitle', (id, title) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setTitle(title); + getWindowById(id)?.setTitle(title); }); socket.on('browserWindowSetSheetOffset', (id, offsetY, offsetX) => { - var _a, _b; if (offsetX) { - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setSheetOffset(offsetY, offsetX); + getWindowById(id)?.setSheetOffset(offsetY, offsetX); } else { - (_b = getWindowById(id)) === null || _b === void 0 ? void 0 : _b.setSheetOffset(offsetY); + getWindowById(id)?.setSheetOffset(offsetY); } }); socket.on('browserWindowFlashFrame', (id, flag) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.flashFrame(flag); + getWindowById(id)?.flashFrame(flag); }); socket.on('browserWindowSetSkipTaskbar', (id, skip) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setSkipTaskbar(skip); + getWindowById(id)?.setSkipTaskbar(skip); }); socket.on('browserWindowSetKiosk', (id, flag) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setKiosk(flag); + getWindowById(id)?.setKiosk(flag); }); socket.on('browserWindowIsKiosk', (id) => { - var _a, _b; - const isKiosk = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isKiosk()) !== null && _b !== void 0 ? _b : null; + const isKiosk = getWindowById(id)?.isKiosk() ?? null; electronSocket.emit('browserWindow-isKiosk-completed' + id, isKiosk); }); socket.on('browserWindowGetNativeWindowHandle', (id) => { - var _a, _b, _c, _d; - const nativeWindowHandle = (_d = (_c = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.getNativeWindowHandle()) === null || _b === void 0 ? void 0 : _b.readInt32LE(0)) === null || _c === void 0 ? void 0 : _c.toString(16)) !== null && _d !== void 0 ? _d : null; + const nativeWindowHandle = getWindowById(id)?.getNativeWindowHandle()?.readInt32LE(0)?.toString(16) ?? null; electronSocket.emit('browserWindow-getNativeWindowHandle-completed' + id, nativeWindowHandle); }); socket.on('browserWindowSetRepresentedFilename', (id, filename) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setRepresentedFilename(filename); + getWindowById(id)?.setRepresentedFilename(filename); }); socket.on('browserWindowGetRepresentedFilename', (id) => { - var _a, _b; - const pathname = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.getRepresentedFilename()) !== null && _b !== void 0 ? _b : null; + const pathname = getWindowById(id)?.getRepresentedFilename() ?? null; electronSocket.emit('browserWindow-getRepresentedFilename-completed' + id, pathname); }); socket.on('browserWindowSetDocumentEdited', (id, edited) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setDocumentEdited(edited); + getWindowById(id)?.setDocumentEdited(edited); }); socket.on('browserWindowIsDocumentEdited', (id) => { - var _a, _b; - const edited = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isDocumentEdited()) !== null && _b !== void 0 ? _b : null; + const edited = getWindowById(id)?.isDocumentEdited() ?? null; electronSocket.emit('browserWindow-isDocumentEdited-completed' + id, edited); }); socket.on('browserWindowFocusOnWebView', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.focusOnWebView(); + getWindowById(id)?.focusOnWebView(); }); socket.on('browserWindowBlurWebView', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.blurWebView(); + getWindowById(id)?.blurWebView(); }); socket.on('browserWindowLoadURL', (id, url, options) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.loadURL(url, options); + getWindowById(id)?.loadURL(url, options); }); socket.on('browserWindowReload', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.reload(); + getWindowById(id)?.reload(); }); socket.on('browserWindowSetMenu', (id, menuItems) => { - var _a; let menu = null; if (menuItems) { menu = electron_1.Menu.buildFromTemplate(menuItems); @@ -601,11 +534,10 @@ module.exports = (socket, app) => { electronSocket.emit('windowMenuItemClicked', id); }); } - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setMenu(menu); + getWindowById(id)?.setMenu(menu); }); socket.on('browserWindowRemoveMenu', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.removeMenu(); + getWindowById(id)?.removeMenu(); }); function addMenuItemClickConnector(menuItems, callback) { menuItems.forEach((item) => { @@ -613,29 +545,26 @@ 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); + }; } }); } socket.on('browserWindowSetProgressBar', (id, progress) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setProgressBar(progress); + getWindowById(id)?.setProgressBar(progress); }); socket.on('browserWindowSetProgressBar', (id, progress, options) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setProgressBar(progress, options); + getWindowById(id)?.setProgressBar(progress, options); }); socket.on('browserWindowSetHasShadow', (id, hasShadow) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setHasShadow(hasShadow); + getWindowById(id)?.setHasShadow(hasShadow); }); socket.on('browserWindowHasShadow', (id) => { - var _a, _b; - const hasShadow = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.hasShadow()) !== null && _b !== void 0 ? _b : null; + const hasShadow = getWindowById(id)?.hasShadow() ?? null; electronSocket.emit('browserWindow-hasShadow-completed' + id, hasShadow); }); socket.on('browserWindowSetThumbarButtons', (id, thumbarButtons) => { - var _a, _b; thumbarButtons.forEach(thumbarButton => { const imagePath = path.join(__dirname.replace('api', ''), 'bin', thumbarButton.icon.toString()); thumbarButton.icon = electron_1.nativeImage.createFromPath(imagePath); @@ -643,77 +572,64 @@ module.exports = (socket, app) => { electronSocket.emit('thumbarButtonClicked', thumbarButton['id']); }; }); - const success = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setThumbarButtons(thumbarButtons)) !== null && _b !== void 0 ? _b : null; + const success = getWindowById(id)?.setThumbarButtons(thumbarButtons) ?? null; electronSocket.emit('browserWindowSetThumbarButtons-completed' + id, success); }); socket.on('browserWindowSetThumbnailClip', (id, rectangle) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setThumbnailClip(rectangle); + getWindowById(id)?.setThumbnailClip(rectangle); }); socket.on('browserWindowSetThumbnailToolTip', (id, toolTip) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setThumbnailToolTip(toolTip); + getWindowById(id)?.setThumbnailToolTip(toolTip); }); socket.on('browserWindowSetAppDetails', (id, options) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setAppDetails(options); + getWindowById(id)?.setAppDetails(options); + }); + socket.on('browserWindowSetTitleBarOverlay', (id, options) => { + getWindowById(id)?.setTitleBarOverlay(options); }); socket.on('browserWindowShowDefinitionForSelection', (id) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.showDefinitionForSelection(); + getWindowById(id)?.showDefinitionForSelection(); }); socket.on('browserWindowSetAutoHideMenuBar', (id, hide) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setAutoHideMenuBar(hide); + getWindowById(id)?.setAutoHideMenuBar(hide); }); socket.on('browserWindowIsMenuBarAutoHide', (id) => { - var _a, _b; - const isMenuBarAutoHide = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isMenuBarAutoHide()) !== null && _b !== void 0 ? _b : null; + const isMenuBarAutoHide = getWindowById(id)?.isMenuBarAutoHide() ?? null; electronSocket.emit('browserWindow-isMenuBarAutoHide-completed' + id, isMenuBarAutoHide); }); socket.on('browserWindowSetMenuBarVisibility', (id, visible) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setMenuBarVisibility(visible); + getWindowById(id)?.setMenuBarVisibility(visible); }); socket.on('browserWindowIsMenuBarVisible', (id) => { - var _a, _b; - const isMenuBarVisible = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isMenuBarVisible()) !== null && _b !== void 0 ? _b : null; + const isMenuBarVisible = getWindowById(id)?.isMenuBarVisible() ?? null; electronSocket.emit('browserWindow-isMenuBarVisible-completed' + id, isMenuBarVisible); }); socket.on('browserWindowSetVisibleOnAllWorkspaces', (id, visible) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setVisibleOnAllWorkspaces(visible); + getWindowById(id)?.setVisibleOnAllWorkspaces(visible); }); socket.on('browserWindowIsVisibleOnAllWorkspaces', (id) => { - var _a, _b; - const isVisibleOnAllWorkspaces = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.isVisibleOnAllWorkspaces()) !== null && _b !== void 0 ? _b : null; + const isVisibleOnAllWorkspaces = getWindowById(id)?.isVisibleOnAllWorkspaces() ?? null; electronSocket.emit('browserWindow-isVisibleOnAllWorkspaces-completed' + id, isVisibleOnAllWorkspaces); }); socket.on('browserWindowSetIgnoreMouseEvents', (id, ignore) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setIgnoreMouseEvents(ignore); + getWindowById(id)?.setIgnoreMouseEvents(ignore); }); socket.on('browserWindowSetContentProtection', (id, enable) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setContentProtection(enable); + getWindowById(id)?.setContentProtection(enable); }); socket.on('browserWindowSetFocusable', (id, focusable) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setFocusable(focusable); + getWindowById(id)?.setFocusable(focusable); }); socket.on('browserWindowSetParentWindow', (id, parent) => { - var _a; const browserWindow = electron_1.BrowserWindow.fromId(parent.id); - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setParentWindow(browserWindow); + getWindowById(id)?.setParentWindow(browserWindow); }); socket.on('browserWindowGetParentWindow', (id) => { - var _a, _b; - const browserWindow = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.getParentWindow()) !== null && _b !== void 0 ? _b : null; + const browserWindow = getWindowById(id)?.getParentWindow() ?? null; electronSocket.emit('browserWindow-getParentWindow-completed' + id, browserWindow.id); }); socket.on('browserWindowGetChildWindows', (id) => { - var _a, _b; - const browserWindows = (_b = (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.getChildWindows()) !== null && _b !== void 0 ? _b : null; + const browserWindows = getWindowById(id)?.getChildWindows() ?? null; const ids = []; browserWindows.forEach(x => { ids.push(x.id); @@ -721,22 +637,31 @@ module.exports = (socket, app) => { electronSocket.emit('browserWindow-getChildWindows-completed' + id, ids); }); socket.on('browserWindowSetAutoHideCursor', (id, autoHide) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setAutoHideCursor(autoHide); + getWindowById(id)?.setAutoHideCursor(autoHide); }); socket.on('browserWindowSetVibrancy', (id, type) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setVibrancy(type); + getWindowById(id)?.setVibrancy(type); + }); + socket.on('browserWindowSetExcludedFromShownWindowsMenu', (id) => { + const w = getWindowById(id); + if (w) { + w.excludedFromShownWindowsMenu = true; + } }); socket.on('browserWindow-setBrowserView', (id, browserViewId) => { - var _a; - (_a = getWindowById(id)) === null || _a === void 0 ? void 0 : _a.setBrowserView((0, 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 b902101..b93e551 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 f223491..de42c2b 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 * as path from 'path'; +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[]; -const readyToShowWindowsIds: number[] = (global['readyToShowWindowsIds'] = global['readyToShowWindowsIds'] || []) as number[]; +let readyToShowWindowsIds: number[] = []; +let window, electronSocket; +let mainWindowURL; const proxyToCredentialsMap: { [proxy: string]: string } = (global['proxyToCredentialsMap'] = global['proxyToCredentialsMap'] || []) as { [proxy: string]: string }; -let window: Electron.BrowserWindow, lastOptions:Electron.BrowserWindowConstructorOptions, electronSocket: Socket; - -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) { - const proxy = `${authInfo.host}:${authInfo.port}` - if (proxy in proxyToCredentialsMap && proxyToCredentialsMap[proxy].split(':').length === 2) { - event.preventDefault() - const user = proxyToCredentialsMap[proxy].split(':')[0] - const 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) => { const index = readyToShowWindowsIds.indexOf(id); @@ -210,11 +213,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; } if (options.parent) { @@ -226,10 +241,8 @@ export = (socket: Socket, app: Electron.App) => { window = app['mainWindow']; if (window) { window.reload(); - if (windows.findIndex(i => i.id == window.id) == -1){ - windows.push(window); - } - electronSocket.emit('BrowserWindowCreated', window.id); + windows.push(window); + electronSocket.emit('BrowserWindowCreated' + guid, window.id); return; } } else { @@ -245,41 +258,39 @@ export = (socket: Socket, app: Electron.App) => { if (options.proxy && options.proxyCredentials) { proxyToCredentialsMap[options.proxy] = options.proxyCredentials; } - thisWindow.on('ready-to-show', () => { - const index = readyToShowWindowsIds.indexOf(thisWindow.id); - if (index > -1) { - readyToShowWindowsIds.splice(index, 1); + + 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 { readyToShowWindowsIds.push(thisWindow.id); } }); - lastOptions = options; - - thisWindow.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); + window.on('closed', (sender) => { + 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; + } } } - } - }); - - // this seems dangerous to assume - 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) { @@ -298,14 +309,32 @@ export = (socket: Socket, app: Electron.App) => { app['mainWindow'] = thisWindow; } - windows.push(thisWindow); - electronSocket.emit('BrowserWindowCreated', thisWindow.id); + windows.push(window); + 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(); }); @@ -388,6 +417,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; @@ -656,7 +689,9 @@ export = (socket: Socket, app: Electron.App) => { } if ('id' in item && item.id) { - item.click = () => { callback(item.id); }; + item.click = () => { + callback(item.id); + }; } }); } @@ -704,6 +739,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(); }); @@ -782,6 +821,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)); }); @@ -789,8 +835,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 9ff8751..76c599b 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,14 +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(); - for (const key in dataContent) { + // tslint:disable-next-line: forin + 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 43394eb..b298143 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 645bd43..19db075 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,25 +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); + }); - for (const key in dataContent) { + function deserializeImage(data) { + const image = nativeImage.createEmpty(); + // tslint:disable-next-line: forin + 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 7d84909..e4c907f 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 f206b93..475ac08 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 0000000..fb2fbbb --- /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 0000000..9be8fa7 --- /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 0000000..dd28600 --- /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 5234bcb..de8458c 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 e40802d..c58b9e1 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,EAAE,QAAQ,EAAE,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,qBAAqB,CAAC,eAAe,EAAE,CAAC,CAAC;SACtJ;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,EAAE,QAAQ,EAAE,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,qBAAqB,CAAC,eAAe,EAAE,CAAC,CAAC;SACpJ;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 095f7b4..0e9d7b1 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, { response: messageBoxReturnValue.response, checked: 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, { response: messageBoxReturnValue.response, checked: 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 7d5010d..ad71fe3 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 449d44b..ddac661 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 bf2b908..c83130c 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.map b/ElectronNET.Host/api/globalShortcut.js.map index 2cab736..ace72a4 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;YACZ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;SACxB;IACL,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;YACZ,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;SACxB;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 bad981f..671247a 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) => { diff --git a/ElectronNET.Host/api/ipc.js b/ElectronNET.Host/api/ipc.js index 4c18ea8..8bcbbea 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 2876296..65679d0 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 801160f..63b1d45 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 28fac07..434c9c3 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 75447e2..e6855cd 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":"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"} \ 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 4385ab0..617b635 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; @@ -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 5f4bfd4..6a5b517 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 16d22cd..6a186a1 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 f6e58d4..cccd0cb 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 50f1a2d..32c497d 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 f83530e..ea39668 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 f4c1fd4..e2ad6f9 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 d522a8b..ec9310c 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,23 @@ 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 2fc6f62..54ac264 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,EAAE,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,CAAC,CAAC;QAC3H,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":"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"} \ No newline at end of file diff --git a/ElectronNET.Host/api/screen.ts b/ElectronNET.Host/api/screen.ts index 4ee6149..37854f7 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: display, changedMetrics: 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 49882b7..e0f25ab 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,EAAE;QAC5C,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,EAAE;QAC5C,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 3cfb5d3..f3ba69f 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 c653a21..5de0b46 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 6ef1620..a8eb9b0 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 0579319..2acb8fe 100644 --- a/ElectronNET.Host/api/tray.ts +++ b/ElectronNET.Host/api/tray.ts @@ -6,7 +6,7 @@ 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, {eventArgs: (event).__proto__, bounds: bounds }); }); @@ -14,7 +14,7 @@ export = (socket: Socket) => { }); 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 }); }); @@ -22,15 +22,18 @@ export = (socket: Socket) => { }); 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); }); @@ -38,7 +41,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 +49,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 +72,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 +116,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 +128,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 +146,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 5c89946..bab9f03 100644 --- a/ElectronNET.Host/api/webContents.js +++ b/ElectronNET.Host/api/webContents.js @@ -1,7 +1,7 @@ "use strict"; const electron_1 = require("electron"); const browserView_1 = require("./browserView"); -const fs = require("fs"); +const fs = require('fs'); let electronSocket; module.exports = (socket) => { electronSocket = socket; @@ -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) => { diff --git a/ElectronNET.Host/api/webContents.js.map b/ElectronNET.Host/api/webContents.js.map index 53d0e3e..57e62b4 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":";AACA,uCAAsD;AACtD,+CAA0D;AAC1D,yBAAyB;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,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QACxH,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,EAAE,eAAe,EAAE,eAAe,EAAE,CAAC,CAAC;QAEpH,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 +{"version":3,"file":"webContents.js","sourceRoot":"","sources":["webContents.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/ElectronNET.Host/api/webContents.ts b/ElectronNET.Host/api/webContents.ts index 1e17866..f66fe5a 100644 --- a/ElectronNET.Host/api/webContents.ts +++ b/ElectronNET.Host/api/webContents.ts @@ -1,7 +1,8 @@ -import { Socket } from 'net'; -import { BrowserWindow, BrowserView } from 'electron'; -import { browserViewMediateService } from './browserView'; -import * as fs from 'fs'; +import {Socket} from 'net'; +import {BrowserView, BrowserWindow} from 'electron'; +import {browserViewMediateService} from './browserView'; + +const fs = require('fs'); let electronSocket; export = (socket: Socket) => { @@ -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: cookie, cause: cause, removed: removed }); + electronSocket.emit('webContents-session-cookies-changed' + id, { + cookie: cookie, + cause: cause, + removed: removed + }); }); }); @@ -263,7 +268,7 @@ 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); }); diff --git a/ElectronNET.Host/main.js b/ElectronNET.Host/main.js index 47f1a39..6a9e0dd 100644 --- a/ElectronNET.Host/main.js +++ b/ElectronNET.Host/main.js @@ -1,25 +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 processApi; +let ignoreApiProcessClosed = false; let manifestJsonFileName = 'electron.manifest.json'; let watchable = false; +let development = false; if (app.commandLine.hasSwitch('manifest')) { manifestJsonFileName = app.commandLine.getSwitchValue('manifest'); @@ -29,6 +36,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); @@ -38,6 +49,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) => { @@ -50,31 +65,64 @@ 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('='); + let socket = global['electronsocket']; - if (words.length > 1) { - app.commandLine.appendSwitch(words[0].replace('--', ''), words[1]); - } else { - app.commandLine.appendSwitch(words[0].replace('--', '')); - } + 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 (windows[0].isMinimized()) { + windows[0].restore(); + } + windows[0].focus(); } }); if (!mainInstance) { app.quit(); + return; } } @@ -98,6 +146,13 @@ if (manifestJsonFile.hasOwnProperty('domainNamesToIgnoreCertificateErrors')) { }) } } +//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', () => { @@ -111,16 +166,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) => { @@ -149,10 +215,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); } @@ -181,12 +254,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; @@ -205,14 +279,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); } @@ -222,30 +320,50 @@ 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); + + //Give the server 60 seconds to reconnect, otherwise exits + checkReconnectTimeout = setTimeout((_) => { + if (!isConnected) { + app.exit(57005); //0xDEAD + } + }, 60000); + }); + socket.on("auth", function (authKey) { + if (authKey != auth) { + throw new Error("Invalid auth key"); + } + + //We only hook to events on app on the first initialization of each component + let firstTime = (global['electronsocket'] == undefined); - if (global['electronsocket'] === undefined) { global['electronsocket'] = socket; - global['electronsocket'].setMaxListeners(0); - } + socket.setMaxListeners(0); - console.log('ASP.NET Core Application connected...', 'global.electronsocket', global['electronsocket'].id, new Date()); + try { console.log('.NET connected on socket ' + socket.id + ' on ' + new Date()); } catch { } if (appApi === undefined) appApi = require('./api/app')(socket, app); if (browserWindows === undefined) browserWindows = require('./api/browserWindows')(socket, app); @@ -267,53 +385,61 @@ function startSocketApiBridge(port) { if (dock === undefined) dock = require('./api/dock')(socket); if (processApi === undefined) processApi = require('./api/process')(socket); - socket.on('register-app-open-file-event', (id) => { - global['electronsocket'] = socket; - - app.on('open-file', (event, file) => { - event.preventDefault(); - - global['electronsocket'].emit('app-open-file' + id, file); + 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; + + app.on('open-url', (event, url) => { + event.preventDefault(); + global['electronsocket'].emit('app-open-url' + id, url); + }); + + if (launchUrl) { + socket.emit('app-open-url' + id, launchUrl); + } + }); + + socket.on('console-stdout', (data) => { + try { console.log(`stdout: ${data.toString()}`); } catch { } + }); + + 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(); + } + } catch (error) { + try { console.error(error.message); } catch { } } }); - - socket.on('console-stdout', (data) => { - console.log(`stdout: ${data.toString()}`); - }); - - socket.on('console-stderr', (data) => { - console.log(`stderr: ${data.toString()}`); - }); - - 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(); - } - } catch (error) { - console.error(error.message); - } }); } @@ -336,7 +462,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; @@ -352,15 +478,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) => { @@ -373,15 +505,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(); } @@ -402,7 +546,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}`]; @@ -416,9 +560,15 @@ function startAspCoreBackendWithWatch(electronPort) { } } - var options = { cwd: currentBinPath, env: process.env, detached: detachedProcess, stdio: stdioopt }; + let env = process.env; - apiProcess = cProcess('dotnet', parameters, options); + if (manifestJsonFile.hasOwnProperty('variables')) { + env = { ...env, ...manifestJsonFile.variables }; + } + + var options = { cwd: currentBinPath, env: env, detached: detachedProcess, stdio: stdioopt }; + + apiProcess = cProcess.spawn('dotnet', parameters, options); if (!detachedProcess) { apiProcess.stdout.on('data', (data) => { @@ -431,11 +581,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) { @@ -468,3 +631,83 @@ function shouldIgnoreCertificateForUrl(url) { return false; } + +//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 deleted file mode 100644 index 7af0992..0000000 --- a/ElectronNET.Host/package-lock.json +++ /dev/null @@ -1,4591 +0,0 @@ -{ - "name": "electron.net.host", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "electron.net.host", - "version": "1.0.0", - "license": "MIT", - "dependencies": { - "dasherize": "^2.0.0", - "electron-updater": "^4.6.5", - "image-size": "^1.0.0", - "portscanner": "^2.2.0", - "socket.io": "^4.4.1" - }, - "devDependencies": { - "@typescript-eslint/eslint-plugin": "^5.18.0", - "@typescript-eslint/parser": "^5.18.0", - "electron": "^18.0.2", - "eslint": "^8.12.0", - "typescript": "^4.6.3" - } - }, - "node_modules/@electron/get": { - "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, - "dependencies": { - "debug": "^4.1.1", - "env-paths": "^2.2.0", - "fs-extra": "^8.1.0", - "got": "^9.6.0", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" - }, - "engines": { - "node": ">=8.6" - }, - "optionalDependencies": { - "global-agent": "^3.0.0", - "global-tunnel-ng": "^2.7.1" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", - "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.1", - "globals": "^13.9.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/@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==", - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/@szmarczak/http-timer": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "dependencies": { - "defer-to-connect": "^1.0.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@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==" - }, - "node_modules/@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==" - }, - "node_modules/@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==" - }, - "node_modules/@types/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "node_modules/@types/node": { - "version": "16.11.26", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.26.tgz", - "integrity": "sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==" - }, - "node_modules/@types/semver": { - "version": "7.3.9", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.9.tgz", - "integrity": "sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==" - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.18.0.tgz", - "integrity": "sha512-tzrmdGMJI/uii9/V6lurMo4/o+dMTKDH82LkNjhJ3adCW22YQydoRs5MwTiqxGF9CSYxPxQ7EYb4jLNlIs+E+A==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.18.0", - "@typescript-eslint/type-utils": "5.18.0", - "@typescript-eslint/utils": "5.18.0", - "debug": "^4.3.2", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.2.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", - "dev": true, - "dependencies": { - "lru-cache": "^7.4.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.18.0.tgz", - "integrity": "sha512-+08nYfurBzSSPndngnHvFw/fniWYJ5ymOrn/63oMIbgomVQOvIDhBoJmYZ9lwQOCnQV9xHGvf88ze3jFGUYooQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.18.0", - "@typescript-eslint/types": "5.18.0", - "@typescript-eslint/typescript-estree": "5.18.0", - "debug": "^4.3.2" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.18.0.tgz", - "integrity": "sha512-C0CZML6NyRDj+ZbMqh9FnPscg2PrzSaVQg3IpTmpe0NURMVBXlghGZgMYqBw07YW73i0MCqSDqv2SbywnCS8jQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.18.0", - "@typescript-eslint/visitor-keys": "5.18.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.18.0.tgz", - "integrity": "sha512-vcn9/6J5D6jtHxpEJrgK8FhaM8r6J1/ZiNu70ZUJN554Y3D9t3iovi6u7JF8l/e7FcBIxeuTEidZDR70UuCIfA==", - "dev": true, - "dependencies": { - "@typescript-eslint/utils": "5.18.0", - "debug": "^4.3.2", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.18.0.tgz", - "integrity": "sha512-bhV1+XjM+9bHMTmXi46p1Led5NP6iqQcsOxgx7fvk6gGiV48c6IynY0apQb7693twJDsXiVzNXTflhplmaiJaw==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.18.0.tgz", - "integrity": "sha512-wa+2VAhOPpZs1bVij9e5gyVu60ReMi/KuOx4LKjGx2Y3XTNUDJgQ+5f77D49pHtqef/klglf+mibuHs9TrPxdQ==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.18.0", - "@typescript-eslint/visitor-keys": "5.18.0", - "debug": "^4.3.2", - "globby": "^11.0.4", - "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", - "dev": true, - "dependencies": { - "lru-cache": "^7.4.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.18.0.tgz", - "integrity": "sha512-+hFGWUMMri7OFY26TsOlGa+zgjEy1ssEipxpLjtl4wSll8zy85x0GrUSju/FHdKfVorZPYJLkF3I4XPtnCTewA==", - "dev": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.18.0", - "@typescript-eslint/types": "5.18.0", - "@typescript-eslint/typescript-estree": "5.18.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.18.0.tgz", - "integrity": "sha512-Hf+t+dJsjAKpKSkg3EHvbtEpFFb/1CiOHnvI8bjHgOD4/wAw3gKrA0i94LrbekypiZVanJu3McWJg7rWDMzRTg==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.18.0", - "eslint-visitor-keys": "^3.0.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/accepts": { - "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==", - "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "engines": { - "node": "^4.5.0 || >= 5.9" - } - }, - "node_modules/boolean": { - "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 - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "dependencies": { - "fill-range": "^7.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/buffer-from": { - "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 - }, - "node_modules/builder-util-runtime": { - "version": "8.9.2", - "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-8.9.2.tgz", - "integrity": "sha512-rhuKm5vh7E0aAmT6i8aoSfEjxzdYEFX7zDApK+eNgOhjofnWb74d9SRJv0H/8nsgOkos0TZ4zxW0P8J4N7xQ2A==", - "dependencies": { - "debug": "^4.3.2", - "sax": "^1.2.4" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/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==" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "node_modules/concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "engines": [ - "node >= 0.8" - ], - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "optional": true, - "dependencies": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", - "dev": true - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", - "dependencies": { - "object-assign": "^4", - "vary": "^1" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/dasherize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz", - "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg=" - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "dev": true - }, - "node_modules/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==", - "dev": true, - "optional": true, - "dependencies": { - "object-keys": "^1.0.12" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, - "optional": true - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "node_modules/electron": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/electron/-/electron-18.0.2.tgz", - "integrity": "sha512-7bFKptQDCQBMjjTJEXs0p0KiZPoY28fzq4GnYGorQt4NZJ0TAog8L0NxEkuSJHuIWC/siOUTX0C1H1tWO6KPKQ==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@electron/get": "^1.13.0", - "@types/node": "^16.11.26", - "extract-zip": "^1.0.3" - }, - "bin": { - "electron": "cli.js" - }, - "engines": { - "node": ">= 8.6" - } - }, - "node_modules/electron-updater": { - "version": "4.6.5", - "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-4.6.5.tgz", - "integrity": "sha512-kdTly8O9mSZfm9fslc1mnCY+mYOeaYRy7ERa2Fed240u01BKll3aiupzkd07qKw69KvhBSzuHroIW3mF0D8DWA==", - "dependencies": { - "@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.5", - "lodash.escaperegexp": "^4.1.2", - "lodash.isequal": "^4.5.0", - "semver": "^7.3.5" - } - }, - "node_modules/electron-updater/node_modules/fs-extra": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", - "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/electron-updater/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/electron-updater/node_modules/semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", - "dependencies": { - "lru-cache": "^7.4.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/electron-updater/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/engine.io": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.1.3.tgz", - "integrity": "sha512-rqs60YwkvWTLLnfazqgZqLa/aKo+9cueVfEi/dZ8PyGyaf8TLOxj++4QMIgeG3Gn0AhrWiFXvghsoY9L9h25GA==", - "dependencies": { - "@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", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/engine.io-parser": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", - "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", - "dependencies": { - "@socket.io/base64-arraybuffer": "~1.0.2" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "optional": true - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.12.0.tgz", - "integrity": "sha512-it1oBL9alZg1S8UycLm5YDMAkIhtH6FtAzuZs6YvoGVldWjbS08BkAdb/ymP9LlAyq8koANu32U7Ib/w+UNh8Q==", - "dev": true, - "dependencies": { - "@eslint/eslintrc": "^1.2.1", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^2.0.0" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - }, - "peerDependencies": { - "eslint": ">=5" - } - }, - "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/espree": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", - "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", - "dev": true, - "dependencies": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/extract-zip": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", - "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", - "dev": true, - "dependencies": { - "concat-stream": "^1.6.2", - "debug": "^2.6.9", - "mkdirp": "^0.5.4", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - } - }, - "node_modules/extract-zip/node_modules/debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/extract-zip/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "node_modules/fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "node_modules/get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/global-agent": { - "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, - "dependencies": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "engines": { - "node": ">=10.0" - } - }, - "node_modules/global-agent/node_modules/semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", - "dev": true, - "optional": true, - "dependencies": { - "lru-cache": "^7.4.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": "^10.0.0 || ^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/global-tunnel-ng": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", - "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", - "dev": true, - "optional": true, - "dependencies": { - "encodeurl": "^1.0.2", - "lodash": "^4.17.10", - "npm-conf": "^1.1.3", - "tunnel": "^0.0.6" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/globals": { - "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globals/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globalthis": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz", - "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==", - "dev": true, - "optional": true, - "dependencies": { - "define-properties": "^1.1.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/image-size": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.1.tgz", - "integrity": "sha512-VAwkvNSNGClRw9mDHhc5Efax8PLlsOGcUTh0T/LIriC8vPA3U5PdqXWqkz406MoYHMKW8Uf9gWr05T/rYB44kQ==", - "dependencies": { - "queue": "6.0.2" - }, - "bin": { - "image-size": "bin/image-size.js" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "optional": true - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-number-like": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", - "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", - "dependencies": { - "lodash.isfinite": "^3.3.2" - } - }, - "node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "dev": true - }, - "node_modules/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=", - "dev": true, - "optional": true - }, - "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.0" - } - }, - "node_modules/lazy-val": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", - "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==" - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "node_modules/lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" - }, - "node_modules/lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" - }, - "node_modules/lodash.isfinite": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", - "integrity": "sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=" - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/lru-cache": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.7.3.tgz", - "integrity": "sha512-WY9wjJNQt9+PZilnLbuFKM+SwDull9+6IAguOrarOMoOHTcJ9GnXSO11+Gw6c7xtDkBkthR57OZMtZKYr+1CEw==", - "engines": { - "node": ">=12" - } - }, - "node_modules/matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, - "optional": true, - "dependencies": { - "escape-string-regexp": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "dependencies": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "dependencies": { - "minimist": "^1.2.6" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/normalize-url": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/npm-conf": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", - "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", - "dev": true, - "optional": true, - "dependencies": { - "config-chain": "^1.1.11", - "pify": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "optional": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "optional": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/portscanner": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz", - "integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==", - "dependencies": { - "async": "^2.6.0", - "is-number-like": "^1.0.3" - }, - "engines": { - "node": ">=0.4", - "npm": ">=1.0.0" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", - "dev": true, - "optional": true - }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "dependencies": { - "inherits": "~2.0.3" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "dependencies": { - "lowercase-keys": "^1.0.0" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, - "optional": true, - "dependencies": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "node_modules/semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", - "dev": true, - "optional": true - }, - "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "optional": true, - "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/socket.io": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.4.1.tgz", - "integrity": "sha512-s04vrBswdQBUmuWJuuNTmXUVJhP0cVky8bBDhdkf8y0Ptsu7fKU2LuLbts9g+pdmAdyMMn8F/9Mf1/wbtUN0fg==", - "dependencies": { - "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" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/socket.io-adapter": { - "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==" - }, - "node_modules/socket.io-parser": { - "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==", - "dependencies": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", - "debug": "~4.3.1" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", - "dev": true, - "optional": true - }, - "node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/sumchecker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", - "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", - "dev": true, - "dependencies": { - "debug": "^4.1.0" - }, - "engines": { - "node": ">= 8.0" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "node_modules/to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.6.11 <=0.7.0 || >=0.7.3" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "optional": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "node_modules/typescript": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", - "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/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=", - "dev": true, - "dependencies": { - "prepend-http": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "node_modules/v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "node_modules/vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "node_modules/ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - } - }, - "dependencies": { - "@electron/get": { - "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": "^3.0.0", - "global-tunnel-ng": "^2.7.1", - "got": "^9.6.0", - "progress": "^2.0.3", - "semver": "^6.2.0", - "sumchecker": "^3.0.1" - } - }, - "@eslint/eslintrc": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.2.1.tgz", - "integrity": "sha512-bxvbYnBPN1Gibwyp6NrpnFzA3YtRL3BBAyEAFVIpNTm2Rn4Vy87GA5M4aSn3InRrlsbX5N0GW7XIx+U4SAEKdQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.3.1", - "globals": "^13.9.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.0.4", - "strip-json-comments": "^3.1.1" - } - }, - "@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - } - }, - "@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - } - }, - "@sindresorhus/is": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", - "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", - "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", - "dev": true, - "requires": { - "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/json-schema": { - "version": "7.0.11", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", - "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==", - "dev": true - }, - "@types/node": { - "version": "16.11.26", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.26.tgz", - "integrity": "sha512-GZ7bu5A6+4DtG7q9GsoHXy3ALcgeIHP4NnL0Vv2wu0uUB/yQex26v0tf6/na1mm0+bS9Uw+0DFex7aaKr2qawQ==" - }, - "@types/semver": { - "version": "7.3.9", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.9.tgz", - "integrity": "sha512-L/TMpyURfBkf+o/526Zb6kd/tchUP3iBDEPjqjb+U2MAJhVRxxrmr2fwpe08E7QsV7YLcpq0tUaQ9O9x97ZIxQ==" - }, - "@typescript-eslint/eslint-plugin": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.18.0.tgz", - "integrity": "sha512-tzrmdGMJI/uii9/V6lurMo4/o+dMTKDH82LkNjhJ3adCW22YQydoRs5MwTiqxGF9CSYxPxQ7EYb4jLNlIs+E+A==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.18.0", - "@typescript-eslint/type-utils": "5.18.0", - "@typescript-eslint/utils": "5.18.0", - "debug": "^4.3.2", - "functional-red-black-tree": "^1.0.1", - "ignore": "^5.1.8", - "regexpp": "^3.2.0", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", - "dev": true, - "requires": { - "lru-cache": "^7.4.0" - } - } - } - }, - "@typescript-eslint/parser": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.18.0.tgz", - "integrity": "sha512-+08nYfurBzSSPndngnHvFw/fniWYJ5ymOrn/63oMIbgomVQOvIDhBoJmYZ9lwQOCnQV9xHGvf88ze3jFGUYooQ==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "5.18.0", - "@typescript-eslint/types": "5.18.0", - "@typescript-eslint/typescript-estree": "5.18.0", - "debug": "^4.3.2" - } - }, - "@typescript-eslint/scope-manager": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.18.0.tgz", - "integrity": "sha512-C0CZML6NyRDj+ZbMqh9FnPscg2PrzSaVQg3IpTmpe0NURMVBXlghGZgMYqBw07YW73i0MCqSDqv2SbywnCS8jQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.18.0", - "@typescript-eslint/visitor-keys": "5.18.0" - } - }, - "@typescript-eslint/type-utils": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.18.0.tgz", - "integrity": "sha512-vcn9/6J5D6jtHxpEJrgK8FhaM8r6J1/ZiNu70ZUJN554Y3D9t3iovi6u7JF8l/e7FcBIxeuTEidZDR70UuCIfA==", - "dev": true, - "requires": { - "@typescript-eslint/utils": "5.18.0", - "debug": "^4.3.2", - "tsutils": "^3.21.0" - } - }, - "@typescript-eslint/types": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.18.0.tgz", - "integrity": "sha512-bhV1+XjM+9bHMTmXi46p1Led5NP6iqQcsOxgx7fvk6gGiV48c6IynY0apQb7693twJDsXiVzNXTflhplmaiJaw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.18.0.tgz", - "integrity": "sha512-wa+2VAhOPpZs1bVij9e5gyVu60ReMi/KuOx4LKjGx2Y3XTNUDJgQ+5f77D49pHtqef/klglf+mibuHs9TrPxdQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.18.0", - "@typescript-eslint/visitor-keys": "5.18.0", - "debug": "^4.3.2", - "globby": "^11.0.4", - "is-glob": "^4.0.3", - "semver": "^7.3.5", - "tsutils": "^3.21.0" - }, - "dependencies": { - "semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", - "dev": true, - "requires": { - "lru-cache": "^7.4.0" - } - } - } - }, - "@typescript-eslint/utils": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.18.0.tgz", - "integrity": "sha512-+hFGWUMMri7OFY26TsOlGa+zgjEy1ssEipxpLjtl4wSll8zy85x0GrUSju/FHdKfVorZPYJLkF3I4XPtnCTewA==", - "dev": true, - "requires": { - "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.18.0", - "@typescript-eslint/types": "5.18.0", - "@typescript-eslint/typescript-estree": "5.18.0", - "eslint-scope": "^5.1.1", - "eslint-utils": "^3.0.0" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.18.0.tgz", - "integrity": "sha512-Hf+t+dJsjAKpKSkg3EHvbtEpFFb/1CiOHnvI8bjHgOD4/wAw3gKrA0i94LrbekypiZVanJu3McWJg7rWDMzRTg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "5.18.0", - "eslint-visitor-keys": "^3.0.0" - } - }, - "accepts": { - "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.34", - "negotiator": "0.6.3" - } - }, - "acorn": { - "version": "8.7.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", - "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", - "dev": true - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "async": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", - "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", - "requires": { - "lodash": "^4.17.14" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" - }, - "boolean": { - "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 - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "dev": true - }, - "buffer-from": { - "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.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" - } - }, - "cacheable-request": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", - "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", - "dev": true, - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^3.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^4.1.0", - "responselike": "^1.0.2" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "clone-response": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", - "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "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==" - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "optional": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "cookie": { - "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.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" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "dasherize": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz", - "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg=" - }, - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "decompress-response": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", - "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", - "dev": true, - "requires": { - "mimic-response": "^1.0.0" - } - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "defer-to-connect": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", - "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", - "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==", - "dev": true, - "optional": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, - "optional": true - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "duplexer3": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", - "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", - "dev": true - }, - "electron": { - "version": "18.0.2", - "resolved": "https://registry.npmjs.org/electron/-/electron-18.0.2.tgz", - "integrity": "sha512-7bFKptQDCQBMjjTJEXs0p0KiZPoY28fzq4GnYGorQt4NZJ0TAog8L0NxEkuSJHuIWC/siOUTX0C1H1tWO6KPKQ==", - "dev": true, - "requires": { - "@electron/get": "^1.13.0", - "@types/node": "^16.11.26", - "extract-zip": "^1.0.3" - } - }, - "electron-updater": { - "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.6", - "builder-util-runtime": "8.9.2", - "fs-extra": "^10.0.0", - "js-yaml": "^4.1.0", - "lazy-val": "^1.0.5", - "lodash.escaperegexp": "^4.1.2", - "lodash.isequal": "^4.5.0", - "semver": "^7.3.5" - }, - "dependencies": { - "fs-extra": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.1.tgz", - "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", - "requires": { - "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==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", - "requires": { - "lru-cache": "^7.4.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" - } - } - }, - "encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", - "dev": true, - "optional": true - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "engine.io": { - "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", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.0.3", - "ws": "~8.2.3" - } - }, - "engine.io-parser": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.3.tgz", - "integrity": "sha512-BtQxwF27XUNnSafQLvDi0dQ8s3i6VgzSoQMJacpIcGNrlUdfHSKbgm3jmjCVvQluGzqwujQMPAoMai3oYSTurg==", - "requires": { - "@socket.io/base64-arraybuffer": "~1.0.2" - } - }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", - "dev": true - }, - "es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "optional": true - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true - }, - "eslint": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.12.0.tgz", - "integrity": "sha512-it1oBL9alZg1S8UycLm5YDMAkIhtH6FtAzuZs6YvoGVldWjbS08BkAdb/ymP9LlAyq8koANu32U7Ib/w+UNh8Q==", - "dev": true, - "requires": { - "@eslint/eslintrc": "^1.2.1", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "dependencies": { - "eslint-scope": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.1.1.tgz", - "integrity": "sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz", - "integrity": "sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA==", - "dev": true - }, - "espree": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.3.1.tgz", - "integrity": "sha512-bvdyLmJMfwkV3NCRl5ZhJf22zBFo1y8bYh3VYb+bfzqNB4Je68P2sSuXyuFquzWLebHpNd2/d5uv7yoP9ISnGQ==", - "dev": true, - "requires": { - "acorn": "^8.7.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^3.3.0" - } - }, - "esquery": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz", - "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "extract-zip": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", - "integrity": "sha512-xoh5G1W/PB0/27lXgMQyIhP5DSY/LhoCsOyZgb+6iMmRtCwVBo55uKaMoEYrDCKQhWvqEip5ZPKAc6eFNyf/MA==", - "dev": true, - "requires": { - "concat-stream": "^1.6.2", - "debug": "^2.6.9", - "mkdirp": "^0.5.4", - "yauzl": "^2.10.0" - }, - "dependencies": { - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - } - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-glob": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.11.tgz", - "integrity": "sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dev": true, - "requires": { - "pend": "~1.2.0" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.5", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.5.tgz", - "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", - "dev": true - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", - "dev": true - }, - "get-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", - "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - }, - "global-agent": { - "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", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "dependencies": { - "semver": { - "version": "7.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.6.tgz", - "integrity": "sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w==", - "dev": true, - "optional": true, - "requires": { - "lru-cache": "^7.4.0" - } - } - } - }, - "global-tunnel-ng": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/global-tunnel-ng/-/global-tunnel-ng-2.7.1.tgz", - "integrity": "sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==", - "dev": true, - "optional": true, - "requires": { - "encodeurl": "^1.0.2", - "lodash": "^4.17.10", - "npm-conf": "^1.1.3", - "tunnel": "^0.0.6" - } - }, - "globals": { - "version": "13.13.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.13.0.tgz", - "integrity": "sha512-EQ7Q18AJlPwp3vUDL4mKA0KXrXyNIQyWon6T6XQiBQF0XHvRsiCSrWmmeATpUzdJN2HhWZU6Pdl0a9zdep5p6A==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - }, - "dependencies": { - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true - } - } - }, - "globalthis": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.2.tgz", - "integrity": "sha512-ZQnSFO1la8P7auIOQECnm0sSuoMeaSq0EEdXMBFF2QJO4uNcwbyhSgG3MruWNbFTqCLmxVwGOl7LZ9kASvHdeQ==", - "dev": true, - "optional": true, - "requires": { - "define-properties": "^1.1.3" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - } - }, - "got": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", - "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", - "dev": true, - "requires": { - "@sindresorhus/is": "^0.14.0", - "@szmarczak/http-timer": "^1.1.2", - "cacheable-request": "^6.0.0", - "decompress-response": "^3.3.0", - "duplexer3": "^0.1.4", - "get-stream": "^4.1.0", - "lowercase-keys": "^1.0.1", - "mimic-response": "^1.0.1", - "p-cancelable": "^1.0.0", - "to-readable-stream": "^1.0.0", - "url-parse-lax": "^3.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "http-cache-semantics": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", - "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", - "dev": true - }, - "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true - }, - "image-size": { - "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" - } - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "optional": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "is-number-like": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", - "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", - "requires": { - "lodash.isfinite": "^3.3.2" - } - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "requires": { - "argparse": "^2.0.1" - } - }, - "json-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", - "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", - "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=", - "dev": true, - "optional": true - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "keyv": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", - "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", - "dev": true, - "requires": { - "json-buffer": "3.0.0" - } - }, - "lazy-val": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", - "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==" - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.escaperegexp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", - "integrity": "sha1-ZHYsSGGAglGKw99Mz11YhtriA0c=" - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" - }, - "lodash.isfinite": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", - "integrity": "sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=" - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lowercase-keys": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", - "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", - "dev": true - }, - "lru-cache": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.7.3.tgz", - "integrity": "sha512-WY9wjJNQt9+PZilnLbuFKM+SwDull9+6IAguOrarOMoOHTcJ9GnXSO11+Gw6c7xtDkBkthR57OZMtZKYr+1CEw==" - }, - "matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, - "optional": true, - "requires": { - "escape-string-regexp": "^4.0.0" - } - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", - "dev": true, - "requires": { - "braces": "^3.0.2", - "picomatch": "^2.3.1" - } - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "requires": { - "mime-db": "1.52.0" - } - }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", - "dev": true - }, - "negotiator": { - "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", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", - "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", - "dev": true - }, - "npm-conf": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/npm-conf/-/npm-conf-1.1.3.tgz", - "integrity": "sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==", - "dev": true, - "optional": true, - "requires": { - "config-chain": "^1.1.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", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "optionator": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", - "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.3" - } - }, - "p-cancelable": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", - "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", - "dev": true - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true - }, - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true, - "optional": true - }, - "portscanner": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz", - "integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==", - "requires": { - "async": "^2.6.0", - "is-number-like": "^1.0.3" - } - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prepend-http": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", - "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true - }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "dev": true - }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=", - "dev": true, - "optional": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true - }, - "queue": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", - "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", - "requires": { - "inherits": "~2.0.3" - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "regexpp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", - "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", - "dev": true - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", - "dev": true, - "requires": { - "lowercase-keys": "^1.0.0" - } - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, - "optional": true, - "requires": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", - "dev": true, - "optional": true - }, - "serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "dev": true, - "optional": true, - "requires": { - "type-fest": "^0.13.1" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "socket.io": { - "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": "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": "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": { - "@types/component-emitter": "^1.2.10", - "component-emitter": "~1.3.0", - "debug": "~4.3.1" - } - }, - "sprintf-js": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", - "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==", - "dev": true, - "optional": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - }, - "sumchecker": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", - "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", - "dev": true, - "requires": { - "debug": "^4.1.0" - } - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true - }, - "to-readable-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", - "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", - "dev": true - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "requires": { - "tslib": "^1.8.1" - } - }, - "tunnel": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz", - "integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==", - "dev": true, - "optional": true - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "optional": true - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "typescript": { - "version": "4.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.3.tgz", - "integrity": "sha512-yNIatDa5iaofVozS/uQJEl3JRWLKKGJKh6Yaiv0GLGSuhpFJe7P3SbHZ8/yjAHRQwKRoA6YZqlfjXWmVzoVSMw==", - "dev": true - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "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=", - "dev": true, - "requires": { - "prepend-http": "^2.0.0" - } - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "v8-compile-cache": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz", - "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==", - "dev": true - }, - "vary": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", - "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "ws": { - "version": "8.2.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", - "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==", - "requires": {} - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dev": true, - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - } - } -} diff --git a/ElectronNET.Host/package.json b/ElectronNET.Host/package.json index b03b280..284fc35 100644 --- a/ElectronNET.Host/package.json +++ b/ElectronNET.Host/package.json @@ -14,15 +14,15 @@ "dependencies": { "dasherize": "^2.0.0", "electron-updater": "^4.6.5", - "image-size": "^1.0.0", + "image-size": "^1.0.1", "portscanner": "^2.2.0", "socket.io": "^4.4.1" }, "devDependencies": { "@typescript-eslint/eslint-plugin": "^5.18.0", "@typescript-eslint/parser": "^5.18.0", - "electron": "^18.0.2", + "electron": "^19.0.9", "eslint": "^8.12.0", - "typescript": "^4.6.3" + "typescript": "^4.7.4" } } diff --git a/ElectronNET.Host/splashscreen/index.html b/ElectronNET.Host/splashscreen/index.html index ddd85e2..bafd72a 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 ea3d493..6454beb 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 f184e14..b7a7bbc 100644 --- a/ElectronNET.WebApp/Controllers/AppSysInformationController.cs +++ b/ElectronNET.WebApp/Controllers/AppSysInformationController.cs @@ -11,28 +11,34 @@ namespace ElectronNET.WebApp.Controllers { 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 a279774..5bb39b0 100644 --- a/ElectronNET.WebApp/Controllers/MenusController.cs +++ b/ElectronNET.WebApp/Controllers/MenusController.cs @@ -70,9 +70,11 @@ namespace ElectronNET.WebApp.Controllers { 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/Program.cs b/ElectronNET.WebApp/Program.cs index 56ad267..77ced2f 100644 --- a/ElectronNET.WebApp/Program.cs +++ b/ElectronNET.WebApp/Program.cs @@ -2,28 +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) { + IWebHostBuilder builder; #if DEBUG - //Uncomment this line to automatically attach the Debugger on launch. This should only be used in development - //Debugger.Launch(); + 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 - CreateWebHostBuilder(args).Build().Run(); + 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 d5111d5..ae9cd85 100644 --- a/ElectronNET.WebApp/Properties/launchSettings.json +++ b/ElectronNET.WebApp/Properties/launchSettings.json @@ -1,10 +1,35 @@ { "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.exe", - "commandLineArgs": "start", + "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" + }, + "run from csharp": { + "commandName": "Project", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "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 ae9b5cc..b317562 100644 --- a/ElectronNET.WebApp/Startup.cs +++ b/ElectronNET.WebApp/Startup.cs @@ -5,6 +5,7 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; +using System.Threading.Tasks; namespace ElectronNET.WebApp { @@ -43,11 +44,11 @@ namespace ElectronNET.WebApp if (HybridSupport.IsElectronActive) { - Electron.App.Ready += () => 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 5e22c04..ca7941b 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 screenshot = document.getElementById('screen-shot');
+    screenshot.addEventListener('click', function (event) {
+        const { desktopCapturer } = require('electron')
 
-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;
-                });
+        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 99f12b4..a0bf79e 100644 --- a/ElectronNET.sln +++ b/ElectronNET.sln @@ -10,7 +10,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\" @@ -41,6 +41,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 @@ -63,6 +65,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/Releaser/Program.cs b/Releaser/Program.cs new file mode 100644 index 0000000..79085b8 --- /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 0000000..fb76edd --- /dev/null +++ b/Releaser/Releaser.csproj @@ -0,0 +1,9 @@ + + + + Exe + net6.0 + enable + + +