diff --git a/Changelog.md b/Changelog.md index 2310a953..a45094a1 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,3 +1,32 @@ +# 0.6.0 + +## ElectronNET.Core + +- Updated dependencies +- Updated `WebContents` zoom level APIs to use `double` instead of `int` (#956) +- Improved migration checks to honor custom output paths and to detect `ProjectGuid` in publish profiles (#946) +- Fixed single instance handling on macOS (#1040) +- Fixed slow socket bridge startup by binding to an explicit loopback address (#1103) +- Fixed socket bridge connection when a system proxy is configured (#1105) +- Fixed electron-builder using the host RID instead of the target RID (#1097) +- Fixed cross-compilation behavior on same platform (#1098) @epsnm +- Fixed resolution of unrelated target (#1099) @epsnm +- Fixed false alarm for `ELECTRON001` on a root `package-lock.json` (#946) +- Added `ElectronNET.Core.Templates` package with a `dotnet new electron-blazor` template (#414) +- Added `WebContents.OnZoomChanged` event (#956) +- Added `WebContents` page loading APIs `LoadFileAsync`, `IsLoadingAsync`, `IsLoadingMainFrameAsync`, `IsWaitingForResponseAsync`, `Reload`, `ReloadIgnoringCache` and `Stop` (#956) +- Added `WebContents.InsertCSSAsync` and `WebContents.RemoveInsertedCSSAsync` for dynamic CSS (#956) +- Added `WebContents` editing and selection APIs (undo, redo, cut, copy, paste, insert text, select, ...) (#956) +- Added `WebContents.FindInPageAsync`, `WebContents.StopFindInPage` and the `OnFoundInPage` event (#956) +- Added `WebContents` audio events `OnAudioStateChanged`, `OnMediaStartedPlaying` and `OnMediaPaused` (#956) +- Added `WebContents.ScrollToTop` and `WebContents.ScrollToBottom` (#956) +- Added target framework customization (#1095) @epsnm +- Added configurable Electron root directory for custom packaging layouts (#1106) @DYH1319 +- Added ability for `custom_main.js` to modify command line switches (#1029) @AeonSake +- Added migration checks for incomplete `ElectronHostHook` folders (`ELECTRON010`, `ELECTRON011`) (#946) +- Added `ElectronExecutableName` to separate the product name from the executable name (#1003) @AeonSake +- Added build extensibility properties `ElectronSkipExecCommands` and `ElectronIntermediatePublishDir` (#1106) @DYH1319 + # 0.5.2 ## ElectronNET.Core diff --git a/Directory.Build.props b/Directory.Build.props index e147d635..3b8d0f51 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,4 +5,11 @@ + + $([MSBuild]::GetPathOfFileAbove('ElectronNet.Build.props', '$(MSBuildThisFileDirectory)../')) + + + + + diff --git a/README.md b/README.md index c264e3be..cc11de0b 100644 --- a/README.md +++ b/README.md @@ -23,13 +23,14 @@ While the classic Electron.NET setup (using an ASP.NET host run by the Electron * ElectronNET.Core: [![NuGet](https://img.shields.io/nuget/v/ElectronNET.Core.svg?style=flat-square)](https://www.nuget.org/packages/ElectronNET.Core.API/) * ElectronNET.Core.API: [![NuGet](https://img.shields.io/nuget/v/ElectronNET.Core.API.svg?style=flat-square)](https://www.nuget.org/packages/ElectronNET.Core.API/) * ElectronNET.Core.AspNet: [![NuGet](https://img.shields.io/nuget/v/ElectronNET.Core.AspNet.svg?style=flat-square)](https://www.nuget.org/packages/ElectronNET.Core.AspNet/) +* ElectronNET.Core.Templates: [![NuGet](https://img.shields.io/nuget/v/ElectronNET.Core.Templates.svg?style=flat-square)](https://www.nuget.org/packages/ElectronNET.Core.Templates/) ## 🛠 Requirements to Run You should have installed: -* .NET 6/8 or later. -* The minimum base OS is the same as [.NET 6](https://github.com/dotnet/core/blob/main/release-notes/6.0/supported-os.md) / [.NET 8](https://github.com/dotnet/core/blob/main/release-notes/8.0/supported-os.md). +* .NET 8/10 or later. +* The minimum base OS is the same as [.NET 8](https://github.com/dotnet/core/blob/main/release-notes/8.0/supported-os.md) / [.NET 10](https://github.com/dotnet/core/blob/main/release-notes/10.0/supported-os.md). * Node.JS using at least [Version 22.x](https://nodejs.org). ## 👩‍🏫 Usage with ASP.NET @@ -202,6 +203,8 @@ Alternatively, consider using a GitHub sponsorship for the core maintainers: - [Gregor Biswanger](https://github.com/sponsors/GregorBiswanger) - [Florian Rappl](https://github.com/sponsors/FlorianRappl) +Or just [buy Florian a coffee](https://buymeacoffee.com/florianrappl) :coffee:. + Any support appreciated! 🍻 ## 🎉 License diff --git a/docs/API/WebContents.md b/docs/API/WebContents.md index e878e58a..eb6ba058 100644 --- a/docs/API/WebContents.md +++ b/docs/API/WebContents.md @@ -58,6 +58,23 @@ Works for both BrowserWindows and BrowserViews. - `isBrowserWindow` - Whether the webContents belong to a BrowserWindow or not (the other option is a BrowserView) - `path` - Absolute path to the CSS file location +#### 🧊 `Task InsertCSSAsync(string css, string cssOrigin = null)` +Injects CSS into the current web page and returns a unique key for the inserted style sheet. + +**Parameters:** +- `css` - The style sheet to inject +- `cssOrigin` - Can be either `user` or `author`, defaults to `author` + +**Returns:** + +The key of the inserted style sheet, to be used with `RemoveInsertedCSSAsync`. + +#### 🧊 `Task RemoveInsertedCSSAsync(string key)` +Removes a previously inserted style sheet from the current web page. + +**Parameters:** +- `key` - The key returned by `InsertCSSAsync` + #### 🧊 `Task LoadURLAsync(string url)` Loads the url in the window. The url must contain the protocol prefix. @@ -113,6 +130,106 @@ Prints window's web page as PDF with Chromium's preview printing custom settings Whether the PDF generation succeeded. +#### 🧊 `Task GetZoomFactorAsync()` +Returns the current zoom factor. A factor of `1.0` means 100%. + +#### 🧊 `void SetZoomFactor(double factor)` +Changes the zoom factor to the specified factor. The zoom factor is the zoom percent divided by 100, so 300% = `3.0`. The factor must be greater than `0.0`. + +**Parameters:** +- `factor` - The zoom factor + +#### 🧊 `Task GetZoomLevelAsync()` +Returns the current zoom level. + +#### 🧊 `void SetZoomLevel(double level)` +Changes the zoom level to the specified level. The original size is `0` and each increment above or below represents zooming 20% larger or smaller to default limits of 300% and 50% of the original size, respectively. + +**Parameters:** +- `level` - The zoom level + +#### 🧊 `Task SetVisualZoomLevelLimitsAsync(double minimumLevel, double maximumLevel)` +Sets the maximum and minimum pinch-to-zoom level. + +**Parameters:** +- `minimumLevel` - The minimum pinch-to-zoom level +- `maximumLevel` - The maximum pinch-to-zoom level + +#### 🧊 `Task LoadFileAsync(string filePath, LoadFileOptions options = null)` +Loads the given HTML file, relative to the root of the application. + +**Parameters:** +- `filePath` - Path to the HTML file +- `options` - Optional `Query`, `Search` and `Hash` parts of the resulting URL + +#### 🧊 `void SetAudioMuted(bool muted)` +Mutes or unmutes the audio on the current web page. + +#### 🧊 `Task IsAudioMutedAsync()` +Whether this page has been muted. + +#### 🧊 `Task IsCurrentlyAudibleAsync()` +Whether audio is currently playing. + +#### 🧊 `Task GetUserAgentAsync()` / `void SetUserAgent(string userAgent)` +Gets or overrides the user agent for this web page. + +#### 🧊 `Task IsLoadingAsync()` +Whether the web page is still loading resources. + +#### 🧊 `Task IsLoadingMainFrameAsync()` +Whether the main frame (and not just iframes or frames within it) is still loading. + +#### 🧊 `Task IsWaitingForResponseAsync()` +Whether the web page is waiting for a first response from the main resource of the page. + +#### 🧊 `void Reload()` +Reloads the current web page. + +#### 🧊 `void ReloadIgnoringCache()` +Reloads the current web page and ignores the cache. + +#### 🧊 `void Stop()` +Stops any pending navigation. + +#### 🧊 `void Undo()` / `void Redo()` +Executes the `undo` / `redo` editing command in the web page. + +#### 🧊 `void Cut()` / `void Copy()` / `void Paste()` / `void PasteAndMatchStyle()` / `void Delete()` +Executes the corresponding editing command in the web page. + +#### 🧊 `void CopyImageAt(int x, int y)` +Copies the image at the given position to the clipboard. + +#### 🧊 `void SelectAll()` / `void Unselect()` / `void CenterSelection()` +Selects all content, clears the selection, or scrolls to the current selection. + +#### 🧊 `void ScrollToTop()` / `void ScrollToBottom()` +Scrolls to the top or the bottom of the current web page. + +#### 🧊 `void AdjustSelection(AdjustSelectionOptions options)` +Adjusts the start and end points of the current text selection by the given amounts. Negative amounts move towards the beginning of the document. + +#### 🧊 `Task InsertTextAsync(string text)` +Inserts text into the focused element. + +#### 🧊 `void Replace(string text)` / `void ReplaceMisspelling(string text)` +Replaces the current selection, or the currently misspelled word, with the given text. + +#### 🧊 `Task FindInPageAsync(string text, FindInPageOptions options = null)` +Starts a request to find all matches for the text in the web page. Results are reported via the `OnFoundInPage` event. + +**Parameters:** +- `text` - Content to be searched, must not be empty +- `options` - Optional `Forward`, `FindNext` and `MatchCase` flags + +**Returns:** + +The request id of the find request. + +#### 🧊 `void StopFindInPage(StopFindInPageAction action)` +Stops any `FindInPageAsync` request with the given action (`ClearSelection`, `KeepSelection` or `ActivateSelection`). + ## Events #### ⚡ `InputEvent` @@ -142,6 +259,21 @@ Emitted when the document in the top-level frame is loaded. #### ⚡ `OnWillRedirect` Emitted when a server side redirect occurs during navigation. +#### ⚡ `OnZoomChanged` +Emitted when the user changes the zoom level using the mouse wheel or the keyboard. The handler receives the `ZoomDirection` (`In` or `Out`). + +#### ⚡ `OnFoundInPage` +Emitted when a result is available for a `FindInPageAsync` request. The handler receives a `FoundInPageResult`. + +#### ⚡ `OnAudioStateChanged` +Emitted when media becomes audible or inaudible. The handler receives `true` if one or more frames or child web contents are emitting audio. + +#### ⚡ `OnMediaStartedPlaying` +Emitted when media starts playing. + +#### ⚡ `OnMediaPaused` +Emitted when media is paused or done playing. + ## Usage Examples ### Page Loading @@ -279,6 +411,82 @@ webContents.OnCrashed += (killed) => }; ``` +### Zoom Control + +```csharp +// Set the zoom to 150% +webContents.SetZoomFactor(1.5); + +var factor = await webContents.GetZoomFactorAsync(); +Console.WriteLine($"Current zoom: {factor * 100}%"); + +// Zoom levels are relative: each step is 20% larger/smaller, 0 is the original size +webContents.SetZoomLevel(2); + +// Restrict pinch-to-zoom +await webContents.SetVisualZoomLevelLimitsAsync(1, 3); + +// React to zoom changes triggered by the user +webContents.OnZoomChanged += (direction) => +{ + Console.WriteLine($"User zoomed {direction}"); +}; +``` + +> **Note:** The zoom factor is shared by all windows using the same session partition. Assign a unique `WebPreferences.Partition` per window if each window should keep its own zoom. + +### Dynamic CSS + +```csharp +var key = await webContents.InsertCSSAsync("body { background-color: #202020; }"); + +// ... later +await webContents.RemoveInsertedCSSAsync(key); +``` + +### Editing and Selection + +```csharp +await webContents.InsertTextAsync("Hello from .NET"); + +webContents.SelectAll(); +webContents.Copy(); +webContents.Unselect(); +``` + +### Find in Page + +```csharp +webContents.OnFoundInPage += (result) => +{ + Console.WriteLine($"{result.ActiveMatchOrdinal}/{result.Matches} matches"); + + if (result.FinalUpdate) + { + webContents.StopFindInPage(StopFindInPageAction.ClearSelection); + } +}; + +var requestId = await webContents.FindInPageAsync("electron", new FindInPageOptions { MatchCase = false }); +``` + +### Audio + +```csharp +webContents.SetAudioMuted(true); + +var muted = await webContents.IsAudioMutedAsync(); +var audible = await webContents.IsCurrentlyAudibleAsync(); + +webContents.OnAudioStateChanged += (isAudible) => +{ + Console.WriteLine(isAudible ? "Page started emitting audio" : "Page went silent"); +}; + +webContents.OnMediaStartedPlaying += () => Console.WriteLine("Media playing"); +webContents.OnMediaPaused += () => Console.WriteLine("Media paused"); +``` + ## Related APIs - [Electron.WindowManager](WindowManager.md) - Windows containing web contents diff --git a/docs/Core/Migration-Checks.md b/docs/Core/Migration-Checks.md index e07902fc..84eaebfd 100644 --- a/docs/Core/Migration-Checks.md +++ b/docs/Core/Migration-Checks.md @@ -17,6 +17,10 @@ When you build an Electron.NET project, the following validation checks are perf | [ELECTRON005](#4-parent-paths-not-allowed-in-electron-builderjson) | Parent paths not allowed | Checks for `..` references in config | | [ELECTRON006](#5-publish-profile-validation) | ASP.NET publish profile mismatch | Warns when ASP.NET projects have console-style profiles | | [ELECTRON007](#5-publish-profile-validation) | Console publish profile mismatch | Warns when console projects have ASP.NET-style profiles | +| [ELECTRON010](#6-electronhosthook-folder-validation) | ElectronHostHook without package.json | Warns when hook TypeScript files exist without a `package.json` | +| [ELECTRON011](#6-electronhosthook-folder-validation) | ElectronHostHook without tsconfig.json | Warns when hook TypeScript files exist without a `tsconfig.json` | + +All checks skip the build output folders (`bin`, `obj`, `publish`, `.electron`, `node_modules`) as well as any custom output paths configured via `BaseOutputPath` / `BaseIntermediateOutputPath` (for example the .NET `artifacts` output layout). --- @@ -32,7 +36,7 @@ Rules: - **ELECTRON001**: `package.json` / `package-lock.json` must not exist in the project directory or subdirectories - Exception: `ElectronHostHook` folder is allowed - - Note: a **root** `package.json` is **excluded** from `ELECTRON001` and validated by `ELECTRON008` / `ELECTRON009` + - Note: a **root** `package.json` (and its `package-lock.json`) is **excluded** from `ELECTRON001` and validated by `ELECTRON008` / `ELECTRON009` - **ELECTRON008**: If a root `package.json` exists, it must **not** contain electron-related dependencies or configuration. @@ -113,6 +117,10 @@ The `electron.manifest.json` file format is deprecated. All configuration should "mac": { "icon": "Assets/app.icns", "target": ["dmg", "zip"] + }, + "nsis": { + "oneClick": true, + "perMachine": false } } ``` @@ -208,7 +216,7 @@ The build system examines `.pubxml` files in the `Properties/PublishProfiles` fo - **ELECTRON006**: For **ASP.NET projects** (using `Microsoft.NET.Sdk.Web`), checks that publish profiles include `WebPublishMethod`. This property is required for proper ASP.NET publishing. -- **ELECTRON007**: For **console/other projects** (not using the Web SDK), checks that publish profiles do NOT include the `WebPublishMethod` property. These ASP.NET-specific properties are incorrect for non-web applications. +- **ELECTRON007**: For **console/other projects** (not using the Web SDK), checks that publish profiles do NOT include the `WebPublishMethod` or `ProjectGuid` property. These ASP.NET-specific properties are incorrect for non-web applications. ### Why this matters @@ -233,9 +241,54 @@ For correct publish profile examples for both ASP.NET and Console applications, --- +## 6. ElectronHostHook Folder Validation + +**Warning Codes:** `ELECTRON010`, `ELECTRON011` + +### What is checked + +If the project contains an `ElectronHostHook` folder with TypeScript files: + +- **ELECTRON010**: The folder must contain a `package.json` +- **ELECTRON011**: The folder must contain a `tsconfig.json` + +### Why this matters + +Custom host hook code is only compiled and packaged when the `ElectronHostHook` folder declares its npm dependencies in a `package.json`. If that file is missing, the hook is silently dropped and the corresponding `Electron.HostHook` calls fail at runtime. The `tsconfig.json` is required so the hook sources are compiled with the expected settings. + +### How to fix + +Add the missing files to the `ElectronHostHook` folder: + +```json +{ + "name": "electron-host-hook", + "version": "1.0.0", + "main": "index.js", + "dependencies": { + "socket.io": "^4.8.1" + }, + "devDependencies": { + "typescript": "^5.9.3" + } +} +``` + +> **See also:** [HostHook API](../API/HostHook.md) + +--- + ## Disabling Migration Checks -If you need to disable specific migration checks (not recommended), you can set the following properties in your `.csproj` file: +Individual checks can be downgraded to messages by their warning code: + +```xml + + $(MSBuildWarningsAsMessages);ELECTRON005 + +``` + +If you need to disable all migration checks (not recommended), you can set the following property in your `.csproj` file: ```xml diff --git a/docs/Core/Migration-Guide.md b/docs/Core/Migration-Guide.md index 5fa5a07f..9e01009b 100644 --- a/docs/Core/Migration-Guide.md +++ b/docs/Core/Migration-Guide.md @@ -48,17 +48,19 @@ You can also manually edit `electron-builder.json`: ```json { "linux": { - "target": [ - "tar.xz" - ] + "target": ["tar.xz"] }, "win": { "target": [ { - "target": "portable", + "target": "nsis", "arch": "x64" } ] + }, + "nsis": { + "oneClick": true, + "perMachine": false } } ``` diff --git a/docs/GettingStarted/ASP.Net.md b/docs/GettingStarted/ASP.Net.md index 953a6410..8bc80245 100644 --- a/docs/GettingStarted/ASP.Net.md +++ b/docs/GettingStarted/ASP.Net.md @@ -10,6 +10,11 @@ See [System Requirements](../GettingStarted/System-Requirements.md). ## 🚀 Quick Start +> [!Tip] +> To skip the manual setup below, scaffold a ready-to-run app with the +> [project templates](Templates.md): `dotnet new install ElectronNET.Core.Templates` followed by +> `dotnet new electron-blazor -n MyDesktopApp`. + ### 1. Create ASP.NET Core Project #### Visual Studio diff --git a/docs/GettingStarted/Console-App.md b/docs/GettingStarted/Console-App.md index 3b36d0e4..65e814c8 100644 --- a/docs/GettingStarted/Console-App.md +++ b/docs/GettingStarted/Console-App.md @@ -54,7 +54,7 @@ Add the Electron.NET configuration to your `.csproj` file: - + ``` diff --git a/docs/GettingStarted/Templates.md b/docs/GettingStarted/Templates.md new file mode 100644 index 00000000..fce91890 --- /dev/null +++ b/docs/GettingStarted/Templates.md @@ -0,0 +1,88 @@ + +# Project Templates + +Electron.NET ships a `dotnet new` template package so you can scaffold a ready-to-run desktop app instead of wiring up an ASP.NET project by hand. + +## 🛠 System Requirements + +See [System Requirements](../GettingStarted/System-Requirements.md). + +## 📦 Install the Templates + +```bash +dotnet new install ElectronNET.Core.Templates +``` + +To update to the latest version, run the same command again. To remove them: + +```bash +dotnet new uninstall ElectronNET.Core.Templates +``` + +## 🚀 Available Templates + +| Template | Short name | Description | +|----------|------------|-------------| +| Electron.NET Blazor App | `electron-blazor` | A Blazor Server app hosted in an Electron shell | + +## 🧱 Create a Blazor App + +```bash +dotnet new electron-blazor -n MyDesktopApp +cd MyDesktopApp +``` + +Then start it in the Electron shell: + +```bash +dotnet build +dotnet run +``` + +### Options + +| Option | Values | Default | Description | +|--------|--------|---------|-------------| +| `-f`, `--framework` | `net8.0`, `net10.0` | `net10.0` | The target framework of the generated project | +| `-e`, `--electron-version` | any Electron version | `38.2.2` | The Electron version the app is built against | +| `-p`, `--port` | port number | `8001` | The port the ASP.NET server uses during development | +| `--no-restore` | — | — | Skip the automatic `dotnet restore` | + +Example: + +```bash +dotnet new electron-blazor -n MyDesktopApp -f net10.0 -e 30.4.0 -p 8123 +``` + +## 📁 What You Get + +``` +MyDesktopApp/ +├── Components/ +│ ├── Layout/ MainLayout.razor, NavMenu.razor +│ ├── Pages/ Home.razor, Counter.razor +│ ├── App.razor +│ ├── Routes.razor +│ └── _Imports.razor +├── Properties/ +│ ├── PublishProfiles/ win-x64, linux-x64 and osx-arm64 folder profiles +│ ├── electron-builder.json +│ └── launchSettings.json +├── wwwroot/app.css +├── appsettings.json +├── Program.cs +└── MyDesktopApp.csproj +``` + +The project already references `ElectronNET.Core` and `ElectronNET.Core.AspNet`, calls `builder.UseElectron(...)` in `Program.cs`, and passes all [Migration Checks](../Core/Migration-Checks.md) out of the box. + +> [!Note] +> `ElectronNET.API` also defines a type named `App`, which collides with the Blazor root +> component. That is why the template calls `app.MapRazorComponents()` +> with a fully qualified type name. + +## 🚀 Next Steps + +- **[Configuration](../Using/Configuration.md)** - Adjust app metadata and Electron settings +- **[Debugging](../Using/Debugging.md)** - Debug the .NET and Electron sides +- **[Package Building](../Using/Package-Building.md)** - Create distributable packages diff --git a/docs/Using/Configuration.md b/docs/Using/Configuration.md index dd16fc5d..17d1fdd9 100644 --- a/docs/Using/Configuration.md +++ b/docs/Using/Configuration.md @@ -28,9 +28,77 @@ These are the current default values when you don't make any changes: $(MSBuildProjectName.Replace(".", "-").ToLower()) electron-builder.json $(MSBuildProjectName) + + ../.. + false ``` +### Product Name and Executable Name + +`Title` is the product name of the application. It is used for the window title, the installer, the macOS app bundle and the Linux desktop entry, and it may contain spaces and other characters that are awkward in a file name. + +`ElectronExecutableName` controls the name of the executable inside the package (electron-builder's `executableName`). When it is not set, it defaults to the following behavior: + +| Target | Default | +| --- | --- | +| Windows | `$(Title)` | +| Linux / macOS | `$(ElectronPackageId)` | + +So to ship a product called `My Great App` with a `mygreatapp` binary on every platform: + +```xml + + My Great App + mygreatapp + +``` + +> [!NOTE] +> `ElectronExecutable` is a separate, advanced setting: it is the binary Electron.NET launches when the .NET app starts first. It defaults to `ElectronExecutableName` and only needs to be changed when the package contains a launcher stub (for example added by an electron-builder hook) that should be started instead of the Electron binary. + +### Custom Packaging Layout + +`ElectronRootDir` tells the .NET app where to find the Electron binary when it is started first (DotNet-First startup of a packaged app). The path is resolved relative to the directory of the .NET executable; absolute paths are used as-is. + +The default `../..` matches the standard Electron-First packaging layout produced by `dotnet publish`, where the .NET app is placed in `resources/bin` of the Electron package: + +``` +/ + MyApp # Electron executable + resources/ + bin/ + MyApp # .NET executable +``` + +If your own packaging pipeline places the .NET executable at the package root and Electron in a subdirectory, set `ElectronRootDir` accordingly: + +```xml +electron +``` + +``` +/ + MyApp # .NET executable + electron/ + MyApp # Electron executable + resources/ + locales/ +``` + +The property is also used to detect whether the app runs packaged or unpackaged, so it must point to the directory that actually contains the Electron binary. + +### Build Extensibility + +These properties are useful when Electron.NET is embedded into a custom build or CI pipeline: + +| Property | Default | Description | +| --- | --- | --- | +| `ElectronSkipExecCommands` | `false` | Skips all `npm`/`npx` invocations of the Electron build and publish targets. Use it when the dependencies and the Electron distribution are provided by the pipeline itself (for example from a cache or an offline mirror). | +| `ElectronIntermediatePublishDir` | `$(IntermediateOutputPath)PubTmp\` | Overrides the intermediate directory the .NET app is published to before it is assembled into the Electron package. | + +`ElectronPackageId` and `Title` only fall back to the project name when they are not already set, so both can be defined by a `Directory.Build.props` or passed on the command line. + ### Relation to package.json ElectronNET.Core does not work with an `electron-manifest.json` file anymore. @@ -42,11 +110,17 @@ Since electron builder still expects a `package.json` file to exist, ElectronNET "productName": "$(ElectronTitle)", "build": { "appId": "$(ElectronPackageId)", + "win": { + "executableName": "$(ElectronExecutableName)" + }, + "mac": { + "executableName": "$(ElectronExecutableName)" + }, "linux": { "desktop": { "entry": { "Name": "$(Title)" } }, - "executableName": "$(ElectronPackageId)" + "executableName": "$(ElectronExecutableName)" }, "deb": { "desktop": { diff --git a/docs/Using/Custom_main.md b/docs/Using/Custom_main.md index dac300fb..7a3f1ec5 100644 --- a/docs/Using/Custom_main.md +++ b/docs/Using/Custom_main.md @@ -7,6 +7,7 @@ This guide explains how to include and use a `custom_main.js` file in your Elect - Register custom protocol handlers (e.g., `myapp://`) — protocols must be registered before the app is fully initialized - Integrate Node.js modules (e.g., telemetry, OS APIs) - Control startup logic (abort, environment checks) +- Modify Chromium / Electron.NET command line switches before they are evaluated - Set up IPC messaging or preload scripts ## Step-by-Step Process @@ -65,10 +66,29 @@ Use environment variables to control features: if (env === 'Development') { /* enable dev features */ } ``` +### Modifying Command Line Switches + +`onStartup` is invoked before Electron.NET reads any of its own switches (`manifest`, `unpackedelectron`, `unpackeddotnet`, `dotnetpacked`, `electronforcedport`, `electronurl`), so the hook can append or override them: + +```javascript +module.exports.onStartup = function (host) { + const { app } = require('electron'); + + // Force a fixed socket bridge port + app.commandLine.appendSwitch('electronforcedport', '8000'); + + // Chromium switches, e.g. to disable the GPU sandbox + app.commandLine.appendSwitch('disable-gpu-sandbox'); + + return true; +}; +``` + ## Notes - `custom_main.js` must use CommonJS syntax (`module.exports.onStartup = ...`). - Place the file in your source directory and copy it to `.electron` using `.csproj`. - Electron.NET will abort startup if `onStartup` returns `false`. +- `onStartup` runs before the Electron.NET command line switches are evaluated, so switches set there are picked up by the host. ### Complete example is available here [ElectronNetSampleApp](https://github.com/niteshsinghal85/ElectronNetSampleApp) \ No newline at end of file diff --git a/docs/Using/Package-Building.md b/docs/Using/Package-Building.md index 6b6325e5..d6f74730 100644 --- a/docs/Using/Package-Building.md +++ b/docs/Using/Package-Building.md @@ -222,6 +222,15 @@ The publish process will: > macOS builds can't be created on Windows machines because they require symlinks that aren't supported on Windows (per [this Electron issue](https://github.com/electron-userland/electron-packager/issues/71)). macOS builds can be produced on either Linux or macOS machines. +## Custom Packaging Pipelines + +The default layout is Electron-First: electron-builder produces the Electron package and the .NET app is placed in `resources/bin`. If you assemble the package yourself and put the .NET executable at the package root with Electron in a subdirectory, set `ElectronRootDir` so the .NET app can locate the Electron binary at runtime. + +For pipelines that provide the npm dependencies themselves, `ElectronSkipExecCommands` suppresses all `npm`/`npx` invocations, and `ElectronIntermediatePublishDir` redirects the intermediate publish output. + +See [Configuration](Configuration.md#custom-packaging-layout) for details. + + ## 🚀 Next Steps - **[Startup Methods](Startup-Methods.md)** - Understanding different launch modes for packaged apps diff --git a/docs/_Sidebar.md b/docs/_Sidebar.md index 6b883561..28af3551 100644 --- a/docs/_Sidebar.md +++ b/docs/_Sidebar.md @@ -15,6 +15,7 @@ # Getting Started - [System Requirements](GettingStarted/System-Requirements.md) +- [Project Templates](GettingStarted/Templates.md) - [With ASP.Net](GettingStarted/ASP.Net.md) - [With a Console App](GettingStarted/Console-App.md) diff --git a/src/ElectronNET.API/API/Entities/AdjustSelectionOptions.cs b/src/ElectronNET.API/API/Entities/AdjustSelectionOptions.cs new file mode 100644 index 00000000..513bed6b --- /dev/null +++ b/src/ElectronNET.API/API/Entities/AdjustSelectionOptions.cs @@ -0,0 +1,18 @@ +namespace ElectronNET.API.Entities +{ + /// + /// Options for . + /// + public class AdjustSelectionOptions + { + /// + /// Amount to shift the start index of the current selection. + /// + public int? Start { get; set; } + + /// + /// Amount to shift the end index of the current selection. + /// + public int? End { get; set; } + } +} diff --git a/src/ElectronNET.API/API/Entities/FindInPageOptions.cs b/src/ElectronNET.API/API/Entities/FindInPageOptions.cs new file mode 100644 index 00000000..550cee9e --- /dev/null +++ b/src/ElectronNET.API/API/Entities/FindInPageOptions.cs @@ -0,0 +1,24 @@ +namespace ElectronNET.API.Entities +{ + /// + /// Options for . + /// + public class FindInPageOptions + { + /// + /// Whether to search forward or backward, defaults to true. + /// + public bool? Forward { get; set; } + + /// + /// Whether to begin a new text finding session with this request. Should be true + /// for initial requests, and false for subsequent requests. Defaults to false. + /// + public bool? FindNext { get; set; } + + /// + /// Whether search should be case-sensitive, defaults to false. + /// + public bool? MatchCase { get; set; } + } +} diff --git a/src/ElectronNET.API/API/Entities/FoundInPageResult.cs b/src/ElectronNET.API/API/Entities/FoundInPageResult.cs new file mode 100644 index 00000000..59b3ca1b --- /dev/null +++ b/src/ElectronNET.API/API/Entities/FoundInPageResult.cs @@ -0,0 +1,33 @@ +namespace ElectronNET.API.Entities +{ + /// + /// The result of a text finding session, reported by the found-in-page event. + /// + public class FoundInPageResult + { + /// + /// The identifier of the request returned by FindInPageAsync. + /// + public int RequestId { get; set; } + + /// + /// Position of the active match. + /// + public int ActiveMatchOrdinal { get; set; } + + /// + /// Number of matches. + /// + public int Matches { get; set; } + + /// + /// Coordinates of the first match region. + /// + public Rectangle SelectionArea { get; set; } + + /// + /// Indicates whether more responses are to follow. + /// + public bool FinalUpdate { get; set; } + } +} diff --git a/src/ElectronNET.API/API/Entities/LoadFileOptions.cs b/src/ElectronNET.API/API/Entities/LoadFileOptions.cs new file mode 100644 index 00000000..b3ec35a5 --- /dev/null +++ b/src/ElectronNET.API/API/Entities/LoadFileOptions.cs @@ -0,0 +1,25 @@ +using System.Collections.Generic; + +namespace ElectronNET.API.Entities +{ + /// + /// Options for loading a local file into a web page. + /// + public class LoadFileOptions + { + /// + /// Passed to url.format(). + /// + public Dictionary Query { get; set; } + + /// + /// Passed to url.format(). + /// + public string Search { get; set; } + + /// + /// Passed to url.format(). + /// + public string Hash { get; set; } + } +} diff --git a/src/ElectronNET.API/API/Entities/StopFindInPageAction.cs b/src/ElectronNET.API/API/Entities/StopFindInPageAction.cs new file mode 100644 index 00000000..07099074 --- /dev/null +++ b/src/ElectronNET.API/API/Entities/StopFindInPageAction.cs @@ -0,0 +1,23 @@ +namespace ElectronNET.API.Entities +{ + /// + /// Determines what happens to the selection when a text finding session is stopped. + /// + public enum StopFindInPageAction + { + /// + /// Clear the selection. + /// + ClearSelection, + + /// + /// Translate the selection into a normal selection. + /// + KeepSelection, + + /// + /// Focus and click the selection node. + /// + ActivateSelection + } +} diff --git a/src/ElectronNET.API/API/Entities/ZoomDirection.cs b/src/ElectronNET.API/API/Entities/ZoomDirection.cs new file mode 100644 index 00000000..2ae57012 --- /dev/null +++ b/src/ElectronNET.API/API/Entities/ZoomDirection.cs @@ -0,0 +1,18 @@ +namespace ElectronNET.API.Entities +{ + /// + /// The direction of a zoom change triggered by the user. + /// + public enum ZoomDirection + { + /// + /// The user zoomed in. + /// + In, + + /// + /// The user zoomed out. + /// + Out + } +} diff --git a/src/ElectronNET.API/API/WebContents.cs b/src/ElectronNET.API/API/WebContents.cs index 7657b413..bfc51385 100644 --- a/src/ElectronNET.API/API/WebContents.cs +++ b/src/ElectronNET.API/API/WebContents.cs @@ -113,6 +113,52 @@ public event Action OnDomReady remove => RemoveEvent(value, Id); } + /// + /// Emitted when the user is requesting to change the zoom level using the mouse wheel or the keyboard. + /// + public event Action OnZoomChanged + { + add => AddEvent(value, Id); + remove => RemoveEvent(value, Id); + } + + /// + /// Emitted when a result is available for a request. + /// + public event Action OnFoundInPage + { + add => AddEvent(value, Id); + remove => RemoveEvent(value, Id); + } + + /// + /// Emitted when media becomes audible or inaudible. The parameter is true if one or more + /// frames or child web contents are emitting audio. + /// + public event Action OnAudioStateChanged + { + add => AddEvent(value, Id); + remove => RemoveEvent(value, Id); + } + + /// + /// Emitted when media starts playing. + /// + public event Action OnMediaStartedPlaying + { + add => AddEvent(value, Id); + remove => RemoveEvent(value, Id); + } + + /// + /// Emitted when media is paused or done playing. + /// + public event Action OnMediaPaused + { + add => AddEvent(value, Id); + remove => RemoveEvent(value, Id); + } + internal WebContents(int id) { Id = id; @@ -304,6 +350,68 @@ public Task LoadURLAsync(string url, LoadURLOptions options) return tcs.Task; } + /// + /// Loads the given file in the window. The file path must be a path to an HTML file + /// relative to the root of your application. + /// + /// Path to the HTML file. + /// Optional query, search and hash parts of the resulting URL. + public Task LoadFileAsync(string filePath, LoadFileOptions options = null) + { + var tcs = new TaskCompletionSource(); + + BridgeConnector.Socket.Once("webContents-loadFile-complete" + Id, () => + { + BridgeConnector.Socket.Off("webContents-loadFile-error" + Id); + tcs.SetResult(); + }); + + BridgeConnector.Socket.Once("webContents-loadFile-error" + Id, (error) => { tcs.SetException(new InvalidOperationException(error)); }); + + BridgeConnector.Socket.Emit("webContents-loadFile", Id, filePath, options); + + return tcs.Task; + } + + /// + /// Returns boolean - Whether web page is still loading resources. + /// + public Task IsLoadingAsync() => InvokeAsync(); + + /// + /// Returns boolean - Whether the main frame (and not just iframes or frames within it) is still loading. + /// + public Task IsLoadingMainFrameAsync() => InvokeAsync(); + + /// + /// Returns boolean - Whether the web page is waiting for a first-response from the main resource of the page. + /// + public Task IsWaitingForResponseAsync() => InvokeAsync(); + + /// + /// Reloads the current web page. + /// + public void Reload() + { + BridgeConnector.Socket.Emit("webContents-reload", Id); + } + + /// + /// Reloads the current page and ignores cache. + /// + public void ReloadIgnoringCache() + { + BridgeConnector.Socket.Emit("webContents-reloadIgnoringCache", Id); + } + + /// + /// Stops any pending navigation. + /// + public void Stop() + { + BridgeConnector.Socket.Emit("webContents-stop", Id); + } + /// /// Inserts CSS into the web page. /// See: https://www.electronjs.org/docs/api/web-contents#contentsinsertcsscss-options @@ -316,6 +424,37 @@ public void InsertCSS(bool isBrowserWindow, string path) BridgeConnector.Socket.Emit("webContents-insertCSS", Id, isBrowserWindow, path); } + /// + /// Injects CSS into the current web page and returns a unique key for the inserted + /// stylesheet, which can be used with . + /// + /// The style sheet to inject. + /// Can be either 'user' or 'author'. Defaults to 'author'. + /// The key of the inserted style sheet. + public Task InsertCSSAsync(string css, string cssOrigin = null) + { + var tcs = new TaskCompletionSource(); + + BridgeConnector.Socket.Once("webContents-insertCSSText-completed" + Id, tcs.SetResult); + BridgeConnector.Socket.Emit("webContents-insertCSSText", Id, css, cssOrigin); + + return tcs.Task; + } + + /// + /// Removes the inserted CSS from the current web page. + /// + /// The key returned by . + public Task RemoveInsertedCSSAsync(string key) + { + var tcs = new TaskCompletionSource(); + + BridgeConnector.Socket.Once("webContents-removeInsertedCSS-completed" + Id, tcs.SetResult); + BridgeConnector.Socket.Emit("webContents-removeInsertedCSS", Id, key); + + return tcs.Task; + } + /// /// Returns number - The current zoom factor. /// @@ -337,14 +476,14 @@ public void SetZoomFactor(double factor) /// Returns number - The current zoom level. /// /// - public Task GetZoomLevelAsync() => InvokeAsync(); + public Task GetZoomLevelAsync() => InvokeAsync(); /// /// Changes the zoom level to the specified level. /// The original size is 0 and each increment above or below represents zooming 20% larger or smaller to default limits of 300% and 50% of original size, respectively. /// /// - public void SetZoomLevel(int level) + public void SetZoomLevel(double level) { BridgeConnector.Socket.Emit("webContents-setZoomLevel", Id, level); } @@ -354,7 +493,7 @@ public void SetZoomLevel(int level) /// /// /// - public Task SetVisualZoomLevelLimitsAsync(int minimumLevel, int maximumLevel) + public Task SetVisualZoomLevelLimitsAsync(double minimumLevel, double maximumLevel) { var tcs = new TaskCompletionSource(); @@ -399,4 +538,178 @@ public void SetUserAgent(string userAgent) { BridgeConnector.Socket.Emit("webContents-setUserAgent", Id, userAgent); } + + /// + /// Executes the editing command undo in web page. + /// + public void Undo() + { + BridgeConnector.Socket.Emit("webContents-undo", Id); + } + + /// + /// Executes the editing command redo in web page. + /// + public void Redo() + { + BridgeConnector.Socket.Emit("webContents-redo", Id); + } + + /// + /// Executes the editing command cut in web page. + /// + public void Cut() + { + BridgeConnector.Socket.Emit("webContents-cut", Id); + } + + /// + /// Executes the editing command copy in web page. + /// + public void Copy() + { + BridgeConnector.Socket.Emit("webContents-copy", Id); + } + + /// + /// Copies the image at the given position to the clipboard. + /// + /// + /// + public void CopyImageAt(int x, int y) + { + BridgeConnector.Socket.Emit("webContents-copyImageAt", Id, x, y); + } + + /// + /// Executes the editing command paste in web page. + /// + public void Paste() + { + BridgeConnector.Socket.Emit("webContents-paste", Id); + } + + /// + /// Executes the editing command pasteAndMatchStyle in web page. + /// + public void PasteAndMatchStyle() + { + BridgeConnector.Socket.Emit("webContents-pasteAndMatchStyle", Id); + } + + /// + /// Executes the editing command delete in web page. + /// + public void Delete() + { + BridgeConnector.Socket.Emit("webContents-delete", Id); + } + + /// + /// Executes the editing command selectAll in web page. + /// + public void SelectAll() + { + BridgeConnector.Socket.Emit("webContents-selectAll", Id); + } + + /// + /// Executes the editing command unselect in web page. + /// + public void Unselect() + { + BridgeConnector.Socket.Emit("webContents-unselect", Id); + } + + /// + /// Adjusts the current text selection starting and ending points by the given amounts. + /// A negative amount moves the selection towards the beginning of the document. + /// + /// + public void AdjustSelection(AdjustSelectionOptions options) + { + BridgeConnector.Socket.Emit("webContents-adjustSelection", Id, options); + } + + /// + /// Scrolls to the current text selection. + /// + public void CenterSelection() + { + BridgeConnector.Socket.Emit("webContents-centerSelection", Id); + } + + /// + /// Scrolls to the top of the current web page. + /// + public void ScrollToTop() + { + BridgeConnector.Socket.Emit("webContents-scrollToTop", Id); + } + + /// + /// Scrolls to the bottom of the current web page. + /// + public void ScrollToBottom() + { + BridgeConnector.Socket.Emit("webContents-scrollToBottom", Id); + } + + /// + /// Inserts text to the focused element. + /// + /// The text to be inserted. + public Task InsertTextAsync(string text) + { + var tcs = new TaskCompletionSource(); + + BridgeConnector.Socket.Once("webContents-insertText-completed" + Id, tcs.SetResult); + BridgeConnector.Socket.Emit("webContents-insertText", Id, text); + + return tcs.Task; + } + + /// + /// Executes the editing command replace in web page. + /// + /// + public void Replace(string text) + { + BridgeConnector.Socket.Emit("webContents-replace", Id, text); + } + + /// + /// Executes the editing command replaceMisspelling in web page. + /// + /// + public void ReplaceMisspelling(string text) + { + BridgeConnector.Socket.Emit("webContents-replaceMisspelling", Id, text); + } + + /// + /// Starts a request to find all matches for the text in the web page. + /// The result of the request can be obtained by subscribing to the event. + /// + /// Content to be searched, must not be empty. + /// + /// The request id used for the request. + public Task FindInPageAsync(string text, FindInPageOptions options = null) + { + var tcs = new TaskCompletionSource(); + + BridgeConnector.Socket.Once("webContents-findInPage-completed" + Id, tcs.SetResult); + BridgeConnector.Socket.Emit("webContents-findInPage", Id, text, options); + + return tcs.Task; + } + + /// + /// Stops any findInPage request for the web contents with the provided action. + /// + /// + public void StopFindInPage(StopFindInPageAction action) + { + BridgeConnector.Socket.Emit("webContents-stopFindInPage", Id, action); + } } \ No newline at end of file diff --git a/src/ElectronNET.API/API/WindowManager.cs b/src/ElectronNET.API/API/WindowManager.cs index ff675782..97713840 100644 --- a/src/ElectronNET.API/API/WindowManager.cs +++ b/src/ElectronNET.API/API/WindowManager.cs @@ -157,10 +157,19 @@ private void EnsureBrowserWindowClosedSubscription() } BridgeConnector.Socket.On("BrowserWindowClosed", HandleBrowserWindowClosed); + BridgeConnector.Socket.On("BrowserWindowRecreated", HandleBrowserWindowRecreated); _browserWindowClosedSubscribed = true; } } + private void HandleBrowserWindowRecreated(int id) + { + if (_browserWindows.All(window => window.Id != id)) + { + _browserWindows.Add(new BrowserWindow(id)); + } + } + private void HandleBrowserWindowClosed(int[] ids) { if (ids == null || ids.Length == 0) diff --git a/src/ElectronNET.API/Bridge/SocketIOConnection.cs b/src/ElectronNET.API/Bridge/SocketIOConnection.cs index 36ea2e52..10a88a72 100644 --- a/src/ElectronNET.API/Bridge/SocketIOConnection.cs +++ b/src/ElectronNET.API/Bridge/SocketIOConnection.cs @@ -4,6 +4,7 @@ namespace ElectronNET.API; using System; using System.Collections.Generic; +using System.Net; using System.Threading.Tasks; using ElectronNET.API.Serialization; using SocketIO.Serializer.SystemTextJson; @@ -18,13 +19,21 @@ internal class SocketIOConnection : ISocketConnection public SocketIOConnection(string uri, string authorization) { - var opts = string.IsNullOrEmpty(authorization) ? new SocketIOOptions() : new SocketIOOptions + var opts = new SocketIOOptions { - ExtraHeaders = new Dictionary + // The bridge is a loopback IPC channel, so it must never go through a + // (system) proxy - otherwise the handshake never reaches the socket server. + Proxy = DirectProxy.Instance, + }; + + if (!string.IsNullOrEmpty(authorization)) + { + opts.ExtraHeaders = new Dictionary { ["authorization"] = authorization - }, - }; + }; + } + _socket = new SocketIO(uri, opts); _socket.Serializer = new SystemTextJsonSerializer(ElectronJson.Options); // Use default System.Text.Json serializer from SocketIOClient. @@ -152,4 +161,15 @@ private void CheckDisposed() throw new ObjectDisposedException(nameof(SocketIOConnection)); } } + + private sealed class DirectProxy : IWebProxy + { + public static readonly DirectProxy Instance = new DirectProxy(); + + public ICredentials Credentials { get; set; } + + public Uri GetProxy(Uri destination) => destination; + + public bool IsBypassed(Uri host) => true; + } } \ No newline at end of file diff --git a/src/ElectronNET.API/Common/ProcessRunner.cs b/src/ElectronNET.API/Common/ProcessRunner.cs index d561020e..2d44e921 100644 --- a/src/ElectronNET.API/Common/ProcessRunner.cs +++ b/src/ElectronNET.API/Common/ProcessRunner.cs @@ -37,10 +37,18 @@ public class ProcessRunner : IDisposable public ProcessRunner(string name) { this.Name = name; + this.ExitWaitTimeout = DefaultExitWaitTimeout; } public event EventHandler ProcessExited; + /// Gets or sets the value is initialized with. + public static int DefaultExitWaitTimeout { get; set; } = 5000; + + /// Gets or sets the time in milliseconds to wait for the process and its I/O to finish + /// after the exited event has been raised. Values of zero or less wait indefinitely. + public int ExitWaitTimeout { get; set; } + public bool IsDisposed { get; private set; } private Process Process @@ -498,8 +506,17 @@ private void WaitForExitAfterExited() { try { + var timeout = this.ExitWaitTimeout; + // This shouldn't throw here, but the mono process implementation doesn't always behave as it should. - this.process.WaitForExit(); + if (timeout > 0) + { + this.process.WaitForExit(timeout); + } + else + { + this.process.WaitForExit(); + } } catch (Exception ex) { diff --git a/src/ElectronNET.API/ElectronNET.API.csproj b/src/ElectronNET.API/ElectronNET.API.csproj index 7a1cda19..6439aed3 100644 --- a/src/ElectronNET.API/ElectronNET.API.csproj +++ b/src/ElectronNET.API/ElectronNET.API.csproj @@ -3,7 +3,7 @@ - net6.0;net8.0;net10.0 + $(ElectronNetTargetFrameworks) ..\..\artifacts $(PackageNamePrefix).API $(PackageId) @@ -29,7 +29,7 @@ - + diff --git a/src/ElectronNET.API/ElectronNetRuntime.cs b/src/ElectronNET.API/ElectronNetRuntime.cs index 97fa2ed1..e8230526 100644 --- a/src/ElectronNET.API/ElectronNetRuntime.cs +++ b/src/ElectronNET.API/ElectronNetRuntime.cs @@ -15,6 +15,7 @@ public static class ElectronNetRuntime internal const int DefaultSocketPort = 8000; internal const int DefaultWebPort = 8001; internal const string ElectronPortArgumentName = "electronPort"; + internal const string ElectronHostArgumentName = "electronHost"; internal const string ElectronPidArgumentName = "electronPID"; internal const string ElectronAuthTokenArgumentName = "electronAuthToken"; @@ -31,6 +32,11 @@ static ElectronNetRuntime() public static int? ElectronSocketPort { get; internal set; } + /// + /// The loopback address the Electron socket bridge is listening on. + /// + public static string ElectronSocketHost { get; internal set; } + public static int? AspNetWebPort { get; internal set; } public static StartupMethod StartupMethod { get; internal set; } diff --git a/src/ElectronNET.API/Runtime/Data/BuildInfo.cs b/src/ElectronNET.API/Runtime/Data/BuildInfo.cs index 75febe06..faefd128 100644 --- a/src/ElectronNET.API/Runtime/Data/BuildInfo.cs +++ b/src/ElectronNET.API/Runtime/Data/BuildInfo.cs @@ -6,6 +6,8 @@ public class BuildInfo public string ElectronVersion { get; internal set; } + public string ElectronRootDir { get; internal set; } + public string RuntimeIdentifier { get; internal set; } public bool ElectronSingleInstance { get; internal set; } diff --git a/src/ElectronNET.API/Runtime/Helpers/ElectronRootDirResolver.cs b/src/ElectronNET.API/Runtime/Helpers/ElectronRootDirResolver.cs new file mode 100644 index 00000000..6d17a61f --- /dev/null +++ b/src/ElectronNET.API/Runtime/Helpers/ElectronRootDirResolver.cs @@ -0,0 +1,31 @@ +namespace ElectronNET.Runtime.Helpers +{ + using System; + using System.IO; + + /// + /// Resolves the directory that contains the Electron binary of a packaged application. + /// + internal static class ElectronRootDirResolver + { + /// The location of the Electron binary relative to the .NET application directory in the + /// default (Electron-first) layout, where the .NET application is placed in 'resources/bin'. + internal const string DefaultElectronRootDir = "../.."; + + /// Resolves the Electron root directory relative to the given .NET application directory. + /// The directory containing the .NET application. + /// The directory containing the Electron binary. + public static DirectoryInfo Resolve(DirectoryInfo baseDirectory) + { + var rootDir = ElectronNetRuntime.BuildInfo?.ElectronRootDir; + + if (string.IsNullOrWhiteSpace(rootDir)) + { + rootDir = DefaultElectronRootDir; + } + + // An absolute ElectronRootDir is used as-is by Path.Combine. + return new DirectoryInfo(Path.GetFullPath(Path.Combine(baseDirectory.FullName, rootDir))); + } + } +} diff --git a/src/ElectronNET.API/Runtime/Helpers/UnpackagedDetector.cs b/src/ElectronNET.API/Runtime/Helpers/UnpackagedDetector.cs index f5c5f549..ed814a26 100644 --- a/src/ElectronNET.API/Runtime/Helpers/UnpackagedDetector.cs +++ b/src/ElectronNET.API/Runtime/Helpers/UnpackagedDetector.cs @@ -69,6 +69,15 @@ public static bool CheckIsUnpackaged() return false; } + // Packaged, if the Electron binary is found where ElectronRootDir points to. + var electronExecutable = ElectronNetRuntime.ElectronExecutable; + + if (!string.IsNullOrEmpty(electronExecutable) && + File.Exists(Path.Combine(ElectronRootDirResolver.Resolve(dir).FullName, electronExecutable))) + { + return false; + } + if (dir.GetDirectories().Any(e => e.Name == ".electron")) { return true; diff --git a/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs b/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs index b7c65ed4..55e502d0 100644 --- a/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs +++ b/src/ElectronNET.API/Runtime/Services/ElectronProcess/ElectronProcessActive.cs @@ -11,6 +11,7 @@ using System.Threading.Tasks; using ElectronNET.Common; using ElectronNET.Runtime.Data; + using ElectronNET.Runtime.Helpers; /// /// Launches and manages the Electron app process. @@ -18,7 +19,7 @@ [Localizable(false)] internal class ElectronProcessActive : ElectronProcessBase { - private readonly Regex extractor = new Regex("^Electron Socket: listening on port (\\d+) at .* using ([a-f0-9]+)$"); + private readonly Regex extractor = new Regex("^Electron Socket: listening on port (\\d+) at (\\S+) using ([a-f0-9]+)$"); private readonly bool isUnpackaged; private readonly string electronBinaryName; @@ -87,7 +88,7 @@ protected override async Task StartCore() } else { - dir = dir.Parent!.Parent!; + dir = ElectronRootDirResolver.Resolve(dir); startCmd = Path.Combine(dir.FullName, this.electronBinaryName); args = $"-dotnetpacked -electronforcedport={this.socketPort:D} " + this.extraArguments; workingDir = dir.FullName; @@ -179,11 +180,13 @@ void Read_SocketIO_Parameters(object sender, string line) if (match?.Success ?? false) { var port = int.Parse(match.Groups[1].Value); - var token = match.Groups[2].Value; + var host = match.Groups[2].Value; + var token = match.Groups[3].Value; this.process.LineReceived -= Read_SocketIO_Parameters; ElectronNetRuntime.ElectronAuthToken = token; ElectronNetRuntime.ElectronSocketPort = port; + ElectronNetRuntime.ElectronSocketHost = host; tcs.SetResult(); } } diff --git a/src/ElectronNET.API/Runtime/Services/SocketBridge/SocketBridgeService.cs b/src/ElectronNET.API/Runtime/Services/SocketBridge/SocketBridgeService.cs index 4530a651..dd40033c 100644 --- a/src/ElectronNET.API/Runtime/Services/SocketBridge/SocketBridgeService.cs +++ b/src/ElectronNET.API/Runtime/Services/SocketBridge/SocketBridgeService.cs @@ -16,7 +16,19 @@ public SocketBridgeService(int socketPort, string authorization) { this.socketPort = socketPort; this.authorization = authorization; - this.socketUrl = $"http://localhost:{this.socketPort}"; + this.socketUrl = $"http://{FormatHost(ElectronNetRuntime.ElectronSocketHost)}:{this.socketPort}"; + } + + // The Electron host reports the loopback address it is actually listening on; only + // when it is unknown we have to fall back to the ambiguous hostname. + private static string FormatHost(string socketHost) + { + if (string.IsNullOrWhiteSpace(socketHost)) + { + return "localhost"; + } + + return socketHost.Contains(':') ? $"[{socketHost}]" : socketHost; } public int SocketPort => this.socketPort; diff --git a/src/ElectronNET.API/Runtime/StartupManager.cs b/src/ElectronNET.API/Runtime/StartupManager.cs index e7ceff17..c945ef11 100644 --- a/src/ElectronNET.API/Runtime/StartupManager.cs +++ b/src/ElectronNET.API/Runtime/StartupManager.cs @@ -94,8 +94,20 @@ private void CollectProcessData() } } - var pidArg = argsList.FirstOrDefault(e => e.Contains(ElectronNetRuntime.ElectronPidArgumentName, StringComparison.OrdinalIgnoreCase)); + var hostArg = argsList.FirstOrDefault(e => e.Contains(ElectronNetRuntime.ElectronHostArgumentName, StringComparison.OrdinalIgnoreCase)); + + if (hostArg != null) + { + var parts = hostArg.Split('=', StringSplitOptions.TrimEntries); + if (parts.Length > 1 && !string.IsNullOrWhiteSpace(parts[1])) + { + ElectronNetRuntime.ElectronSocketHost = parts[1]; + + Console.WriteLine("Use Electron Host: " + parts[1]); + } + } + var pidArg = argsList.FirstOrDefault(e => e.Contains(ElectronNetRuntime.ElectronPidArgumentName, StringComparison.OrdinalIgnoreCase)); if (pidArg != null) { var parts = pidArg.Split('=', StringSplitOptions.TrimEntries); @@ -166,6 +178,7 @@ private BuildInfo GatherBuildInfo() { buildInfo.ElectronExecutable = attributes.FirstOrDefault(e => e.Key == nameof(buildInfo.ElectronExecutable))?.Value; buildInfo.ElectronVersion = attributes.FirstOrDefault(e => e.Key == nameof(buildInfo.ElectronVersion))?.Value; + buildInfo.ElectronRootDir = attributes.FirstOrDefault(e => e.Key == nameof(buildInfo.ElectronRootDir))?.Value; buildInfo.RuntimeIdentifier = attributes.FirstOrDefault(e => e.Key == nameof(buildInfo.RuntimeIdentifier))?.Value; buildInfo.Title = attributes.FirstOrDefault(e => e.Key == nameof(buildInfo.Title))?.Value; buildInfo.Version = attributes.FirstOrDefault(e => e.Key == nameof(buildInfo.Version))?.Value; diff --git a/src/ElectronNET.AspNet/ElectronNET.AspNet.csproj b/src/ElectronNET.AspNet/ElectronNET.AspNet.csproj index b5c17913..28f5282c 100644 --- a/src/ElectronNET.AspNet/ElectronNET.AspNet.csproj +++ b/src/ElectronNET.AspNet/ElectronNET.AspNet.csproj @@ -3,7 +3,7 @@ - net6.0;net8.0;net10.0 + $(ElectronNetTargetFrameworks) ..\..\artifacts $(PackageNamePrefix).AspNet $(PackageId) diff --git a/src/ElectronNET.ConsoleApp/ElectronNET.ConsoleApp.csproj b/src/ElectronNET.ConsoleApp/ElectronNET.ConsoleApp.csproj index 7662dfa7..416e3805 100644 --- a/src/ElectronNET.ConsoleApp/ElectronNET.ConsoleApp.csproj +++ b/src/ElectronNET.ConsoleApp/ElectronNET.ConsoleApp.csproj @@ -70,7 +70,7 @@ - + diff --git a/src/ElectronNET.Host/ElectronHostHook/package-lock.json b/src/ElectronNET.Host/ElectronHostHook/package-lock.json index d406ed1f..bf39b3d5 100644 --- a/src/ElectronNET.Host/ElectronHostHook/package-lock.json +++ b/src/ElectronNET.Host/ElectronHostHook/package-lock.json @@ -247,9 +247,9 @@ } }, "node_modules/socket.io-parser": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.6.tgz", - "integrity": "sha512-asJqbVBDsBCJx0pTqw3WfesSY0iRX+2xzWEWzrpcH7L6fLzrhyF8WPI8UaeM4YCuDfpwA/cgsdugMsmtz8EJeg==", + "version": "4.2.7", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.7.tgz", + "integrity": "sha512-IH/iSeO9T6gz1KkFleGDWkG9N3dl4jXVYUtMhIqH10Md0ttMer8nUNWiP1DKuNrybD2xBrixLJdCC9J6ECoYkg==", "license": "MIT", "dependencies": { "@socket.io/component-emitter": "~3.1.0", diff --git a/src/ElectronNET.Host/ElectronNET.Host.esproj b/src/ElectronNET.Host/ElectronNET.Host.esproj index 0f56fbfb..4469c3b2 100644 --- a/src/ElectronNET.Host/ElectronNET.Host.esproj +++ b/src/ElectronNET.Host/ElectronNET.Host.esproj @@ -1,4 +1,4 @@ - + diff --git a/src/ElectronNET.Host/api/browserWindows.js b/src/ElectronNET.Host/api/browserWindows.js index 5ed71e8a..e6027d07 100644 --- a/src/ElectronNET.Host/api/browserWindows.js +++ b/src/ElectronNET.Host/api/browserWindows.js @@ -39,7 +39,6 @@ const windows = (global["browserWindows"] = global["browserWindows"] || []); let readyToShowWindowsIds = []; let window; -let lastOptions; let electronSocket; const proxyToCredentialsMap = (global["proxyToCredentialsMap"] = global["proxyToCredentialsMap"] || []); module.exports = (socket, app) => { @@ -203,6 +202,18 @@ module.exports = (socket, app) => { }); }); socket.on("createBrowserWindow", (options, loadUrl) => { + createWindow(options, loadUrl, "BrowserWindowCreated"); + }); + // Allows the host (main.js) to bring the main window back when the app is activated + // again on macOS after all windows have been closed. + global["recreateMainWindow"] = () => { + if (electron_1.BrowserWindow.getAllWindows().length > 0 || !app["mainWindowOptions"]) { + return false; + } + createWindow(app["mainWindowOptions"], app["mainWindowURL"], "BrowserWindowRecreated"); + return true; + }; + function createWindow(options, loadUrl, createdEventName) { if (options.webPreferences && !("nodeIntegration" in options.webPreferences)) { options = { @@ -226,21 +237,19 @@ module.exports = (socket, app) => { delete options.isRunningBlazor; // we dont want to recreate the window when watch is ready. if (app.commandLine.hasSwitch("watch") && - app["mainWindowURL"] === loadUrl) { + app["mainWindowURL"] === loadUrl && + app["mainWindow"] && + !app["mainWindow"].isDestroyed()) { window = app["mainWindow"]; - if (window) { - window.reload(); - synchronizeWindowRegistry(); - if (!windows.some((entry) => tryGetWindowId(entry) === window.id)) { - windows.push(window); - } - electronSocket.emit("BrowserWindowCreated", window.id); - return; + window.reload(); + synchronizeWindowRegistry(); + if (!windows.some((entry) => tryGetWindowId(entry) === window.id)) { + windows.push(window); } + electronSocket.emit(createdEventName, window.id); + return; } - else { - window = new electron_1.BrowserWindow(options); - } + window = new electron_1.BrowserWindow(options); if (options.proxy) { window.webContents.session.setProxy({ proxyRules: options.proxy }); } @@ -255,18 +264,10 @@ module.exports = (socket, app) => { readyToShowWindowsIds.push(window.id); } }); - lastOptions = options; window.on("closed", () => { synchronizeWindowRegistry(); emitBrowserWindowClosed(); }); - 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); - } - }); if (loadUrl) { // Append authentication token to initial URL if available const token = global["authToken"]; @@ -299,10 +300,14 @@ module.exports = (socket, app) => { if (app["mainWindowURL"] == undefined || app["mainWindowURL"] == "") { app["mainWindowURL"] = loadUrl; app["mainWindow"] = window; + app["mainWindowOptions"] = options; + } + else if (app["mainWindowURL"] === loadUrl) { + app["mainWindow"] = window; } windows.push(window); - electronSocket.emit("BrowserWindowCreated", window.id); - }); + electronSocket.emit(createdEventName, window.id); + } socket.on("browserWindowDestroy", (id) => { getWindowById(id).destroy(); }); diff --git a/src/ElectronNET.Host/api/browserWindows.js.map b/src/ElectronNET.Host/api/browserWindows.js.map index 0cb4245c..6affc0bd 100644 --- a/src/ElectronNET.Host/api/browserWindows.js.map +++ b/src/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/src/ElectronNET.Host/api/browserWindows.ts b/src/ElectronNET.Host/api/browserWindows.ts index 4434f816..cd5c5d05 100644 --- a/src/ElectronNET.Host/api/browserWindows.ts +++ b/src/ElectronNET.Host/api/browserWindows.ts @@ -10,7 +10,6 @@ const windows: Electron.BrowserWindow[] = (global["browserWindows"] = let readyToShowWindowsIds: number[] = []; let window; -let lastOptions; let electronSocket; const proxyToCredentialsMap: { [proxy: string]: string } = (global[ @@ -217,6 +216,26 @@ export = (socket: Socket, app: Electron.App) => { }); socket.on("createBrowserWindow", (options, loadUrl) => { + createWindow(options, loadUrl, "BrowserWindowCreated"); + }); + + // Allows the host (main.js) to bring the main window back when the app is activated + // again on macOS after all windows have been closed. + global["recreateMainWindow"] = () => { + if (BrowserWindow.getAllWindows().length > 0 || !app["mainWindowOptions"]) { + return false; + } + + createWindow( + app["mainWindowOptions"], + app["mainWindowURL"], + "BrowserWindowRecreated", + ); + + return true; + }; + + function createWindow(options, loadUrl, createdEventName: string) { if ( options.webPreferences && !("nodeIntegration" in options.webPreferences) @@ -250,22 +269,24 @@ export = (socket: Socket, app: Electron.App) => { // we dont want to recreate the window when watch is ready. if ( app.commandLine.hasSwitch("watch") && - app["mainWindowURL"] === loadUrl + app["mainWindowURL"] === loadUrl && + app["mainWindow"] && + !app["mainWindow"].isDestroyed() ) { window = app["mainWindow"]; - if (window) { - window.reload(); - synchronizeWindowRegistry(); - if (!windows.some((entry) => tryGetWindowId(entry) === window.id)) { - windows.push(window); - } - electronSocket.emit("BrowserWindowCreated", window.id); - return; + window.reload(); + synchronizeWindowRegistry(); + + if (!windows.some((entry) => tryGetWindowId(entry) === window.id)) { + windows.push(window); } - } else { - window = new BrowserWindow(options); + + electronSocket.emit(createdEventName, window.id); + return; } + window = new BrowserWindow(options); + if (options.proxy) { window.webContents.session.setProxy({ proxyRules: options.proxy }); } @@ -284,21 +305,11 @@ export = (socket: Socket, app: Electron.App) => { } }); - lastOptions = options; - window.on("closed", () => { synchronizeWindowRegistry(); emitBrowserWindowClosed(); }); - 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); - } - }); - if (loadUrl) { // Append authentication token to initial URL if available const token = global["authToken"]; @@ -338,11 +349,14 @@ export = (socket: Socket, app: Electron.App) => { if (app["mainWindowURL"] == undefined || app["mainWindowURL"] == "") { app["mainWindowURL"] = loadUrl; app["mainWindow"] = window; + app["mainWindowOptions"] = options; + } else if (app["mainWindowURL"] === loadUrl) { + app["mainWindow"] = window; } windows.push(window); - electronSocket.emit("BrowserWindowCreated", window.id); - }); + electronSocket.emit(createdEventName, window.id); + } socket.on("browserWindowDestroy", (id) => { getWindowById(id).destroy(); diff --git a/src/ElectronNET.Host/api/webContents.js b/src/ElectronNET.Host/api/webContents.js index 6f77a829..2e2f9931 100644 --- a/src/ElectronNET.Host/api/webContents.js +++ b/src/ElectronNET.Host/api/webContents.js @@ -111,6 +111,41 @@ module.exports = (socket) => { electronSocket.emit("webContents-domReady" + id); }); }); + socket.on("register-webContents-zoomChanged", (id) => { + const browserWindow = getWindowById(id); + browserWindow.webContents.removeAllListeners("zoom-changed"); + browserWindow.webContents.on("zoom-changed", (_, zoomDirection) => { + electronSocket.emit("webContents-zoomChanged" + id, zoomDirection); + }); + }); + socket.on("register-webContents-foundInPage", (id) => { + const browserWindow = getWindowById(id); + browserWindow.webContents.removeAllListeners("found-in-page"); + browserWindow.webContents.on("found-in-page", (_, result) => { + electronSocket.emit("webContents-foundInPage" + id, result); + }); + }); + socket.on("register-webContents-audioStateChanged", (id) => { + const browserWindow = getWindowById(id); + browserWindow.webContents.removeAllListeners("audio-state-changed"); + browserWindow.webContents.on("audio-state-changed", (event) => { + electronSocket.emit("webContents-audioStateChanged" + id, event.audible); + }); + }); + socket.on("register-webContents-mediaStartedPlaying", (id) => { + const browserWindow = getWindowById(id); + browserWindow.webContents.removeAllListeners("media-started-playing"); + browserWindow.webContents.on("media-started-playing", () => { + electronSocket.emit("webContents-mediaStartedPlaying" + id); + }); + }); + socket.on("register-webContents-mediaPaused", (id) => { + const browserWindow = getWindowById(id); + browserWindow.webContents.removeAllListeners("media-paused"); + browserWindow.webContents.on("media-paused", () => { + electronSocket.emit("webContents-mediaPaused" + id); + }); + }); socket.on("webContents-openDevTools", (id, options) => { if (options) { getWindowById(id).webContents.openDevTools(options); @@ -308,6 +343,36 @@ module.exports = (socket) => { electronSocket.emit("webContents-loadURL-error" + id, error); }); }); + socket.on("webContents-loadFile", (id, filePath, options) => { + const browserWindow = getWindowById(id); + browserWindow.webContents + .loadFile(filePath, options ?? undefined) + .then(() => { + electronSocket.emit("webContents-loadFile-complete" + id); + }) + .catch((error) => { + console.error(error); + electronSocket.emit("webContents-loadFile-error" + id, error); + }); + }); + socket.on("webContents-isLoading", (id) => { + electronSocket.emit("webContents-isLoading-completed", getWindowById(id).webContents.isLoading()); + }); + socket.on("webContents-isLoadingMainFrame", (id) => { + electronSocket.emit("webContents-isLoadingMainFrame-completed", getWindowById(id).webContents.isLoadingMainFrame()); + }); + socket.on("webContents-isWaitingForResponse", (id) => { + electronSocket.emit("webContents-isWaitingForResponse-completed", getWindowById(id).webContents.isWaitingForResponse()); + }); + socket.on("webContents-reload", (id) => { + getWindowById(id).webContents.reload(); + }); + socket.on("webContents-reloadIgnoringCache", (id) => { + getWindowById(id).webContents.reloadIgnoringCache(); + }); + socket.on("webContents-stop", (id) => { + getWindowById(id).webContents.stop(); + }); socket.on("webContents-insertCSS", (id, isBrowserWindow, path) => { if (isBrowserWindow) { const browserWindow = getWindowById(id); @@ -330,6 +395,14 @@ module.exports = (socket) => { } } }); + socket.on("webContents-insertCSSText", async (id, css, cssOrigin) => { + const key = await getWindowById(id).webContents.insertCSS(css, cssOrigin ? { cssOrigin } : undefined); + electronSocket.emit("webContents-insertCSSText-completed" + id, key); + }); + socket.on("webContents-removeInsertedCSS", async (id, key) => { + await getWindowById(id).webContents.removeInsertedCSS(key); + electronSocket.emit("webContents-removeInsertedCSS-completed" + id); + }); socket.on("webContents-session-getAllExtensions", (id) => { const browserWindow = getWindowById(id); const extensionsList = browserWindow.webContents.session.getAllExtensions(); @@ -403,6 +476,65 @@ module.exports = (socket) => { socket.on("webContents-setUserAgent", (id, userAgent) => { getWindowById(id).webContents.setUserAgent(userAgent); }); + socket.on("webContents-undo", (id) => { + getWindowById(id).webContents.undo(); + }); + socket.on("webContents-redo", (id) => { + getWindowById(id).webContents.redo(); + }); + socket.on("webContents-cut", (id) => { + getWindowById(id).webContents.cut(); + }); + socket.on("webContents-copy", (id) => { + getWindowById(id).webContents.copy(); + }); + socket.on("webContents-copyImageAt", (id, x, y) => { + getWindowById(id).webContents.copyImageAt(x, y); + }); + socket.on("webContents-paste", (id) => { + getWindowById(id).webContents.paste(); + }); + socket.on("webContents-pasteAndMatchStyle", (id) => { + getWindowById(id).webContents.pasteAndMatchStyle(); + }); + socket.on("webContents-delete", (id) => { + getWindowById(id).webContents.delete(); + }); + socket.on("webContents-selectAll", (id) => { + getWindowById(id).webContents.selectAll(); + }); + socket.on("webContents-unselect", (id) => { + getWindowById(id).webContents.unselect(); + }); + socket.on("webContents-adjustSelection", (id, options) => { + getWindowById(id).webContents.adjustSelection(options ?? {}); + }); + socket.on("webContents-centerSelection", (id) => { + getWindowById(id).webContents.centerSelection(); + }); + socket.on("webContents-scrollToTop", (id) => { + getWindowById(id).webContents.scrollToTop(); + }); + socket.on("webContents-scrollToBottom", (id) => { + getWindowById(id).webContents.scrollToBottom(); + }); + socket.on("webContents-insertText", async (id, text) => { + await getWindowById(id).webContents.insertText(text); + electronSocket.emit("webContents-insertText-completed" + id); + }); + socket.on("webContents-replace", (id, text) => { + getWindowById(id).webContents.replace(text); + }); + socket.on("webContents-replaceMisspelling", (id, text) => { + getWindowById(id).webContents.replaceMisspelling(text); + }); + socket.on("webContents-findInPage", (id, text, options) => { + const requestId = getWindowById(id).webContents.findInPage(text, options ?? undefined); + electronSocket.emit("webContents-findInPage-completed" + id, requestId); + }); + socket.on("webContents-stopFindInPage", (id, action) => { + getWindowById(id).webContents.stopFindInPage(action); + }); function getWindowById(id) { if (id >= 1000) { return (0, browserView_1.browserViewMediateService)(id - 1000); diff --git a/src/ElectronNET.Host/api/webContents.js.map b/src/ElectronNET.Host/api/webContents.js.map index 9ae7081c..ea9563bf 100644 --- a/src/ElectronNET.Host/api/webContents.js.map +++ b/src/ElectronNET.Host/api/webContents.js.map @@ -1 +1 @@ -{"version":3,"file":"webContents.js","sourceRoot":"","sources":["webContents.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"webContents.js","sourceRoot":"","sources":["webContents.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AAEzB,uCAAsD;AAEtD,+CAA0D;AAE1D,IAAI,cAAsB,CAAC;AAE3B,iBAAS,CAAC,MAAc,EAAE,EAAE;IAC1B,cAAc,GAAG,MAAM,CAAC;IAExB,oDAAoD;IACpD,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,CAAC,EAAE,EAAE,EAAE;QAC/C,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QACxD,iDAAiD;QACjD,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE;YACxD,cAAc,CAAC,IAAI,CAAC,qBAAqB,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,oCAAoC,EAAE,CAAC,EAAE,EAAE,EAAE;QACrD,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;YACnD,cAAc,CAAC,IAAI,CAAC,2BAA2B,GAAG,EAAE,CAAC,CAAC;QACxD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yCAAyC,EAAE,CAAC,EAAE,EAAE,EAAE;QAC1D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,sBAAsB,CAAC,CAAC;QACrE,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC,sBAAsB,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;YAC9D,cAAc,CAAC,IAAI,CAAC,gCAAgC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,CAAC,EAAE,EAAE,EAAE;QACnD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;QAC7D,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,gBAAgB,EAAE,EAAE;YACxE,cAAc,CAAC,IAAI,CAAC,yBAAyB,GAAG,EAAE,EAAE;gBAClD,GAAG;gBACH,gBAAgB;aACjB,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,mCAAmC,EAAE,CAAC,EAAE,EAAE,EAAE;QACpD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;QAC9D,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;YACvD,cAAc,CAAC,IAAI,CAAC,0BAA0B,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QAC5D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,CAAC,EAAE,EAAE,EAAE;QACnD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;QAC9D,aAAa,CAAC,WAAW,CAAC,EAAE,CAC1B,eAAe,EACf,CAAC,CAAC,EAAE,SAAS,EAAE,YAAY,EAAE,EAAE;YAC7B,cAAc,CAAC,IAAI,CAAC,yBAAyB,GAAG,EAAE,EAAE;gBAClD,SAAS;gBACT,YAAY;aACb,CAAC,CAAC;QACL,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,4CAA4C,EAAE,CAAC,EAAE,EAAE,EAAE;QAC7D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,yBAAyB,CAAC,CAAC;QACxE,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE;YACjE,cAAc,CAAC,IAAI,CAAC,mCAAmC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,CAAC,EAAE,EAAE,EAAE;QACnD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,aAAa,CAAC,CAAC;QAC5D,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE;YAC3D,IAAI,SAAS,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC9B,cAAc,CAAC,IAAI,CAAC,yBAAyB,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;YACjE,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,+BAA+B,EAAE,CAAC,EAAE,EAAE,EAAE;QAChD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC;QAC1D,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE;YAC7C,cAAc,CAAC,IAAI,CAAC,sBAAsB,GAAG,EAAE,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,CAAC,EAAE,EAAE,EAAE;QACnD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;QAC7D,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC,cAAc,EAAE,CAAC,CAAC,EAAE,aAAa,EAAE,EAAE;YAChE,cAAc,CAAC,IAAI,CAAC,yBAAyB,GAAG,EAAE,EAAE,aAAa,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,CAAC,EAAE,EAAE,EAAE;QACnD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;QAC9D,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC,eAAe,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE;YAC1D,cAAc,CAAC,IAAI,CAAC,yBAAyB,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,wCAAwC,EAAE,CAAC,EAAE,EAAE,EAAE;QACzD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,qBAAqB,CAAC,CAAC;QACpE,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC,qBAAqB,EAAE,CAAC,KAAK,EAAE,EAAE;YAC5D,cAAc,CAAC,IAAI,CAAC,+BAA+B,GAAG,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,0CAA0C,EAAE,CAAC,EAAE,EAAE,EAAE;QAC3D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,uBAAuB,CAAC,CAAC;QACtE,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;YACzD,cAAc,CAAC,IAAI,CAAC,iCAAiC,GAAG,EAAE,CAAC,CAAC;QAC9D,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,CAAC,EAAE,EAAE,EAAE;QACnD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QAExC,aAAa,CAAC,WAAW,CAAC,kBAAkB,CAAC,cAAc,CAAC,CAAC;QAC7D,aAAa,CAAC,WAAW,CAAC,EAAE,CAAC,cAAc,EAAE,GAAG,EAAE;YAChD,cAAc,CAAC,IAAI,CAAC,yBAAyB,GAAG,EAAE,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,0BAA0B,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE;QACpD,IAAI,OAAO,EAAE,CAAC;YACZ,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;QACtD,CAAC;aAAM,CAAC;YACN,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;QAC/C,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE;QAChD,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,gBAAgB,EAAE,CAAC;QACxE,cAAc,CAAC,IAAI,CAAC,mCAAmC,EAAE,QAAQ,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,mBAAmB,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,EAAE;QACxD,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnD,cAAc,CAAC,IAAI,CAAC,6BAA6B,EAAE,IAAI,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,wBAAwB,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE;QACnE,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;YACnC,IAAI,KAAK,EAAE,CAAC;gBACV,cAAc,CAAC,IAAI,CAAC,kCAAkC,EAAE,KAAK,CAAC,CAAC;YACjE,CAAC;iBAAM,CAAC;gBACN,cAAc,CAAC,IAAI,CAAC,kCAAkC,EAAE,IAAI,CAAC,CAAC;YAChE,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CACP,+BAA+B,EAC/B,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,GAAG,KAAK,EAAE,EAAE;QACtC,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,iBAAiB,CAClE,IAAI,EACJ,WAAW,CACZ,CAAC;QACF,cAAc,CAAC,IAAI,CAAC,yCAAyC,EAAE,MAAM,CAAC,CAAC;IACzE,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,UAAU,EAAE;QAC1C,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,cAAc,CAAC,IAAI,CACjB,oBAAoB,GAAG,EAAE,EACzB,aAAa,CAAC,WAAW,CAAC,MAAM,EAAE,CACnC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CACP,oDAAoD,EACpD,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE;QACd,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,8BAA8B,CAAC,OAAO,CAAC,CAAC;IAC5E,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,EAAE,CAAC,oCAAoC,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE;QAChE,sDAAsD;QACtD,MAAM,aAAa,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7C,IAAI,IAAY,CAAC;QACjB,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACtB,aAAa;YACb,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACf,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC3D,CAAC;aAAM,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACf,IAAI,CAAC;gBACH,aAAa;gBACb,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YAClE,CAAC;YAAC,MAAM,CAAC;gBACP,kFAAkF;gBAClF,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;YAC3D,CAAC;QACH,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,qBAAqB;QAC/B,CAAC;QACD,cAAc,CAAC,IAAI,CAAC,8CAA8C,GAAG,IAAI,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gCAAgC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;QAC7D,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;IACzE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,4CAA4C,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;QACzE,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,sBAAsB,EAAE,CAAC;QAEjE,cAAc,CAAC,IAAI,CACjB,sDAAsD,GAAG,IAAI,CAC9D,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,sCAAsC,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,gBAAgB,CAAC,EAAE,CAAC,CAAC;QAE7D,cAAc,CAAC,IAAI,CACjB,gDAAgD,GAAG,IAAI,CACxD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CACP,8CAA8C,EAC9C,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QAC1B,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,CACjB,wDAAwD,GAAG,IAAI,CAChE,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,EAAE,CAAC,+CAA+C,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE;QACzE,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,6CAA6C,EAAE,CAAC,EAAE,EAAE,EAAE;QAC9D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAC9D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,4CAA4C,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE;QACtE,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACpE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,sCAAsC,EAAE,CAAC,EAAE,EAAE,EAAE;QACvD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,gBAAgB,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,EAAE;QAC1E,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,MAAM,GACV,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QAElE,cAAc,CAAC,IAAI,CACjB,2CAA2C,GAAG,IAAI,EAClD,MAAM,CAAC,MAAM,CACd,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;QAC/D,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,CACjB,4CAA4C,GAAG,IAAI,EACnD,IAAI,CACL,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;QACxD,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,CACjB,2CAA2C,GAAG,IAAI,EAClD,QAAQ,CACT,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;QACzD,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,CACjB,4CAA4C,GAAG,IAAI,EACnD,SAAS,CACV,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE;QACpE,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,CACjB,4CAA4C,GAAG,IAAI,EACnD,KAAK,CACN,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,qCAAqC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;QAC5D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE;QAC5D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,KAAK,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,EAAE;QAC1E,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;IACvE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CACP,kCAAkC,EAClC,CAAC,EAAE,EAAE,SAAS,EAAE,eAAe,EAAE,EAAE;QACjC,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,YAAY,CAC5C,SAAS,EACT,eAAe,CAChB,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,EAAE,CACP,yDAAyD,EACzD,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE;QACb,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC;QAElD,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE;YAC/D,MAAM,CAAC,IAAI,CACT,iDAAiD,EAAE,EAAE,EACrD,OAAO,CACR,CAAC;YACF,wDAAwD;YACxD,cAAc,CAAC,IAAI,CACjB,0DAA0D,EAAE,EAAE,EAC9D,CAAC,QAAQ,EAAE,EAAE;gBACX,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACrB,CAAC,CACF,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,EAAE,CAAC,8CAA8C,EAAE,CAAC,EAAE,EAAE,EAAE;QAC/D,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,CAC1C,SAAS,EACT,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YAChC,cAAc,CAAC,IAAI,CAAC,qCAAqC,GAAG,EAAE,EAAE;gBAC9D,MAAM;gBACN,KAAK;gBACL,OAAO;aACR,CAAC,CAAC;QACL,CAAC,CACF,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;QACtE,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,CACjB,2CAA2C,GAAG,IAAI,EAClD,OAAO,CACR,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,KAAK,EAAE,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;QACvE,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;IAC1E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CACP,oCAAoC,EACpC,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE;QAC5B,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,CACjB,8CAA8C,GAAG,IAAI,CACtD,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,EAAE,CAAC,wCAAwC,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;QACrE,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,CACjB,kDAAkD,GAAG,IAAI,CAC1D,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,qBAAqB,EAAE,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QACpD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW;aACtB,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC;aACrB,IAAI,CAAC,GAAG,EAAE;YACT,cAAc,CAAC,IAAI,CAAC,8BAA8B,GAAG,EAAE,CAAC,CAAC;QAC3D,CAAC,CAAC;aACD,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;QAC/D,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,sBAAsB,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE;QAC1D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW;aACtB,QAAQ,CAAC,QAAQ,EAAE,OAAO,IAAI,SAAS,CAAC;aACxC,IAAI,CAAC,GAAG,EAAE;YACT,cAAc,CAAC,IAAI,CAAC,+BAA+B,GAAG,EAAE,CAAC,CAAC;QAC5D,CAAC,CAAC;aACD,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;YACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACrB,cAAc,CAAC,IAAI,CAAC,4BAA4B,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;QAChE,CAAC,CAAC,CAAC;IACP,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,uBAAuB,EAAE,CAAC,EAAE,EAAE,EAAE;QACxC,cAAc,CAAC,IAAI,CACjB,iCAAiC,EACjC,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,SAAS,EAAE,CAC1C,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gCAAgC,EAAE,CAAC,EAAE,EAAE,EAAE;QACjD,cAAc,CAAC,IAAI,CACjB,0CAA0C,EAC1C,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,kBAAkB,EAAE,CACnD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kCAAkC,EAAE,CAAC,EAAE,EAAE,EAAE;QACnD,cAAc,CAAC,IAAI,CACjB,4CAA4C,EAC5C,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,oBAAoB,EAAE,CACrD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,EAAE,EAAE,EAAE;QACrC,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iCAAiC,EAAE,CAAC,EAAE,EAAE,EAAE;QAClD,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,mBAAmB,EAAE,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,EAAE,EAAE,EAAE;QACnC,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,uBAAuB,EAAE,CAAC,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,EAAE;QAC/D,IAAI,eAAe,EAAE,CAAC;YACpB,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;YACxC,IAAI,aAAa,EAAE,CAAC;gBAClB,aAAa,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;YACrE,CAAC;QACH,CAAC;aAAM,CAAC;YACN,MAAM,YAAY,GAAkB,CAAC,MAAM,CAAC,cAAc,CAAC;gBACzD,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,CAAkB,CAAC;YACjD,IAAI,IAAI,GAAgB,IAAI,CAAC;YAC7B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,YAAY,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7C,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,EAAE,EAAE,CAAC;oBACxC,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;oBACvB,MAAM;gBACR,CAAC;YACH,CAAC;YACD,IAAI,IAAI,EAAE,CAAC;gBACT,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,2BAA2B,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE;QAClE,MAAM,GAAG,GAAG,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,SAAS,CACvD,GAAG,EACH,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,SAAS,CACtC,CAAC;QACF,cAAc,CAAC,IAAI,CAAC,qCAAqC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,+BAA+B,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE;QAC3D,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAC3D,cAAc,CAAC,IAAI,CAAC,yCAAyC,GAAG,EAAE,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,sCAAsC,EAAE,CAAC,EAAE,EAAE,EAAE;QACvD,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,CAAC,GAAG,EAAE,EAAE;YAC1C,mBAAmB,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,cAAc,CAAC,IAAI,CACjB,gDAAgD,EAChD,mBAAmB,CACpB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,qCAAqC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;QAC5D,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CACP,mCAAmC,EACnC,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,GAAG,KAAK,EAAE,EAAE;QAC1C,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,aAAa,CACrE,IAAI,EACJ,EAAE,eAAe,EAAE,eAAe,EAAE,CACrC,CAAC;QAEF,cAAc,CAAC,IAAI,CACjB,6CAA6C,EAC7C,SAAS,CACV,CAAC;IACJ,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,EAAE,CAAC,2BAA2B,EAAE,CAAC,EAAE,EAAE,EAAE;QAC5C,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,IAAI,GAAG,aAAa,CAAC,WAAW,CAAC,aAAa,EAAE,CAAC;QACvD,cAAc,CAAC,IAAI,CAAC,qCAAqC,EAAE,IAAI,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,2BAA2B,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE;QACpD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,0BAA0B,EAAE,CAAC,EAAE,EAAE,EAAE;QAC3C,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,aAAa,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;QACzD,cAAc,CAAC,IAAI,CAAC,oCAAoC,EAAE,OAAO,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,0BAA0B,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE;QAClD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,aAAa,CAAC,WAAW,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CACP,sCAAsC,EACtC,KAAK,EAAE,EAAE,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE;QACvC,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,MAAM,aAAa,CAAC,WAAW,CAAC,wBAAwB,CACtD,YAAY,EACZ,YAAY,CACb,CAAC;QACF,cAAc,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;IACxE,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,EAAE,CAAC,4BAA4B,EAAE,CAAC,EAAE,EAAE,EAAE;QAC7C,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,cAAc,EAAE,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,2BAA2B,EAAE,CAAC,EAAE,EAAE,EAAE;QAC5C,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,aAAa,EAAE,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,8BAA8B,EAAE,UAAU,EAAE;QACpD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,cAAc,CAAC,IAAI,CACjB,wCAAwC,EACxC,aAAa,CAAC,WAAW,CAAC,gBAAgB,EAAE,CAC7C,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,+BAA+B,EAAE,UAAU,EAAE;QACrD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,cAAc,CAAC,IAAI,CACjB,yCAAyC,EACzC,aAAa,CAAC,WAAW,CAAC,iBAAiB,EAAE,CAC9C,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,2BAA2B,EAAE,CAAC,EAAE,EAAE,KAAK,EAAE,EAAE;QACnD,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,0BAA0B,EAAE,UAAU,EAAE;QAChD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,cAAc,CAAC,IAAI,CACjB,oCAAoC,EACpC,aAAa,CAAC,WAAW,CAAC,YAAY,EAAE,CACzC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gCAAgC,EAAE,UAAU,EAAE;QACtD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,cAAc,CAAC,IAAI,CACjB,0CAA0C,EAC1C,aAAa,CAAC,WAAW,CAAC,kBAAkB,EAAE,CAC/C,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,0BAA0B,EAAE,UAAU,EAAE;QAChD,MAAM,aAAa,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;QACxC,cAAc,CAAC,IAAI,CACjB,oCAAoC,EACpC,aAAa,CAAC,WAAW,CAAC,YAAY,EAAE,CACzC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,0BAA0B,EAAE,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE;QACtD,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,EAAE,EAAE,EAAE;QACnC,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,EAAE,EAAE,EAAE;QACnC,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,EAAE,EAAE,EAAE;QAClC,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,kBAAkB,EAAE,CAAC,EAAE,EAAE,EAAE;QACnC,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;QAChD,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,EAAE,EAAE,EAAE;QACpC,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gCAAgC,EAAE,CAAC,EAAE,EAAE,EAAE;QACjD,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,kBAAkB,EAAE,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,EAAE,EAAE,EAAE;QACrC,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,MAAM,EAAE,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,uBAAuB,EAAE,CAAC,EAAE,EAAE,EAAE;QACxC,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,sBAAsB,EAAE,CAAC,EAAE,EAAE,EAAE;QACvC,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,QAAQ,EAAE,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,6BAA6B,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE;QACvD,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,eAAe,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,6BAA6B,EAAE,CAAC,EAAE,EAAE,EAAE;QAC9C,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,yBAAyB,EAAE,CAAC,EAAE,EAAE,EAAE;QAC1C,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,4BAA4B,EAAE,CAAC,EAAE,EAAE,EAAE;QAC7C,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,cAAc,EAAE,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,wBAAwB,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE;QACrD,MAAM,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACrD,cAAc,CAAC,IAAI,CAAC,kCAAkC,GAAG,EAAE,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,qBAAqB,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;QAC5C,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,gCAAgC,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE;QACvD,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACzD,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,wBAAwB,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;QACxD,MAAM,SAAS,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,UAAU,CACxD,IAAI,EACJ,OAAO,IAAI,SAAS,CACrB,CAAC;QACF,cAAc,CAAC,IAAI,CAAC,kCAAkC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;IAC1E,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,4BAA4B,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE;QACrD,aAAa,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,SAAS,aAAa,CACpB,EAAU;QAEV,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;YACf,OAAO,IAAA,uCAAyB,EAAC,EAAE,GAAG,IAAI,CAAC,CAAC;QAC9C,CAAC;QAED,OAAO,wBAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAClC,CAAC;AACH,CAAC,CAAC"} \ No newline at end of file diff --git a/src/ElectronNET.Host/api/webContents.ts b/src/ElectronNET.Host/api/webContents.ts index 42466526..2104fe38 100644 --- a/src/ElectronNET.Host/api/webContents.ts +++ b/src/ElectronNET.Host/api/webContents.ts @@ -103,6 +103,51 @@ export = (socket: Socket) => { }); }); + socket.on("register-webContents-zoomChanged", (id) => { + const browserWindow = getWindowById(id); + + browserWindow.webContents.removeAllListeners("zoom-changed"); + browserWindow.webContents.on("zoom-changed", (_, zoomDirection) => { + electronSocket.emit("webContents-zoomChanged" + id, zoomDirection); + }); + }); + + socket.on("register-webContents-foundInPage", (id) => { + const browserWindow = getWindowById(id); + + browserWindow.webContents.removeAllListeners("found-in-page"); + browserWindow.webContents.on("found-in-page", (_, result) => { + electronSocket.emit("webContents-foundInPage" + id, result); + }); + }); + + socket.on("register-webContents-audioStateChanged", (id) => { + const browserWindow = getWindowById(id); + + browserWindow.webContents.removeAllListeners("audio-state-changed"); + browserWindow.webContents.on("audio-state-changed", (event) => { + electronSocket.emit("webContents-audioStateChanged" + id, event.audible); + }); + }); + + socket.on("register-webContents-mediaStartedPlaying", (id) => { + const browserWindow = getWindowById(id); + + browserWindow.webContents.removeAllListeners("media-started-playing"); + browserWindow.webContents.on("media-started-playing", () => { + electronSocket.emit("webContents-mediaStartedPlaying" + id); + }); + }); + + socket.on("register-webContents-mediaPaused", (id) => { + const browserWindow = getWindowById(id); + + browserWindow.webContents.removeAllListeners("media-paused"); + browserWindow.webContents.on("media-paused", () => { + electronSocket.emit("webContents-mediaPaused" + id); + }); + }); + socket.on("webContents-openDevTools", (id, options) => { if (options) { getWindowById(id).webContents.openDevTools(options); @@ -409,6 +454,52 @@ export = (socket: Socket) => { }); }); + socket.on("webContents-loadFile", (id, filePath, options) => { + const browserWindow = getWindowById(id); + browserWindow.webContents + .loadFile(filePath, options ?? undefined) + .then(() => { + electronSocket.emit("webContents-loadFile-complete" + id); + }) + .catch((error) => { + console.error(error); + electronSocket.emit("webContents-loadFile-error" + id, error); + }); + }); + + socket.on("webContents-isLoading", (id) => { + electronSocket.emit( + "webContents-isLoading-completed", + getWindowById(id).webContents.isLoading(), + ); + }); + + socket.on("webContents-isLoadingMainFrame", (id) => { + electronSocket.emit( + "webContents-isLoadingMainFrame-completed", + getWindowById(id).webContents.isLoadingMainFrame(), + ); + }); + + socket.on("webContents-isWaitingForResponse", (id) => { + electronSocket.emit( + "webContents-isWaitingForResponse-completed", + getWindowById(id).webContents.isWaitingForResponse(), + ); + }); + + socket.on("webContents-reload", (id) => { + getWindowById(id).webContents.reload(); + }); + + socket.on("webContents-reloadIgnoringCache", (id) => { + getWindowById(id).webContents.reloadIgnoringCache(); + }); + + socket.on("webContents-stop", (id) => { + getWindowById(id).webContents.stop(); + }); + socket.on("webContents-insertCSS", (id, isBrowserWindow, path) => { if (isBrowserWindow) { const browserWindow = getWindowById(id); @@ -431,6 +522,19 @@ export = (socket: Socket) => { } }); + socket.on("webContents-insertCSSText", async (id, css, cssOrigin) => { + const key = await getWindowById(id).webContents.insertCSS( + css, + cssOrigin ? { cssOrigin } : undefined, + ); + electronSocket.emit("webContents-insertCSSText-completed" + id, key); + }); + + socket.on("webContents-removeInsertedCSS", async (id, key) => { + await getWindowById(id).webContents.removeInsertedCSS(key); + electronSocket.emit("webContents-removeInsertedCSS-completed" + id); + }); + socket.on("webContents-session-getAllExtensions", (id) => { const browserWindow = getWindowById(id); const extensionsList = browserWindow.webContents.session.getAllExtensions(); @@ -557,6 +661,87 @@ export = (socket: Socket) => { getWindowById(id).webContents.setUserAgent(userAgent); }); + socket.on("webContents-undo", (id) => { + getWindowById(id).webContents.undo(); + }); + + socket.on("webContents-redo", (id) => { + getWindowById(id).webContents.redo(); + }); + + socket.on("webContents-cut", (id) => { + getWindowById(id).webContents.cut(); + }); + + socket.on("webContents-copy", (id) => { + getWindowById(id).webContents.copy(); + }); + + socket.on("webContents-copyImageAt", (id, x, y) => { + getWindowById(id).webContents.copyImageAt(x, y); + }); + + socket.on("webContents-paste", (id) => { + getWindowById(id).webContents.paste(); + }); + + socket.on("webContents-pasteAndMatchStyle", (id) => { + getWindowById(id).webContents.pasteAndMatchStyle(); + }); + + socket.on("webContents-delete", (id) => { + getWindowById(id).webContents.delete(); + }); + + socket.on("webContents-selectAll", (id) => { + getWindowById(id).webContents.selectAll(); + }); + + socket.on("webContents-unselect", (id) => { + getWindowById(id).webContents.unselect(); + }); + + socket.on("webContents-adjustSelection", (id, options) => { + getWindowById(id).webContents.adjustSelection(options ?? {}); + }); + + socket.on("webContents-centerSelection", (id) => { + getWindowById(id).webContents.centerSelection(); + }); + + socket.on("webContents-scrollToTop", (id) => { + getWindowById(id).webContents.scrollToTop(); + }); + + socket.on("webContents-scrollToBottom", (id) => { + getWindowById(id).webContents.scrollToBottom(); + }); + + socket.on("webContents-insertText", async (id, text) => { + await getWindowById(id).webContents.insertText(text); + electronSocket.emit("webContents-insertText-completed" + id); + }); + + socket.on("webContents-replace", (id, text) => { + getWindowById(id).webContents.replace(text); + }); + + socket.on("webContents-replaceMisspelling", (id, text) => { + getWindowById(id).webContents.replaceMisspelling(text); + }); + + socket.on("webContents-findInPage", (id, text, options) => { + const requestId = getWindowById(id).webContents.findInPage( + text, + options ?? undefined, + ); + electronSocket.emit("webContents-findInPage-completed" + id, requestId); + }); + + socket.on("webContents-stopFindInPage", (id, action) => { + getWindowById(id).webContents.stopFindInPage(action); + }); + function getWindowById( id: number, ): Electron.BrowserWindow | Electron.BrowserView { diff --git a/src/ElectronNET.Host/main.js b/src/ElectronNET.Host/main.js index 47168da2..c182ef3e 100644 --- a/src/ElectronNET.Host/main.js +++ b/src/ElectronNET.Host/main.js @@ -29,32 +29,11 @@ let electronforcedport; let electronUrl; let authToken = randomUUID().split('-').join(''); -if (app.commandLine.hasSwitch('manifest')) { - manifestJsonFileName = app.commandLine.getSwitchValue('manifest'); -} - -if (app.commandLine.hasSwitch('unpackedelectron')) { - unpackedelectron = true; -} -else if (app.commandLine.hasSwitch('unpackeddotnet')) { - unpackeddotnet = true; -} -else if (app.commandLine.hasSwitch('dotnetpacked')) { - dotnetpacked = true; -} - -if (app.commandLine.hasSwitch('electronforcedport')) { - electronforcedport = +app.commandLine.getSwitchValue('electronforcedport'); -} - // Store in global for access by browser windows global.authToken = authToken; -if (app.commandLine.hasSwitch('electronurl')) { - electronUrl = app.commandLine.getSwitchValue('electronurl'); -} - // Custom startup hook: look for custom_main.js and invoke its onStartup(host) if present. +// Runs before any command line switch is evaluated so the hook can still modify them. // If the hook returns false, abort Electron startup. try { const fs = require('fs'); @@ -77,6 +56,28 @@ try { console.error('Error while executing custom_main.js:', err); } +if (app.commandLine.hasSwitch('manifest')) { + manifestJsonFileName = app.commandLine.getSwitchValue('manifest'); +} + +if (app.commandLine.hasSwitch('unpackedelectron')) { + unpackedelectron = true; +} +else if (app.commandLine.hasSwitch('unpackeddotnet')) { + unpackeddotnet = true; +} +else if (app.commandLine.hasSwitch('dotnetpacked')) { + dotnetpacked = true; +} + +if (app.commandLine.hasSwitch('electronforcedport')) { + electronforcedport = +app.commandLine.getSwitchValue('electronforcedport'); +} + +if (app.commandLine.hasSwitch('electronurl')) { + electronUrl = app.commandLine.getSwitchValue('electronurl'); +} + const currentPath = __dirname; let currentBinPath = path.join(currentPath.replace('app.asar', ''), 'bin'); let manifestJsonFilePath = path.join(currentPath, manifestJsonFileName); @@ -103,9 +104,44 @@ app.on('will-finish-launching', () => { const manifestJsonFile = require(manifestJsonFilePath); +// Brings the app back to the foreground: focuses an already existing window or - if +// all windows have been closed (which keeps the app alive on macOS) - recreates the +// main window. +function activateApp() { + const windows = BrowserWindow.getAllWindows().filter((window) => !window.isDestroyed()); + + if (!windows.length) { + return typeof global.recreateMainWindow === 'function' && global.recreateMainWindow(); + } + + const target = windows.find((window) => window.isVisible()) || windows[0]; + + if (target.isMinimized()) { + target.restore(); + } + + if (!target.isVisible()) { + target.show(); + } + + target.focus(); + + if (platform() === 'darwin') { + // On macOS focusing a window does not necessarily bring the app itself to the front + app.focus({ steal: true }); + } + + return true; +} + if (manifestJsonFile.singleInstance) { - const mainInstance = app.requestSingleInstanceLock(); - app.on('second-instance', (events, args = []) => { + if (!app.requestSingleInstanceLock()) { + // Another instance already owns the lock. Exit right away so that neither the + // socket bridge nor the .NET backend process of this instance is started. + app.exit(0); + } + + app.on('second-instance', (event, args = []) => { args.forEach((parameter) => { const words = parameter.split('='); @@ -116,20 +152,16 @@ if (manifestJsonFile.singleInstance) { } }); - const windows = BrowserWindow.getAllWindows(); - if (windows.length) { - if (windows[0].isMinimized()) { - windows[0].restore(); - } - windows[0].focus(); - } + activateApp(); }); - - if (!mainInstance) { - app.quit(); - } } +// On macOS launching an already running app (or clicking its dock icon) does not +// start a second instance - the 'activate' event is raised instead. +app.on('activate', () => { + activateApp(); +}); + // Collect user supplied command line args (excluding those handled by Electron host itself) function getForwardedArgs() { const skipSwitches = new Set(['unpackedelectron', 'unpackeddotnet', 'dotnetpacked']); @@ -144,6 +176,7 @@ function getForwardedArgs() { if (cleaned.startsWith('remote-debugging-port')) return false; // We add /electronPort ourselves later if (cleaned.startsWith('electronPort=')) return false; + if (cleaned.startsWith('electronHost=')) return false; if (cleaned.startsWith('electronWebPort=')) return false; return true; }); @@ -264,7 +297,6 @@ function startSocketApiBridge(port) { // otherwise the Windows Firewall will be triggered console.debug('Electron Socket: starting...'); server = createServer(); - const host = !port ? '127.0.0.1' : 'localhost'; let hostHook; io = new Server({ pingTimeout: 60000, // in ms, default is 5000 @@ -272,16 +304,35 @@ function startSocketApiBridge(port) { }); io.attach(server); - server.listen(port, host); + // Never bind to the 'localhost' hostname: it may resolve to ::1 and 127.0.0.1 in any + // order, so server and client can end up on different stacks - which costs a failed + // connection attempt (or a DNS lookup) on every startup. + const hostCandidates = ['127.0.0.1', '::1']; + let hostIndex = 0; + + server.on('error', (error) => { + const isUnavailable = error.code === 'EADDRNOTAVAIL' || error.code === 'EAFNOSUPPORT' || error.code === 'EINVAL'; + + if (isUnavailable && hostIndex + 1 < hostCandidates.length) { + console.warn(`Electron Socket: cannot bind to ${hostCandidates[hostIndex]} (${error.code}), falling back to ${hostCandidates[hostIndex + 1]}.`); + hostIndex++; + server.listen(port, hostCandidates[hostIndex]); + return; + } + + console.error('Electron Socket: ' + error.message); + }); + + server.listen(port, hostCandidates[hostIndex]); server.on('listening', function () { const addr = server.address(); console.info(`Electron Socket: listening on port ${addr.port} at ${addr.address} using ${authToken}`); // Now that socket connection is established, we can guarantee port will not be open for portscanner if (unpackedelectron) { - startAspCoreBackendUnpackaged(addr.port); + startAspCoreBackendUnpackaged(addr.port, addr.address); } else if (!unpackeddotnet && !dotnetpacked) { - startAspCoreBackend(addr.port); + startAspCoreBackend(addr.port, addr.address); } }); @@ -385,7 +436,7 @@ function startSocketApiBridge(port) { }); } -function startAspCoreBackend(electronPort) { +function startAspCoreBackend(electronPort, electronHost) { startBackend(); function startBackend() { @@ -394,6 +445,7 @@ function startAspCoreBackend(electronPort) { const parameters = [ envParam, `/electronPort=${electronPort}`, + `/electronHost=${electronHost}`, `/electronPID=${process.pid}`, `/electronAuthToken=${authToken}`, // forward user supplied args (avoid duplicate environment) @@ -416,7 +468,7 @@ function startAspCoreBackend(electronPort) { } } -function startAspCoreBackendUnpackaged(electronPort) { +function startAspCoreBackendUnpackaged(electronPort, electronHost) { startBackend(); function startBackend() { @@ -425,6 +477,7 @@ function startAspCoreBackendUnpackaged(electronPort) { const parameters = [ envParam, `/electronPort=${electronPort}`, + `/electronHost=${electronHost}`, `/electronPID=${process.pid}`, `/electronAuthToken=${authToken}`, ...forwardedArgs.filter(a => !(envParam && a.startsWith('--environment='))) diff --git a/src/ElectronNET.Host/package-lock.json b/src/ElectronNET.Host/package-lock.json index f597f6ae..32c98eba 100644 --- a/src/ElectronNET.Host/package-lock.json +++ b/src/ElectronNET.Host/package-lock.json @@ -17,7 +17,7 @@ }, "devDependencies": { "@types/node": "^22.18", - "electron": "^30.0.3", + "electron": "^39.8.10", "eslint": "^9.39.1", "typescript": "^5.9.3" } @@ -762,15 +762,15 @@ "optional": true }, "node_modules/electron": { - "version": "30.5.1", - "resolved": "https://registry.npmjs.org/electron/-/electron-30.5.1.tgz", - "integrity": "sha512-AhL7+mZ8Lg14iaNfoYTkXQ2qee8mmsQyllKdqxlpv/zrKgfxz6jNVtcRRbQtLxtF8yzcImWdfTQROpYiPumdbw==", + "version": "39.8.10", + "resolved": "https://registry.npmjs.org/electron/-/electron-39.8.10.tgz", + "integrity": "sha512-zbYtGPYUI7PzqLAzkk21Rk6j67WN0hxn0Mq/njErZo1d0HSf33is4f8ICI5fMLy5vYe0JtCtM5sYunNOaochSQ==", "dev": true, "hasInstallScript": true, "license": "MIT", "dependencies": { "@electron/get": "^2.0.0", - "@types/node": "^20.9.0", + "@types/node": "^22.7.7", "extract-zip": "^2.0.1" }, "bin": { @@ -847,16 +847,6 @@ "node": ">= 10.0.0" } }, - "node_modules/electron/node_modules/@types/node": { - "version": "20.19.33", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.33.tgz", - "integrity": "sha512-Rs1bVAIdBs5gbTIKza/tgpMuG1k3U/UMJLWecIMxNdJFDMzcM5LOiLVRYh3PilWEYDIeUDv7bpiHPLPsbydGcw==", - "dev": true, - "license": "MIT", - "dependencies": { - "undici-types": "~6.21.0" - } - }, "node_modules/end-of-stream": { "version": "1.4.5", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", diff --git a/src/ElectronNET.Host/package.json b/src/ElectronNET.Host/package.json index 999ecef9..a479db4c 100644 --- a/src/ElectronNET.Host/package.json +++ b/src/ElectronNET.Host/package.json @@ -24,7 +24,7 @@ }, "devDependencies": { "@types/node": "^22.18", - "electron": "^30.0.3", + "electron": "^39.8.10", "eslint": "^9.39.1", "typescript": "^5.9.3" } diff --git a/src/ElectronNET.IntegrationTests/Tests/ElectronCleanTargetsTests.cs b/src/ElectronNET.IntegrationTests/Tests/ElectronCleanTargetsTests.cs new file mode 100644 index 00000000..9923e6d4 --- /dev/null +++ b/src/ElectronNET.IntegrationTests/Tests/ElectronCleanTargetsTests.cs @@ -0,0 +1,108 @@ +using System.Diagnostics; + +namespace ElectronNET.IntegrationTests.Tests; + +/// +/// Tests for the Electron clean targets. +/// Covers GitHub issue #1096: cleaning must not require a restore, so the clean targets +/// must not depend on targets that need the assets file (NETSDK1004). +/// +public class ElectronCleanTargetsTests +{ + private static readonly string CorePropsPath = FindBuildFile("src/ElectronNET/build/ElectronNET.Core.props", "ElectronNET/build/ElectronNET.Core.props"); + private static readonly string CoreTargetsPath = FindBuildFile("src/ElectronNET/build/ElectronNET.Core.targets", "ElectronNET/build/ElectronNET.Core.targets"); + + [Fact] + public async Task ElectronCleanTargets_WithoutRestore_ShouldSucceed() + { + var tempDir = CreateTempProjectDirectory(); + + try + { + await WriteMinimalCsprojAsync(tempDir); + + var (exitCode, output) = await RunDotnetMsBuildAsync(tempDir, "Clean"); + + output.Should().NotContain("NETSDK1004", + $"cleaning must not require the assets file of a previous restore. Full output:\n{output}"); + + exitCode.Should().Be(0, + $"cleaning an unrestored project must succeed. Full output:\n{output}"); + } + finally + { + Directory.Delete(tempDir, recursive: true); + } + } + + private static string FindBuildFile(string relativeFromRepoRoot, string relativeFromSrc) + { + var dir = new DirectoryInfo(AppContext.BaseDirectory); + while (dir != null) + { + var fromRepoRoot = Path.Combine(dir.FullName, relativeFromRepoRoot); + if (File.Exists(fromRepoRoot)) + { + return Path.GetFullPath(fromRepoRoot); + } + + var fromSrc = Path.Combine(dir.FullName, relativeFromSrc); + if (File.Exists(fromSrc)) + { + return Path.GetFullPath(fromSrc); + } + + dir = dir.Parent; + } + + throw new FileNotFoundException( + $"Could not locate '{relativeFromRepoRoot}' by walking up from '{AppContext.BaseDirectory}'."); + } + + private static string CreateTempProjectDirectory() + { + var tempDir = Path.Combine(Path.GetTempPath(), $"electron-net-clean-test-{Guid.NewGuid():N}"); + Directory.CreateDirectory(tempDir); + Directory.CreateDirectory(Path.Combine(tempDir, "Properties")); + return tempDir; + } + + private static Task WriteMinimalCsprojAsync(string tempDir) + { + var propsPathEscaped = CorePropsPath.Replace("'", "'"); + var targetsPathEscaped = CoreTargetsPath.Replace("'", "'"); + + return File.WriteAllTextAsync( + Path.Combine(tempDir, "TestApp.csproj"), + $$""" + + + net10.0 + + + + + + + """); + } + + private static async Task<(int ExitCode, string Output)> RunDotnetMsBuildAsync(string workingDirectory, string target) + { + // Deliberately without /restore - that is what issue #1096 is about. + var psi = new ProcessStartInfo("dotnet", $"msbuild TestApp.csproj --nologo -v:minimal /t:{target}") + { + WorkingDirectory = workingDirectory, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + }; + + using var process = Process.Start(psi)!; + var stdOut = await process.StandardOutput.ReadToEndAsync(); + var stdErr = await process.StandardError.ReadToEndAsync(); + await process.WaitForExitAsync(); + + return (process.ExitCode, stdOut + stdErr); + } +} diff --git a/src/ElectronNET.IntegrationTests/Tests/MigrationChecksTargetsTests.cs b/src/ElectronNET.IntegrationTests/Tests/MigrationChecksTargetsTests.cs index 93b18173..2f42ade9 100644 --- a/src/ElectronNET.IntegrationTests/Tests/MigrationChecksTargetsTests.cs +++ b/src/ElectronNET.IntegrationTests/Tests/MigrationChecksTargetsTests.cs @@ -145,6 +145,111 @@ await File.WriteAllTextAsync( } } + [Fact] + public async Task MigrationChecksTargets_BuildWithRootPackageLockJson_ShouldNotEmitELECTRON001Warning() + { + // A root package.json is validated by ELECTRON008/ELECTRON009 and therefore allowed. + // Its accompanying package-lock.json must not be reported by ELECTRON001. + + var tempDir = CreateTempProjectDirectory(); + try + { + await File.WriteAllTextAsync( + Path.Combine(tempDir, "package.json"), + """{ "devDependencies": { "vite": "^5.0.0" } }"""); + await File.WriteAllTextAsync( + Path.Combine(tempDir, "package-lock.json"), + """{ "lockfileVersion": 3 }"""); + + await WriteMinimalCsprojAsync(tempDir); + + var (exitCode, output) = await RunDotnetBuildAsync(tempDir); + + exitCode.Should().Be(0, $"Full build output:\n{output}"); + + output.Should().NotContain( + "ELECTRON001", + $"a root package-lock.json belongs to the allowed root package.json. " + + $"Full build output:\n{output}"); + } + finally + { + Directory.Delete(tempDir, recursive: true); + } + } + + [Fact] + public async Task MigrationChecksTargets_BuildWithIncompleteHostHookFolder_ShouldEmitELECTRON010AndELECTRON011Warnings() + { + // Host hook TypeScript sources are silently ignored when package.json/tsconfig.json + // are missing, so the migration checks must point that out. + + var tempDir = CreateTempProjectDirectory(); + try + { + var hookDir = Path.Combine(tempDir, "ElectronHostHook"); + Directory.CreateDirectory(hookDir); + await File.WriteAllTextAsync(Path.Combine(hookDir, "index.ts"), "export class HookService {}"); + + await WriteMinimalCsprojAsync(tempDir); + + var (exitCode, output) = await RunDotnetBuildAsync(tempDir); + + exitCode.Should().Be(0, $"Full build output:\n{output}"); + + output.Should().Contain( + "ELECTRON010", + $"the ElectronHostHook folder has TypeScript files but no package.json. " + + $"Full build output:\n{output}"); + output.Should().Contain( + "ELECTRON011", + $"the ElectronHostHook folder has TypeScript files but no tsconfig.json. " + + $"Full build output:\n{output}"); + } + finally + { + Directory.Delete(tempDir, recursive: true); + } + } + + [Fact] + public async Task MigrationChecksTargets_BuildWithConsoleProfileContainingProjectGuid_ShouldEmitELECTRON007Warning() + { + // ProjectGuid is an ASP.NET publish profile property and must be reported for + // non-web projects, just like WebPublishMethod. + + var tempDir = CreateTempProjectDirectory(); + try + { + var profilesDir = Path.Combine(tempDir, "Properties", "PublishProfiles"); + Directory.CreateDirectory(profilesDir); + await File.WriteAllTextAsync( + Path.Combine(profilesDir, "FolderProfile.pubxml"), + """ + + + 00000000-0000-0000-0000-000000000000 + + + """); + + await WriteMinimalCsprojAsync(tempDir); + + var (exitCode, output) = await RunDotnetBuildAsync(tempDir); + + exitCode.Should().Be(0, $"Full build output:\n{output}"); + + output.Should().Contain( + "ELECTRON007", + $"a console project must not use an ASP.NET publish profile. " + + $"Full build output:\n{output}"); + } + finally + { + Directory.Delete(tempDir, recursive: true); + } + } + // ----------------------------------------------------------------------- // Helpers // ----------------------------------------------------------------------- diff --git a/src/ElectronNET.IntegrationTests/Tests/WebContentsTests.cs b/src/ElectronNET.IntegrationTests/Tests/WebContentsTests.cs index 6afdc2eb..55a89a89 100644 --- a/src/ElectronNET.IntegrationTests/Tests/WebContentsTests.cs +++ b/src/ElectronNET.IntegrationTests/Tests/WebContentsTests.cs @@ -108,13 +108,19 @@ public async Task GetSetZoomLevel_check() await Task.Delay(500.ms()); var ok = await window.WebContents.GetZoomLevelAsync(); - ok.Should().Be(0); + ok.Should().Be(0.0); window.WebContents.SetZoomLevel(2); await Task.Delay(500.ms()); ok = await window.WebContents.GetZoomLevelAsync(); - ok.Should().Be(2); + ok.Should().Be(2.0); + + window.WebContents.SetZoomLevel(0.5); + await Task.Delay(500.ms()); + + ok = await window.WebContents.GetZoomLevelAsync(); + ok.Should().BeApproximately(0.5, 0.001); } finally { @@ -193,5 +199,94 @@ public async Task GetSetUserAgent_check() } } + [IntegrationFact] + public async Task InsertAndRemoveCSS_check() + { + var wc = this.MainWindow.WebContents; + await wc.LoadURLAsync("data:text/html,

CSS Test

"); + + var key = await wc.InsertCSSAsync("body { background-color: rgb(255, 0, 0); }"); + key.Should().NotBeNullOrEmpty(); + + var color = await wc.ExecuteJavaScriptAsync("getComputedStyle(document.body).backgroundColor"); + color.Should().Be("rgb(255, 0, 0)"); + + await wc.RemoveInsertedCSSAsync(key); + + color = await wc.ExecuteJavaScriptAsync("getComputedStyle(document.body).backgroundColor"); + color.Should().NotBe("rgb(255, 0, 0)"); + } + + [IntegrationFact] + public async Task EditCommands_check() + { + var wc = this.MainWindow.WebContents; + await wc.LoadURLAsync("data:text/html,"); + await Task.Delay(500.ms()); + + await wc.InsertTextAsync("Electron.NET"); + await Task.Delay(500.ms()); + + var value = await wc.ExecuteJavaScriptAsync("document.getElementById('in').value"); + value.Should().Be("Electron.NET"); + + wc.SelectAll(); + wc.Delete(); + await Task.Delay(500.ms()); + + value = await wc.ExecuteJavaScriptAsync("document.getElementById('in').value"); + value.Should().BeEmpty(); + } + + [IntegrationFact] + public async Task FindInPage_check() + { + var wc = this.MainWindow.WebContents; + await wc.LoadURLAsync("data:text/html,

needle in a haystack

"); + await Task.Delay(500.ms()); + + var tcs = new TaskCompletionSource(); + + void OnFound(FoundInPageResult result) => tcs.TrySetResult(result); + + wc.OnFoundInPage += OnFound; + + try + { + var requestId = await wc.FindInPageAsync("needle"); + requestId.Should().BeGreaterThan(0); + + var completed = await Task.WhenAny(tcs.Task, Task.Delay(5.seconds())); + completed.Should().Be(tcs.Task); + + var result = await tcs.Task; + result.RequestId.Should().Be(requestId); + result.Matches.Should().BeGreaterThan(0); + } + finally + { + wc.OnFoundInPage -= OnFound; + wc.StopFindInPage(StopFindInPageAction.ClearSelection); + } + } + + [IntegrationFact] + public async Task Reload_and_loading_state_check() + { + var wc = this.MainWindow.WebContents; + await wc.LoadURLAsync("data:text/html,

Reload Test

"); + await Task.Delay(500.ms()); + + (await wc.IsLoadingAsync()).Should().BeFalse(); + (await wc.IsLoadingMainFrameAsync()).Should().BeFalse(); + (await wc.IsWaitingForResponseAsync()).Should().BeFalse(); + + wc.Reload(); + await Task.Delay(1.seconds()); + + var title = await wc.ExecuteJavaScriptAsync("document.querySelector('h1').textContent"); + title.Should().Be("Reload Test"); + } + } } \ No newline at end of file diff --git a/src/ElectronNET.Lean.sln b/src/ElectronNET.Lean.sln index 87a55e95..6f09e5b8 100644 --- a/src/ElectronNET.Lean.sln +++ b/src/ElectronNET.Lean.sln @@ -21,6 +21,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "!Config", "!Config", "{02EA EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ElectronNET.AspNet", "ElectronNET.AspNet\ElectronNET.AspNet.csproj", "{DD10D21A-D131-1D9C-33F9-406046E0C5B0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ElectronNET.Templates", "ElectronNET.Templates\ElectronNET.Templates.csproj", "{3F2A1D64-9C71-4E1B-9A2D-5C7B0E4F8A11}" +EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{1BB6F634-2831-4496-83A6-BC6761DCEC8D}" EndProject Global @@ -45,6 +47,10 @@ Global {DD10D21A-D131-1D9C-33F9-406046E0C5B0}.Debug|Any CPU.Build.0 = Debug|Any CPU {DD10D21A-D131-1D9C-33F9-406046E0C5B0}.Release|Any CPU.ActiveCfg = Release|Any CPU {DD10D21A-D131-1D9C-33F9-406046E0C5B0}.Release|Any CPU.Build.0 = Release|Any CPU + {3F2A1D64-9C71-4E1B-9A2D-5C7B0E4F8A11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F2A1D64-9C71-4E1B-9A2D-5C7B0E4F8A11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F2A1D64-9C71-4E1B-9A2D-5C7B0E4F8A11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F2A1D64-9C71-4E1B-9A2D-5C7B0E4F8A11}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -54,6 +60,7 @@ Global {829FC339-4785-4229-ABA5-53ADB544DA00} = {1BB6F634-2831-4496-83A6-BC6761DCEC8D} {8860606D-6847-F22A-5AED-DF4E0984DD24} = {1BB6F634-2831-4496-83A6-BC6761DCEC8D} {DD10D21A-D131-1D9C-33F9-406046E0C5B0} = {1BB6F634-2831-4496-83A6-BC6761DCEC8D} + {3F2A1D64-9C71-4E1B-9A2D-5C7B0E4F8A11} = {1BB6F634-2831-4496-83A6-BC6761DCEC8D} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {81A62E71-9E04-4EFE-AD5C-23165375F8EF} diff --git a/src/ElectronNET.Samples.ElectronHostHook/ElectronNET.Samples.ElectronHostHook.csproj b/src/ElectronNET.Samples.ElectronHostHook/ElectronNET.Samples.ElectronHostHook.csproj index 03a899a3..fca8acf8 100644 --- a/src/ElectronNET.Samples.ElectronHostHook/ElectronNET.Samples.ElectronHostHook.csproj +++ b/src/ElectronNET.Samples.ElectronHostHook/ElectronNET.Samples.ElectronHostHook.csproj @@ -27,8 +27,8 @@ - - + + diff --git a/src/ElectronNET.Templates/ElectronNET.Templates.csproj b/src/ElectronNET.Templates/ElectronNET.Templates.csproj new file mode 100644 index 00000000..85655fcf --- /dev/null +++ b/src/ElectronNET.Templates/ElectronNET.Templates.csproj @@ -0,0 +1,65 @@ + + + + + + netstandard2.0 + ..\..\artifacts + $(PackageNamePrefix).Templates + $(PackageId) + $(DescriptionFirstPart) This package contains the 'dotnet new' project templates. + electron aspnetcore blazor dotnet-new templates + Template + true + false + content + + true + false + false + true + $(NoWarn);NU5128 + disable + + 0.6.0 + templates\blazor\ElectronBlazorApp.csproj + content\templates\blazor\ElectronBlazorApp.csproj + + + + + + + + + + + + + + + <_TemplateProjectSource>$(MSBuildProjectDirectory)\$(TemplateProjectFile) + <_TemplateProjectTarget>$(IntermediateOutputPath)templates\blazor\ElectronBlazorApp.csproj + <_TemplateProjectContent>$([System.IO.File]::ReadAllText('$(_TemplateProjectSource)')) + + + + + + <_TemplateProjectContent>$(_TemplateProjectContent.Replace('Version="$(TemplatePlaceholderVersion)"', 'Version="$(Version)"')) + + + + + + + + + + diff --git a/src/ElectronNET.Templates/templates/blazor/.template.config/dotnetcli.host.json b/src/ElectronNET.Templates/templates/blazor/.template.config/dotnetcli.host.json new file mode 100644 index 00000000..c23c37a5 --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/.template.config/dotnetcli.host.json @@ -0,0 +1,21 @@ +{ + "$schema": "http://json.schemastore.org/dotnetcli.host", + "symbolInfo": { + "Framework": { + "longName": "framework", + "shortName": "f" + }, + "ElectronVersion": { + "longName": "electron-version", + "shortName": "e" + }, + "Port": { + "longName": "port", + "shortName": "p" + }, + "skipRestore": { + "longName": "no-restore", + "shortName": "" + } + } +} diff --git a/src/ElectronNET.Templates/templates/blazor/.template.config/template.json b/src/ElectronNET.Templates/templates/blazor/.template.config/template.json new file mode 100644 index 00000000..0b5dd72a --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/.template.config/template.json @@ -0,0 +1,75 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "Electron.NET", + "classifications": [ "Blazor", "Desktop", "Electron", "Web" ], + "identity": "ElectronNET.Core.Templates.Blazor.CSharp", + "groupIdentity": "ElectronNET.Core.Templates.Blazor", + "name": "Electron.NET Blazor App", + "description": "A Blazor Server app hosted in an Electron shell, wired up with Electron.NET.", + "shortName": "electron-blazor", + "tags": { + "language": "C#", + "type": "project" + }, + "sourceName": "ElectronBlazorApp", + "preferNameDirectory": true, + "defaultName": "ElectronBlazorApp", + "symbols": { + "Framework": { + "type": "parameter", + "description": "The target framework for the project.", + "datatype": "choice", + "choices": [ + { + "choice": "net10.0", + "description": "Target net10.0" + }, + { + "choice": "net8.0", + "description": "Target net8.0" + } + ], + "replaces": "net8.0", + "defaultValue": "net10.0" + }, + "ElectronVersion": { + "type": "parameter", + "description": "The version of Electron to build the app against.", + "datatype": "text", + "replaces": "ELECTRON_VERSION", + "defaultValue": "38.2.2" + }, + "Port": { + "type": "parameter", + "description": "Port number to use for the ASP.NET server during development.", + "datatype": "integer", + "replaces": "8001", + "defaultValue": "8001" + }, + "skipRestore": { + "type": "parameter", + "datatype": "bool", + "description": "If specified, skips the automatic restore of the project on create.", + "defaultValue": "false" + } + }, + "primaryOutputs": [ + { + "path": "ElectronBlazorApp.csproj" + } + ], + "postActions": [ + { + "id": "restore", + "condition": "(!skipRestore)", + "description": "Restore NuGet packages required by this project.", + "manualInstructions": [ + { + "text": "Run 'dotnet restore'" + } + ], + "actionId": "210D431B-A78B-4D2F-B762-4ED3E3EA9025", + "continueOnError": true + } + ] +} diff --git a/src/ElectronNET.Templates/templates/blazor/Components/App.razor b/src/ElectronNET.Templates/templates/blazor/Components/App.razor new file mode 100644 index 00000000..423b01a7 --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/Components/App.razor @@ -0,0 +1,20 @@ + + + + + + + + + + + ElectronBlazorApp + + + + + + + + + diff --git a/src/ElectronNET.Templates/templates/blazor/Components/Layout/MainLayout.razor b/src/ElectronNET.Templates/templates/blazor/Components/Layout/MainLayout.razor new file mode 100644 index 00000000..058086a9 --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/Components/Layout/MainLayout.razor @@ -0,0 +1,9 @@ +@inherits LayoutComponentBase + +
+ + +
+ @Body +
+
diff --git a/src/ElectronNET.Templates/templates/blazor/Components/Layout/NavMenu.razor b/src/ElectronNET.Templates/templates/blazor/Components/Layout/NavMenu.razor new file mode 100644 index 00000000..d2d7591b --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/Components/Layout/NavMenu.razor @@ -0,0 +1,4 @@ + diff --git a/src/ElectronNET.Templates/templates/blazor/Components/Pages/Counter.razor b/src/ElectronNET.Templates/templates/blazor/Components/Pages/Counter.razor new file mode 100644 index 00000000..bba7e167 --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/Components/Pages/Counter.razor @@ -0,0 +1,19 @@ +@page "/counter" +@rendermode InteractiveServer + +Counter + +

Counter

+ +

Current count: @currentCount

+ + + +@code { + private int currentCount = 0; + + private void IncrementCount() + { + currentCount++; + } +} diff --git a/src/ElectronNET.Templates/templates/blazor/Components/Pages/Home.razor b/src/ElectronNET.Templates/templates/blazor/Components/Pages/Home.razor new file mode 100644 index 00000000..76b64ba3 --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/Components/Pages/Home.razor @@ -0,0 +1,34 @@ +@page "/" +@rendermode InteractiveServer +@using ElectronNET.API +@using ElectronNET.API.Entities + +Home + +

Hello from Electron.NET!

+ +

+ This Blazor app is served by ASP.NET Core and displayed in an Electron window. + Everything in the ElectronNET.API namespace is available from your components. +

+ + + +

@status

+ +@code { + private string? status; + + private void ShowNotification() + { + if (HybridSupport.IsElectronActive) + { + Electron.Notification.Show(new NotificationOptions("ElectronBlazorApp", "Hello from Blazor!")); + status = "Notification sent."; + } + else + { + status = "Not running inside Electron."; + } + } +} diff --git a/src/ElectronNET.Templates/templates/blazor/Components/Routes.razor b/src/ElectronNET.Templates/templates/blazor/Components/Routes.razor new file mode 100644 index 00000000..faa2a8c2 --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/Components/Routes.razor @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/ElectronNET.Templates/templates/blazor/Components/_Imports.razor b/src/ElectronNET.Templates/templates/blazor/Components/_Imports.razor new file mode 100644 index 00000000..8912ce80 --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/Components/_Imports.razor @@ -0,0 +1,9 @@ +@using System.Net.Http +@using Microsoft.AspNetCore.Components.Forms +@using Microsoft.AspNetCore.Components.Routing +@using Microsoft.AspNetCore.Components.Web +@using static Microsoft.AspNetCore.Components.Web.RenderMode +@using Microsoft.JSInterop +@using ElectronBlazorApp +@using ElectronBlazorApp.Components +@using ElectronBlazorApp.Components.Layout diff --git a/src/ElectronNET.Templates/templates/blazor/ElectronBlazorApp.csproj b/src/ElectronNET.Templates/templates/blazor/ElectronBlazorApp.csproj new file mode 100644 index 00000000..1493efbc --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/ElectronBlazorApp.csproj @@ -0,0 +1,28 @@ + + + + net8.0 + enable + enable + + OutOfProcess + false + + + + electron-blazor-app + ElectronBlazorApp + A Blazor app running in Electron. + 1.0.0 + My Company + Copyright © $(Company) + ELECTRON_VERSION + true + + + + + + + + diff --git a/src/ElectronNET.Templates/templates/blazor/Program.cs b/src/ElectronNET.Templates/templates/blazor/Program.cs new file mode 100644 index 00000000..83fcba6f --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/Program.cs @@ -0,0 +1,48 @@ +using ElectronNET.API; +using ElectronNET.API.Entities; +using ElectronNET.AspNet.Middleware; +using ElectronNET.AspNet.Services; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddRazorComponents() + .AddInteractiveServerComponents(); + +builder.Services.AddSingleton(); + +builder.Services.AddElectron(); + +// Starts the Electron shell and invokes ElectronAppReady once it is up. +builder.UseElectron(args, ElectronAppReady); + +var app = builder.Build(); + +app.UseMiddleware(); +app.UseRouting(); + +if (!app.Environment.IsDevelopment()) +{ + app.UseExceptionHandler("/Error", createScopeForErrors: true); +} + +app.UseStaticFiles(); +app.UseAntiforgery(); + +// Fully qualified because ElectronNET.API also defines an 'App' type. +app.MapRazorComponents() + .AddInteractiveServerRenderMode(); + +app.Run(); + +static async Task ElectronAppReady() +{ + var window = await Electron.WindowManager.CreateWindowAsync(new BrowserWindowOptions + { + IsRunningBlazor = true, + Width = 1152, + Height = 940, + Show = false, + }); + + window.OnReadyToShow += () => window.Show(); +} diff --git a/src/ElectronNET.Templates/templates/blazor/Properties/PublishProfiles/linux-x64.pubxml b/src/ElectronNET.Templates/templates/blazor/Properties/PublishProfiles/linux-x64.pubxml new file mode 100644 index 00000000..4aa6f5d5 --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/Properties/PublishProfiles/linux-x64.pubxml @@ -0,0 +1,17 @@ + + + + + true + false + false + Release + FileSystem + publish\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\ + FileSystem + <_TargetId>Folder + net8.0 + linux-x64 + true + + diff --git a/src/ElectronNET.Templates/templates/blazor/Properties/PublishProfiles/osx-arm64.pubxml b/src/ElectronNET.Templates/templates/blazor/Properties/PublishProfiles/osx-arm64.pubxml new file mode 100644 index 00000000..d6d13321 --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/Properties/PublishProfiles/osx-arm64.pubxml @@ -0,0 +1,17 @@ + + + + + true + false + false + Release + FileSystem + publish\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\ + FileSystem + <_TargetId>Folder + net8.0 + osx-arm64 + true + + diff --git a/src/ElectronNET.Templates/templates/blazor/Properties/PublishProfiles/win-x64.pubxml b/src/ElectronNET.Templates/templates/blazor/Properties/PublishProfiles/win-x64.pubxml new file mode 100644 index 00000000..e2fb6d00 --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/Properties/PublishProfiles/win-x64.pubxml @@ -0,0 +1,17 @@ + + + + + true + false + false + Release + FileSystem + publish\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\ + FileSystem + <_TargetId>Folder + net8.0 + win-x64 + true + + diff --git a/src/ElectronNET.Templates/templates/blazor/Properties/electron-builder.json b/src/ElectronNET.Templates/templates/blazor/Properties/electron-builder.json new file mode 100644 index 00000000..168dbf11 --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/Properties/electron-builder.json @@ -0,0 +1,22 @@ +{ + "compression": "maximum", + "linux": { + "target": [ "AppImage" ], + "executableArgs": [ "--no-sandbox" ] + }, + "win": { + "target": [ + { + "target": "nsis", + "arch": "x64" + } + ] + }, + "mac": { + "target": [ "dmg" ] + }, + "nsis": { + "oneClick": true, + "perMachine": false + } +} diff --git a/src/ElectronNET.Templates/templates/blazor/Properties/launchSettings.json b/src/ElectronNET.Templates/templates/blazor/Properties/launchSettings.json new file mode 100644 index 00000000..42be4365 --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/Properties/launchSettings.json @@ -0,0 +1,11 @@ +{ + "profiles": { + "ElectronBlazorApp": { + "commandName": "Project", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + }, + "applicationUrl": "http://localhost:8001/" + } + } +} diff --git a/src/ElectronNET.Templates/templates/blazor/appsettings.Development.json b/src/ElectronNET.Templates/templates/blazor/appsettings.Development.json new file mode 100644 index 00000000..0c208ae9 --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/src/ElectronNET.Templates/templates/blazor/appsettings.json b/src/ElectronNET.Templates/templates/blazor/appsettings.json new file mode 100644 index 00000000..10f68b8c --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/src/ElectronNET.Templates/templates/blazor/wwwroot/app.css b/src/ElectronNET.Templates/templates/blazor/wwwroot/app.css new file mode 100644 index 00000000..5eff1cb4 --- /dev/null +++ b/src/ElectronNET.Templates/templates/blazor/wwwroot/app.css @@ -0,0 +1,49 @@ +:root { + color-scheme: light dark; +} + +body { + margin: 0; + font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; + line-height: 1.5; +} + +.page { + display: flex; + flex-direction: column; + min-height: 100vh; +} + +.nav-menu { + display: flex; + gap: 1rem; + padding: 0.75rem 1.5rem; + background-color: #1b1b1f; +} + +.nav-menu a { + color: #d7d7d7; + text-decoration: none; +} + +.nav-menu a.active { + color: #fff; + font-weight: 600; +} + +main { + padding: 1.5rem; +} + +.btn { + padding: 0.5rem 1rem; + border: none; + border-radius: 0.25rem; + background-color: #1b6ec2; + color: #fff; + cursor: pointer; +} + +.btn:hover { + background-color: #1861ac; +} diff --git a/src/ElectronNET.WebApp/Controllers/UpdateController.cs b/src/ElectronNET.WebApp/Controllers/UpdateController.cs index e145ec77..84bcfde7 100644 --- a/src/ElectronNET.WebApp/Controllers/UpdateController.cs +++ b/src/ElectronNET.WebApp/Controllers/UpdateController.cs @@ -29,9 +29,6 @@ public IActionResult Index() Electron.IpcMain.On("auto-update", async (args) => { - // Electron.NET CLI Command for deploy: - // electronize build /target win /electron-params --publish=always - var currentVersion = await Electron.App.GetVersionAsync(); var updateCheckResult = await Electron.AutoUpdater.CheckForUpdatesAndNotifyAsync(); var availableVersion = updateCheckResult.UpdateInfo.Version; diff --git a/src/ElectronNET.WebApp/ElectronHostHook/package-lock.json b/src/ElectronNET.WebApp/ElectronHostHook/package-lock.json index 72216078..e2ad3adf 100644 --- a/src/ElectronNET.WebApp/ElectronHostHook/package-lock.json +++ b/src/ElectronNET.WebApp/ElectronHostHook/package-lock.json @@ -540,9 +540,9 @@ "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", - "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", @@ -1351,9 +1351,9 @@ "license": "ISC" }, "node_modules/js-yaml": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.0.tgz", - "integrity": "sha512-1td788aAnnZ5qs7V2QIRl1owjtYpbKt749Y3xauqQgwIIGF/xXWz1wMTEBx5O3LK3lXLVuqXPdPxj2BoFHaW9Q==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", "dev": true, "funding": [ { @@ -1811,9 +1811,9 @@ } }, "node_modules/readdir-glob/node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" diff --git a/src/ElectronNET.WebApp/ElectronNET.WebApp.csproj b/src/ElectronNET.WebApp/ElectronNET.WebApp.csproj index bf43c579..6c2c3999 100644 --- a/src/ElectronNET.WebApp/ElectronNET.WebApp.csproj +++ b/src/ElectronNET.WebApp/ElectronNET.WebApp.csproj @@ -75,8 +75,8 @@ - - + + diff --git a/src/ElectronNET.WebApp/Views/HostHook/Index.cshtml b/src/ElectronNET.WebApp/Views/HostHook/Index.cshtml index 7dbbed0c..7c5c2673 100644 --- a/src/ElectronNET.WebApp/Views/HostHook/Index.cshtml +++ b/src/ElectronNET.WebApp/Views/HostHook/Index.cshtml @@ -8,7 +8,7 @@

The HostHook API allows you to execute your own JavaScript/TypeScript code on the host process.

-

Create first an ElectronHostHook directory via the Electron.NET CLI, with the following command: electronize add hosthook.

+

Create first an ElectronHostHook directory with a package.json and a JavaScript file.

In this directory you can install any NPM packages and embed your own JavaScript/TypeScript code. It is also possible to respond to events from the host process.

You find the sample source code in Controllers\HostHookController.cs and in the ElectronHostHook folder.

diff --git a/src/ElectronNET.sln b/src/ElectronNET.sln index 43fbaafe..c19b2cbd 100644 --- a/src/ElectronNET.sln +++ b/src/ElectronNET.sln @@ -29,6 +29,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "!Config", "!Config", "{02EA EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ElectronNET.AspNet", "ElectronNET.AspNet\ElectronNET.AspNet.csproj", "{DD10D21A-D131-1D9C-33F9-406046E0C5B0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ElectronNET.Templates", "ElectronNET.Templates\ElectronNET.Templates.csproj", "{3F2A1D64-9C71-4E1B-9A2D-5C7B0E4F8A11}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ElectronNET.ConsoleApp", "ElectronNET.ConsoleApp\ElectronNET.ConsoleApp.csproj", "{EE38A326-5DE8-AF09-9EB9-DF0878938783}" ProjectSection(ProjectDependencies) = postProject {1C5FD66E-A1C6-C436-DF7C-3ECE4FEDDFE6} = {1C5FD66E-A1C6-C436-DF7C-3ECE4FEDDFE6} @@ -99,6 +101,10 @@ Global {DD10D21A-D131-1D9C-33F9-406046E0C5B0}.Debug|Any CPU.Build.0 = Debug|Any CPU {DD10D21A-D131-1D9C-33F9-406046E0C5B0}.Release|Any CPU.ActiveCfg = Release|Any CPU {DD10D21A-D131-1D9C-33F9-406046E0C5B0}.Release|Any CPU.Build.0 = Release|Any CPU + {3F2A1D64-9C71-4E1B-9A2D-5C7B0E4F8A11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3F2A1D64-9C71-4E1B-9A2D-5C7B0E4F8A11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3F2A1D64-9C71-4E1B-9A2D-5C7B0E4F8A11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3F2A1D64-9C71-4E1B-9A2D-5C7B0E4F8A11}.Release|Any CPU.Build.0 = Release|Any CPU {EE38A326-5DE8-AF09-9EB9-DF0878938783}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EE38A326-5DE8-AF09-9EB9-DF0878938783}.Debug|Any CPU.Build.0 = Debug|Any CPU {EE38A326-5DE8-AF09-9EB9-DF0878938783}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -131,6 +137,7 @@ Global {829FC339-4785-4229-ABA5-53ADB544DA00} = {1BB6F634-2831-4496-83A6-BC6761DCEC8D} {8860606D-6847-F22A-5AED-DF4E0984DD24} = {1BB6F634-2831-4496-83A6-BC6761DCEC8D} {DD10D21A-D131-1D9C-33F9-406046E0C5B0} = {1BB6F634-2831-4496-83A6-BC6761DCEC8D} + {3F2A1D64-9C71-4E1B-9A2D-5C7B0E4F8A11} = {1BB6F634-2831-4496-83A6-BC6761DCEC8D} {EE38A326-5DE8-AF09-9EB9-DF0878938783} = {EDCBFC49-2AEE-4BAF-9368-4409298C52FC} {015CB06B-6CAE-209F-E050-21C3ACA5FE9F} = {985D39A7-5216-4945-8167-2FD0CB387BD8} {06CAADC7-DE5B-47B4-AB2A-E9501459A2D1} = {D36CDFFD-3438-42E4-A7FF-88BA19AC4964} diff --git a/src/ElectronNET/ElectronNET.csproj b/src/ElectronNET/ElectronNET.csproj index 2298cd7e..38524f20 100644 --- a/src/ElectronNET/ElectronNET.csproj +++ b/src/ElectronNET/ElectronNET.csproj @@ -3,7 +3,7 @@ - net6.0;net8.0;net10.0 + $(ElectronNetTargetFrameworks) ..\..\artifacts $(PackageNamePrefix) $(PackageId) diff --git a/src/ElectronNET/build/ElectronNET.Build.dll b/src/ElectronNET/build/ElectronNET.Build.dll index c850ff39..0455b561 100644 Binary files a/src/ElectronNET/build/ElectronNET.Build.dll and b/src/ElectronNET/build/ElectronNET.Build.dll differ diff --git a/src/ElectronNET/build/ElectronNET.Core.props b/src/ElectronNET/build/ElectronNET.Core.props index 13578cae..4b4eed4a 100644 --- a/src/ElectronNET/build/ElectronNET.Core.props +++ b/src/ElectronNET/build/ElectronNET.Core.props @@ -4,19 +4,21 @@ 30.4.0 26.0 - - $(RuntimeIdentifier) - - $([System.Runtime.InteropServices.RuntimeInformation]::RuntimeIdentifier) - - win-$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLower()) + true - $(MSBuildProjectName.Replace(".", "-").ToLower()) + $(MSBuildProjectName.Replace(".", "-").ToLower()) electron-builder.json - $(MSBuildProjectName) + $(MSBuildProjectName) + + ../.. + + false diff --git a/src/ElectronNET/build/ElectronNET.Core.targets b/src/ElectronNET/build/ElectronNET.Core.targets index 962ed6fa..f615ce37 100644 --- a/src/ElectronNET/build/ElectronNET.Core.targets +++ b/src/ElectronNET/build/ElectronNET.Core.targets @@ -1,10 +1,16 @@ - + win - $(Title) - $(ElectronPackageId) + $(Title) + $(ElectronPackageId) + + + + + $(ElectronExecutableName) @@ -19,6 +25,7 @@ + diff --git a/src/ElectronNET/build/ElectronNET.LateImport.targets b/src/ElectronNET/build/ElectronNET.LateImport.targets index 9019c09f..1e405ec4 100644 --- a/src/ElectronNET/build/ElectronNET.LateImport.targets +++ b/src/ElectronNET/build/ElectronNET.LateImport.targets @@ -52,7 +52,7 @@ - + @@ -60,7 +60,7 @@ - + @@ -95,8 +95,24 @@ + + + + + $(RuntimeIdentifier) + + $([System.Runtime.InteropServices.RuntimeInformation]::RuntimeIdentifier) + + win-$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLower()) + + + + + + - + @@ -154,7 +170,9 @@ <_NonIntermediatePublishDir>$(PublishDir) $(PublishDir) - $(IntermediateOutputPath)PubTmp\ + + $(ElectronIntermediatePublishDir) + $(IntermediateOutputPath)PubTmp\ @@ -370,7 +388,7 @@ - + x64 @@ -443,13 +461,13 @@ - + - + - + <_NpmCmd>node node_modules/electron/install.js @@ -458,13 +476,13 @@ <_NpmCmd Condition="'$(IsLinuxWsl)' == 'true'">wsl bash -ic '$(_NpmCmd)' - + - + - + @@ -599,11 +617,11 @@ For more information, see: https://github.com/ElectronNET/Electron.NET/wiki/Migr <_NpmAppDepsCmd Condition="'$(IsLinuxWsl)' == 'true'">wsl bash -ic '$(_NpmAppDepsCmd)' - + - + + @@ -629,11 +648,11 @@ For more information, see: https://github.com/ElectronNET/Electron.NET/wiki/Migr <_NpmCmd Condition="'$(IsLinuxWsl)' == 'true'">wsl bash -ic '$(_NpmCmd)' - + - + @@ -653,18 +672,15 @@ For more information, see: https://github.com/ElectronNET/Electron.NET/wiki/Migr - <_NpxCmd>npx electron-builder --config=./$(ElectronBuilderJson) - <_NpxCmd Condition="'$(IsLinuxWsl)' == 'true'">$(_NpxCmd) --$(ElectronPlatform) - <_NpxCmd Condition="'$(IsLinuxWsl)' == 'true'">$(_NpxCmd) --$(ElectronArch) - <_NpxCmd>$(_NpxCmd) -c.electronVersion=$(ElectronVersion) -c.directories.output "$(ElectronPublishUrlFullPath)" $(ElectronPaParams) + <_NpxCmd>npx electron-builder -c.$(ElectronPlatform).defaultArch=$(ElectronArch) --config=./$(ElectronBuilderJson) -c.electronVersion=$(ElectronVersion) --$(ElectronPlatform) --$(ElectronArch) -c.directories.output "$(ElectronPublishUrlFullPath)" $(ElectronPaParams) <_NpxCmd Condition="'$(IsLinuxWsl)' == 'true'">wsl bash -ic '$(_NpxCmd)' - + - + diff --git a/src/ElectronNET/build/ElectronNET.MigrationChecks.targets b/src/ElectronNET/build/ElectronNET.MigrationChecks.targets index ab138a5d..d928e7fc 100644 --- a/src/ElectronNET/build/ElectronNET.MigrationChecks.targets +++ b/src/ElectronNET/build/ElectronNET.MigrationChecks.targets @@ -9,10 +9,22 @@ ElectronCheckNoManifestJson; ElectronCheckElectronBuilderJson; ElectronCheckNoParentPaths; - ElectronCheckPubxmlFiles + ElectronCheckPubxmlFiles; + ElectronCheckHostHookFolder + + + <_ElectronCheckExcludes>$(MSBuildProjectDirectory)\bin\**\*;$(MSBuildProjectDirectory)\obj\**\*;$(MSBuildProjectDirectory)\publish\**\*;$(MSBuildProjectDirectory)\node_modules\**\*;$(MSBuildProjectDirectory)\.electron\**\* + <_ElectronCheckExcludes Condition="'$(BaseOutputPath)' != ''">$(_ElectronCheckExcludes);$([MSBuild]::NormalizeDirectory('$(MSBuildProjectDirectory)', '$(BaseOutputPath)'))**\* + <_ElectronCheckExcludes Condition="'$(BaseIntermediateOutputPath)' != ''">$(_ElectronCheckExcludes);$([MSBuild]::NormalizeDirectory('$(MSBuildProjectDirectory)', '$(BaseIntermediateOutputPath)'))**\* + + + $(_ElectronCheckExcludes)" /> + <_InvalidPackageLockJson Include="$(MSBuildProjectDirectory)\**\package-lock.json" - Exclude="$(MSBuildProjectDirectory)\ElectronHostHook\**\package-lock.json; - $(MSBuildProjectDirectory)\bin\**\package-lock.json; - $(MSBuildProjectDirectory)\obj\**\package-lock.json; - $(MSBuildProjectDirectory)\publish\**\package-lock.json; - $(MSBuildProjectDirectory)\node_modules\**\package-lock.json" /> + Exclude="$(MSBuildProjectDirectory)\package-lock.json; + $(MSBuildProjectDirectory)\ElectronHostHook\**\package-lock.json; + $(_ElectronCheckExcludes)" /> @@ -141,10 +150,7 @@ For more information, see: https://github.com/ElectronNET/Electron.NET/wiki/Migr <_InvalidManifestJson Include="$(MSBuildProjectDirectory)\**\electron.manifest.json;$(MSBuildProjectDirectory)\**\electron-manifest.json" - Exclude="$(MSBuildProjectDirectory)\bin\**\*; - $(MSBuildProjectDirectory)\obj\**\*; - $(MSBuildProjectDirectory)\publish\**\*; - $(MSBuildProjectDirectory)\node_modules\**\*" /> + Exclude="$(_ElectronCheckExcludes)" /> @@ -187,10 +193,7 @@ MIGRATION REQUIRED: <_ElectronBuilderJsonWrongLocation Include="$(MSBuildProjectDirectory)\**\electron-builder.json" Exclude="$(MSBuildProjectDirectory)\Properties\electron-builder.json; - $(MSBuildProjectDirectory)\bin\**\*; - $(MSBuildProjectDirectory)\obj\**\*; - $(MSBuildProjectDirectory)\publish\**\*; - $(MSBuildProjectDirectory)\node_modules\**\*" /> + $(_ElectronCheckExcludes)" /> @@ -296,10 +299,11 @@ For more information, see: https://github.com/ElectronNET/Electron.NET/wiki/Migr - + <_PubxmlFileInfoWithFlags Include="@(_PubxmlFileInfo)" Condition="'%(Identity)' != ''"> $([System.Text.RegularExpressions.Regex]::IsMatch('%(FileContent)', '<WebPublishMethod>')) + $([System.Text.RegularExpressions.Regex]::IsMatch('%(FileContent)', '<ProjectGuid>')) @@ -309,10 +313,10 @@ For more information, see: https://github.com/ElectronNET/Electron.NET/wiki/Migr Condition="'$(_IsAspNetProject)' == 'true' AND '%(HasWebPublishMethod)' == 'False'" /> - + <_ConsolePubxmlWithAspNetProperties Include="@(_PubxmlFileInfoWithFlags)" - Condition="'$(_IsAspNetProject)' != 'true' AND '%(HasWebPublishMethod)' == 'True'" /> + Condition="'$(_IsAspNetProject)' != 'true' AND ('%(HasWebPublishMethod)' == 'True' OR '%(HasProjectGuid)' == 'True')" /> @@ -336,7 +340,7 @@ For more information, see: https://github.com/ElectronNET/Electron.NET/wiki/Migr + + + + + <_HostHookTsFiles Include="$(MSBuildProjectDirectory)\ElectronHostHook\*.ts" /> + + + + <_HasHostHookTsFiles>false + <_HasHostHookTsFiles Condition="@(_HostHookTsFiles->Count()) > 0">true + + + + + + + + diff --git a/src/ElectronNET/build/ElectronNETRules.Project.xaml b/src/ElectronNET/build/ElectronNETRules.Project.xaml index 0331ae8f..bc55308c 100644 --- a/src/ElectronNET/build/ElectronNETRules.Project.xaml +++ b/src/ElectronNET/build/ElectronNETRules.Project.xaml @@ -553,6 +553,30 @@ Category="General"> + + + + + + + + + + + + - 0.5.2 + 0.6.0 ElectronNET.Core Gregor Biswanger, Florian Rappl, softworkz Electron.NET @@ -18,6 +18,7 @@ $(Version) $(Version)$(VersionPostFix) $(Version) + net6.0;net8.0;net10.0