Compare commits

..

350 Commits

Author SHA1 Message Date
Gregor Biswanger
e9bf393165 Merge branch 'theolivenbaum-master' 2022-07-28 11:52:12 +02:00
Gregor Biswanger
d3aa9783d3 Merge of theolivenbaum PR 2022-07-28 11:51:18 +02:00
theolivenbaum
a5bc910926 Release 19.0.9 2022-07-22 10:45:24 +02:00
theolivenbaum
89033c61d4 Return socket port 2022-07-14 17:07:19 +02:00
theolivenbaum
90b4a287d9 Add experimental mode to start electron from C# (for development purposes) 2022-07-14 16:56:50 +02:00
theolivenbaum
e2615a8dc1 Import SocketIO code 2022-07-14 16:53:54 +02:00
theolivenbaum
73330185de Release 19.0.8 2022-07-12 13:43:12 +02:00
theolivenbaum
e1c5b7e3c2 Update main.js 2022-06-28 15:40:58 +02:00
theolivenbaum
a19e095f6e Fix wrong variable name 2022-06-27 16:04:32 +02:00
theolivenbaum
b7ed3d22f1 Update main.js 2022-06-27 14:53:21 +02:00
theolivenbaum
c8f944af4a Release 19.0.6 2022-06-27 14:35:16 +02:00
theolivenbaum
2f73bb8b34 Release 19.0.5 2022-06-21 10:48:40 +02:00
theolivenbaum
1f22be68d2 Drop net5.0 2022-06-09 10:23:29 +02:00
theolivenbaum
576140474e merge #624 2022-06-09 10:22:54 +02:00
theolivenbaum
68c9e80417 merge #673 2022-06-09 10:12:15 +02:00
theolivenbaum
4906babd78 Change to use ImageSharp 2022-06-08 21:28:38 +02:00
theolivenbaum
e0000f7aba Change to use ImageSharp 2022-06-08 21:28:30 +02:00
theolivenbaum
ff05ef20c8 Release 19.0.4 2022-06-08 20:52:35 +02:00
theolivenbaum
79ce1c42e7 Release 19.0.3 2022-06-08 20:20:57 +02:00
Gregor Biswanger
4e95bb3331 Static parameter for build commands method 2022-06-07 23:03:06 +02:00
Gregor Biswanger
58bfa336a8 Change to .NET 6 only 2022-06-07 22:59:26 +02:00
Gregor Biswanger
afa69280f5 Fixed merge conflicts 2022-06-07 22:55:00 +02:00
Gregor Biswanger
8621d8cea3 Merge branch 'master' into dev/electron-18-update 2022-06-07 22:48:13 +02:00
Gregor Biswanger
9106391f60 Merge pull request #698 from stackify/bad-master
#697 fixing conflicts in ElectronNET.CLI commands
2022-06-07 22:41:53 +02:00
Gregor Biswanger
490ef6231b .NET 6 support only 2022-06-07 22:40:44 +02:00
theolivenbaum
89833f42fc Release 19.0.2 2022-06-02 11:11:26 +02:00
theolivenbaum
252ab5050b Release 18.3.2 2022-06-02 11:10:38 +02:00
Daniel Gidman
2ff29e553d #697 fixing conflicts in ElectronNET.CLI commands 2022-05-31 13:49:49 -05:00
theolivenbaum
a1a5f6f9a6 Handle case where pipe breaks showing error message 2022-05-31 13:38:54 +02:00
theolivenbaum
3ea7e96324 Release 19.0.1 2022-05-27 10:10:28 +02:00
theolivenbaum
a00a8a0251 Release 18.3.0 2022-05-24 10:07:32 +02:00
theolivenbaum
e245d0d2f6 release also for 17.4.1 2022-04-23 17:02:54 +02:00
theolivenbaum
48a0d68313 Increase max message size to 100mb 2022-04-23 17:01:34 +02:00
theolivenbaum
4d5d6722a7 Check if version exists 2022-04-21 09:38:41 +02:00
theolivenbaum
d910eec8df Add releaser helper to automate updating versions 2022-04-21 09:36:22 +02:00
theolivenbaum
4f9b46c616 Electron Release 18.1.0 2022-04-21 09:16:05 +02:00
theolivenbaum
4308f2c6d6 Electron Release 17.4.1 2022-04-21 09:15:00 +02:00
theolivenbaum
87468ccd5d Update main.js 2022-04-20 13:05:25 +02:00
theolivenbaum
d863ff95f4 update to 18.0.4 2022-04-20 12:47:18 +02:00
theolivenbaum
3a24b69063 let user define own env variables to start 2022-04-20 12:36:51 +02:00
rafael-aero
d6c98759c5 handle also get nearest point 2022-04-13 20:53:33 +02:00
rafael-aero
6675571aaf handle fail on getdisplaymatching 2022-04-13 20:51:34 +02:00
rafael-aero
3f8766ff9e Build 17.4.0 2022-04-12 11:31:35 +02:00
rafael-aero
9b881b1b71 Roll back to electron 18.0.2
Roll back to electron 18.0.2
2022-04-12 10:41:28 +02:00
rafael-aero
339a319f3e fix race condition on electron socket initialization 2022-04-11 13:59:42 +02:00
rafael-aero
d929102e18 update to Electron 18.0.3 2022-04-10 22:37:43 +02:00
Gregor Biswanger
26595bf290 Refactor eslint hints 2022-04-06 22:34:56 +02:00
Gregor Biswanger
5ca65f1939 Update TypeScript 4.3.5 -> 4.6.3, replace typings to native socket.io 2022-04-06 22:33:54 +02:00
Gregor Biswanger
b4b355eeac Replace tslint with eslint 2022-04-06 22:33:06 +02:00
Gregor Biswanger
47774d2871 Update socket.io 2.4.0 -> 4.4.1, electron 13.1.5 -> 18.0.2, electron-updater 4.3.9 -> 4.6.5, replace tsint with eslint 2022-04-06 22:32:38 +02:00
Gregor Biswanger
43cbdc15b8 Merge branch 'yannikHoeflich-master' 2022-04-06 21:58:38 +02:00
Gregor Biswanger
540be39547 Merge fix: changed the processing of loadUrl at CreateWindowAsync #631 2022-04-06 21:58:20 +02:00
Gregor Biswanger
a7a8685341 Merge branch 'stackify-bug/644' 2022-04-06 19:20:13 +02:00
Gregor Biswanger
0575413768 Transpile new JavaScript host files 2022-04-06 19:19:46 +02:00
Gregor Biswanger
e8394277e7 Merge fix: Fix for #664, open for comment #644 2022-04-06 19:17:43 +02:00
Gregor Biswanger
5fe50b45bb Merge branch 'stackify-CrossPlatformNativeImage' 2022-04-06 19:03:35 +02:00
Gregor Biswanger
70ca42aeaf Merge fix: Conversion to use ImageSharp rather than System.Drawing.Common #658 2022-04-06 19:03:22 +02:00
Gregor Biswanger
f54ce1eb02 Merge branch 'stackify-feature/DI-MOC-Process' 2022-04-06 18:58:15 +02:00
Gregor Biswanger
aa9c2caf47 Merge fix: Support DI and Mocking better + Support launching app with file for win and linux #656 2022-04-06 18:58:02 +02:00
Gregor Biswanger
ba8e941cf1 Merge branch 'stackify-feature/dotnet-args' 2022-04-06 18:53:19 +02:00
Gregor Biswanger
f0003ae953 Merge fix: Support for additional dotnet publish flags #655 2022-04-06 18:52:58 +02:00
Gregor Biswanger
1f5d70be83 Merge branch 'schaveyt-feature/647-launching-app-w-file-win-linux' 2022-04-06 18:46:18 +02:00
Gregor Biswanger
1a1bd61e3e Merge fix: Support launching app with file for win and linux #648 2022-04-06 18:45:51 +02:00
Gregor Biswanger
709780fd04 Merge pull request #673 from MutatedGamer/parentOption
Add ability to set a window's parent using BrowserWindowOptions
2022-04-06 18:26:08 +02:00
Gregor Biswanger
9a17d22343 Merge branch 'stackify-NET6' 2022-04-06 18:10:31 +02:00
Gregor Biswanger
7222c9e6c5 Fix conflicts: Support for .NET 6 2022-04-06 18:10:18 +02:00
Gregor Biswanger
29b4f577a6 Merge pull request #634 from stackify/feature/RecentDocuments-Mac
Recent Document Support for MacOS
2022-04-06 16:35:00 +02:00
Gregor Biswanger
9698c80442 Merge pull request #633 from stackify/feature/DI-MOCK
Support DI and Mocking better.
2022-04-06 16:33:46 +02:00
Gregor Biswanger
4afa535c31 Merge pull request #626 from javierlarota/feature/ignore-cert-errors
Allow ignoring certificate errors
2022-04-06 16:30:00 +02:00
Gregor Biswanger
0de9699a52 Merge pull request #624 from bman46/master
Support Apple Silicon Natively
2022-04-06 16:28:14 +02:00
Gregor Biswanger
6f5fb16091 Merge pull request #595 from theolivenbaum/switch-to-new-socket-lib
Switch to async socket lib
2022-04-06 16:24:02 +02:00
Gregor Biswanger
891870abde Merge branch 'master' into switch-to-new-socket-lib 2022-04-06 16:23:47 +02:00
Gregor Biswanger
ab162d4829 Merge pull request #592 from Meberem/feature/log-dotnet-errors
Log errors in the dotnet process
2022-04-06 16:10:24 +02:00
rafael-aero
ec12dbd6ad Update electron to 18.0.2 2022-04-05 22:41:41 +02:00
rafael-aero
f05934acb8 Forgot to roll back to 18.0.1 2022-04-01 20:59:06 +02:00
rafael-aero
0632112a3a improve build command to try to read version from xml file 2022-04-01 19:03:09 +02:00
rafael-aero
793f714b9e Publish Electron 17.3.1 2022-04-01 18:37:16 +02:00
rafael-aero
e3fbce26d0 Remove default electron version parameter from CLI 2022-04-01 18:27:26 +02:00
rafael-aero
c45ea53a02 Update to Electron 18.0.1 2022-04-01 17:41:21 +02:00
rafael-aero
de56395946 Update to Electron 18.0.0 2022-03-29 10:13:20 +02:00
rafael-aero
b0262b36d0 Update electron to 17.3.0 2022-03-29 09:44:20 +02:00
rafael-aero
0ffecd5bc7 save projects 2022-03-25 12:12:35 +01:00
rafael-aero
b7196ff10d Merge branch 'master' of https://github.com/theolivenbaum/Electron.NET 2022-03-25 12:11:10 +01:00
rafael-aero
93f1875f8b remove again SocketIOClient as package was updated 2022-03-25 12:11:08 +01:00
theolivenbaum
6ca5563dc1 Update build-nuget.yaml for Azure Pipelines 2022-03-25 12:03:54 +01:00
rafael-aero
e643d0db08 Update 2022-03-25 10:30:51 +01:00
rafael-aero
9c89711d59 Import SocketIOClient code until next version is released 2022-03-25 10:23:56 +01:00
rafael-aero
606b2a6481 Update main.js 2022-03-24 19:32:15 +01:00
rafael-aero
ef13ec9cc4 update electron to 17.2.0 2022-03-24 18:45:28 +01:00
rafael-aero
b58b4579f9 Add dotenv and electron-notarize dependencies 2022-03-24 11:46:17 +01:00
rafael-aero
13edd4c3ca fix multi thread usage missing lock 2022-03-23 12:18:52 +01:00
rafael-aero
967ccf385a Add support for random port assignment 2022-03-22 18:51:32 +01:00
MutatedGamer
4a44f3e150 Set parent in createBrowserWindow 2022-03-21 20:34:38 -07:00
MutatedGamer
d6e362c83c Add Parent property to BrowserWindowOptions 2022-03-21 20:34:25 -07:00
rafael-aero
df15d249de Update to 17.1.2 2022-03-10 08:38:32 +01:00
rafael-aero
a5bb3ad36b Update ElectronNET.API.csproj 2022-03-07 23:36:18 +01:00
rafael-aero
8f26ceed3d update socket.io 2022-03-07 23:13:16 +01:00
rafael-aero
7f282c1346 Update to 17.1.1 2022-03-07 22:06:48 +01:00
rafael-aero
8067f8e1ff Update to 17.1.0, remove soon to be deprecated nativeWindowOpen optiojn 2022-03-03 08:21:35 +01:00
Daniel Gidman
468c8ba2fc #644 Check for null before taking actions. Also localize references to window on window creation 2022-02-23 14:58:44 -06:00
Daniel Gidman
ab694e22fc Change IsReady logic to also wait for connection to be open. This is to prevent actions occurring before the app can act upon them. 2022-02-23 14:57:05 -06:00
Robert Muehsig
79a6ef322c Merge pull request #609 from AndreasJagiella-EH/master
Set PublishSingleFile default back to false for NET5 compatibility
2022-02-21 23:01:46 +01:00
Robert Muehsig
0ef5edfdf6 Merge pull request #613 from aguang-xyz/fix/npe-when-target-not-specified
Fix IndexOutOfRangeException in build command parsing logic
2022-02-21 22:55:01 +01:00
Robert Muehsig
7db609c699 Merge pull request #607 from gpgpublickey/build_adds_help_publish_parameters
Adds help regarding to modify publish parameters
2022-02-21 22:49:48 +01:00
Robert Muehsig
127408afdb Merge pull request #598 from tub5/tub5-readme-fix
Update README.md
2022-02-21 22:47:53 +01:00
rafael-aero
40eae5af3d update to 17.0.1 2022-02-15 14:15:32 +01:00
rafael-aero
26ba398428 Add new WCO height option 2022-02-10 23:00:33 +01:00
rafael-aero
56fe57db46 Update to 17.0.0 2022-02-10 09:55:56 +01:00
rafael-aero
c8552041fb Add debug messages for update methods 2022-02-10 00:00:51 +01:00
rafael-aero
13a3753214 emit prepare-for-update 2022-02-09 22:18:04 +01:00
rafael-aero
93ee1871ee update electron to 16.0.8 2022-01-30 20:43:39 +01:00
Daniel Gidman
86644e7366 #637 Conversion to use ImageSharp rather than System.Drawing.Common for cross platform compatibility.
Breaking Changes:

* `System.Drawing.Common` is dropped and `SixLabors.ImageSharp` is introduced.
* uses of `NativeImage.CreateFromBitmap(bitmap, options);` is no longer supported, will cause failed builds.

Unexpected Behaviors:

* uses ToDataUrl will always create png data urls, unexpected output may happen for those that manipulate this output expecting a different data url format.

Obsoletions:

* `CreateFromBitmapOptions` & `CreateFromBufferOptions` have been consolidated into `CreateOptions`. Implicit conversions added to ease transition.
* `ToBitmapOptions`, `ToDataUrlOptions`, `ToPngOptions` & `BitmapOptions` have been consolidated into `ImageOptions`. Implicit conversions added to ease transition.
2022-01-26 11:07:48 -06:00
Daniel Gidman
2331ef43b4 Support electronize as a dotnet 6 target tool 2022-01-25 14:08:40 -06:00
Daniel Gidman
b8845bb402 Include Process into DI Mocking and interfaces 2022-01-25 10:45:49 -06:00
Daniel Gidman
1767bcd5ad Merge commit '64e058b0b59a4fbbd6c0ec9de2ee1850a66684c4' into feature/DI-MOC-Process
# Conflicts:
#	ElectronNET.API/ServiceCollectionExtensions.cs
2022-01-25 10:41:42 -06:00
Daniel Gidman
5338749e4d Fixed extraction of arguments 2022-01-21 20:03:31 -06:00
Daniel Gidman
4790c4ebb2 Support for additional dotnet publish flags. 2022-01-21 16:51:30 -06:00
rafael-aero
d646b84c74 update 16.0.7 2022-01-13 11:49:41 +01:00
Todd Schavey
64e058b0b5 #647 make ProcessVersions Entity a record to ensure readonly access to props
This is to address a PR #648 review comment to ensure that only the external
users are not able to modify the instance values.
2022-01-04 12:11:52 -05:00
Todd Schavey
24a2005776 #647 update XML documentation to ElectronNET.API Process members 2022-01-03 00:21:48 -05:00
Todd Schavey
592148116b #647 correct to ElectronNET.API Process member for versions field 2022-01-02 23:11:01 -05:00
Todd Schavey
ba82b9a600 #647 add to ElectronNET.API Process member interfaces for various fields 2022-01-02 22:46:53 -05:00
Todd Schavey
562cccbfae #647 add to ElectronNET.API Process member interfaces for argv and type 2022-01-02 18:28:39 -05:00
Todd Schavey
1406fc1d79 #647 add initial Process class to ElectronNET.API 2022-01-02 16:46:14 -05:00
Todd Schavey
8e1e184d1e #647 process argv for open-file for win and linux 2021-12-28 21:40:53 -05:00
rafael-aero
9e37d4d857 fix serializtion 2021-12-26 11:00:51 +01:00
rafael-aero
060fb19a6d Update NativeImageJsonConverter.cs 2021-12-26 09:46:55 +01:00
rafael-aero
291faa48de Missing including new file 2021-12-26 09:27:45 +01:00
rafael-aero
4358178524 Add support for DesktopCapturer 2021-12-26 09:03:48 +01:00
Daniel Gidman
4b314940d7 Update ElectronNET.sln
removing the full path reference as suggested.

Co-authored-by: alborozd <alborozd@gmail.com>
2021-12-23 10:54:44 -06:00
rafael-aero
ed841558b8 always exit if .net process exited 2021-12-23 16:54:06 +01:00
rafael-aero
36751db618 fix missing pipe option for detached process 2021-12-23 10:09:08 +01:00
rafael-aero
f229d540a8 Add simple socket auth via stdin exchange 2021-12-23 09:24:29 +01:00
rafael-aero
546c617cd0 Merge branch 'master' of https://github.com/theolivenbaum/Electron.NET 2021-12-17 13:29:49 +01:00
rafael-aero
88e8051004 update electron and electron updater 2021-12-17 13:29:47 +01:00
theolivenbaum
21427f0b44 Merge pull request #5 from theolivenbaum/clipboard-image-support-macos
add support for images in clipboards on macos
2021-12-15 18:31:49 +01:00
Pius Friesch
159c1f46c1 add support for images in clipboards on macos 2021-12-15 17:58:38 +01:00
rafael-aero
8cb235527d Change again socket reconnect logic 2021-12-15 10:44:59 +01:00
theolivenbaum
4a3a5c6aa4 Merge pull request #4 from theolivenbaum/clipboard
Clipboard
2021-12-13 18:13:47 +01:00
Pius Friesch
82bf94b2a2 fix writing images to clipboard when writing multiple formats 2021-12-13 17:40:57 +01:00
Pius Friesch
17a7886d12 formatting 2021-12-13 17:33:00 +01:00
Pius Friesch
6be3019cb6 fix typescript, based on changes to js 2021-12-13 17:31:48 +01:00
rafael-aero
3460217021 refactor socket reconnect 2021-12-13 16:22:08 +01:00
rafael-aero
427592de46 Add background thread to reconnect socket 2021-12-13 14:43:04 +01:00
rafael-aero
8f820d033a Merge branch 'master' of https://github.com/theolivenbaum/Electron.NET 2021-12-13 14:10:40 +01:00
rafael-aero
4118756711 change socket connect loop 2021-12-13 14:10:38 +01:00
Daniel Gidman
ffdf034f5f appveyor dedicated build 2021-12-09 14:01:55 -06:00
Daniel Gidman
946fbd7a72 Update appveyor image 2021-12-09 13:51:13 -06:00
Daniel Gidman
6b0205467b Support for .NET 6
Also included is the ability to target a specific project in the `electronize build/start` command using /dotnet-project
2021-12-09 13:11:24 -06:00
theolivenbaum
a28df5339d Merge pull request #3 from pfriesch/patch-1
Add Image to clipboard data
2021-12-09 17:50:54 +01:00
rafael-aero
f5a141a1c6 Update ElectronNET.API.csproj 2021-12-09 17:50:43 +01:00
Pius Friesch
b5e2b660f7 Add Image to clipboard data 2021-12-09 17:46:30 +01:00
javierlarota
431e401451 Feedback from code review. Improving logging of the domain names that will be ignored. 2021-12-09 04:22:35 +00:00
Daniel Gidman
02faeae603 Add support for Mac recent documents and clear recent documents commands on the Application Menu 2021-12-08 13:32:00 -06:00
Yannik Höflich
0d9483e325 Updated TryParseLoadUrl with UriBuilder for better readability 2021-12-08 17:30:44 +01:00
Daniel Gidman
1b14bb0fe5 Convert main static references off of Electron into interface implementation and expose the underlying Socket for low level interaction. 2021-12-07 11:52:43 -06:00
Brendan McShane
b08a0755e6 Revert automatic change by VS 2021-12-07 12:23:26 -05:00
Brendan McShane
7e89e27c26 Better way to check version
Checks to see if the dotnet 6 or greater is running.
2021-12-06 20:28:57 -05:00
Brendan McShane
e4deba2489 Add dotnet 6 check
Ensure that dotnet 6 is installed when compiling for MacOS ARM.
2021-12-06 20:17:46 -05:00
Brendan McShane
1d9e540fc2 Change back to dotnet 5 2021-12-06 20:17:08 -05:00
Yannik Höflich
c7d2dabbc3 changed the usage of loadUrl at CreateWindowAsync: adds protocol, host and port. You can also insert the port with {port} 2021-12-05 16:31:32 +01:00
theolivenbaum
2d940dbeee update to electron 16.0.4 2021-12-03 09:16:44 +01:00
javierlarota
d9d655cae8 Allow ignoring certificate errors when using an untrusted self-signed certificate for https communication with the AspCore backend.
We can ignore all cert errors or only cert errors from specific domain names configured in electron.manifest.json
2021-11-26 18:03:54 +00:00
theolivenbaum
1b7f722f31 Update Electron to 16.0.2, update electron-updater to 4.6.1 2021-11-25 08:06:49 +01:00
rafael-aero
b1c5c12004 fix null usage on ipc.js 2021-11-22 17:33:50 +01:00
rafael-aero
af0410998e update screenshot code 2021-11-22 11:38:16 +01:00
Brendan McShane
e0e8572cc1 Update README.md
Add notes about osx-arm64.
2021-11-20 21:35:02 -05:00
Brendan McShane
4ba8d9bf46 Add fix for Apple Silicon to build command 2021-11-20 18:25:46 -05:00
Brendan McShane
07d6fed712 Fix for build command 2021-11-20 18:24:41 -05:00
Brendan McShane
5dbe62bcba Add osx-arm64 support to electronize command
Updates the GetTargetPlatformInformationResult() function to add 'osx-arm64' target. 
Updates the 'default' case to automatically detect M1 mac.
2021-11-20 17:59:53 -05:00
Brendan McShane
438c8e1f14 Switch from dotnet 5.0 to dotnet 6.0
The 'osx-arm64' RID is only supported on .net versions greater than 6.0.
https://docs.microsoft.com/en-us/dotnet/core/rid-catalog
2021-11-20 17:56:33 -05:00
rafael-aero
ffedbcc5df Add missing GetFileIcon method 2021-11-20 16:37:38 +01:00
rafael-aero
9aad72431c Update electron to 16.0.1 2021-11-18 20:08:31 +01:00
rafael-aero
4405eba2d5 Add support for dark mode splashscreen 2021-11-17 14:19:07 +01:00
rafael-aero
067300bfec update nuget packages 2021-11-16 14:02:17 +01:00
theolivenbaum
b2f5a0eb34 Update to Electron 16 2021-11-16 06:45:59 +01:00
theolivenbaum
cbc150db06 Update to Electron 15.3.2 2021-11-16 06:43:15 +01:00
theolivenbaum
cbac8541be Add transparent option to webpreferences 2021-11-13 11:13:35 +01:00
rafael-aero
2f9029e267 add launch settings to test build 2021-11-10 11:07:46 +01:00
rafael-aero
390135af8a Revert "move .NET bin output to under Helpers folder to be compliant with macOS bundle formt "
This reverts commit be1182d302.
2021-11-10 11:06:40 +01:00
theolivenbaum
be1182d302 move .NET bin output to under Helpers folder to be compliant with macOS bundle formt 2021-11-10 07:57:22 +01:00
theolivenbaum
54c86d9e2f Fix auto-updater on mac not working 2021-11-10 07:46:25 +01:00
rafael-aero
2cc6823604 Update electron to 15.3.1 2021-11-09 18:16:45 +01:00
rafael-aero
326efd353c Update sdk to 6.0.100 2021-11-09 18:16:32 +01:00
rafael-aero
bd96765db5 Merge branch 'master' of https://github.com/theolivenbaum/Electron.NET 2021-11-05 11:01:33 +01:00
rafael-aero
606bb019f7 fix race condition causing unobserved exception 2021-11-05 11:01:32 +01:00
theolivenbaum
a12a7e4287 Update main.js 2021-11-03 07:51:59 +01:00
rafael-aero
5bf9aa811d Update main.js 2021-11-02 18:20:59 +01:00
rafael-aero
5477bd7f36 Add setImmediate to see if this fixes the macOS update bug 2021-11-02 15:39:57 +01:00
rafael-aero
134a5b1365 Merge branch 'master' of https://github.com/theolivenbaum/Electron.NET 2021-10-29 10:54:45 +02:00
rafael-aero
23791fcc3e fix path detection 2021-10-29 10:54:42 +02:00
theolivenbaum
751c48c804 Update Vibrancy.cs 2021-10-27 22:06:52 +02:00
theolivenbaum
316cf0108e Update Vibrancy.cs 2021-10-27 21:57:24 +02:00
rafael-aero
4caa28dc87 Merge branch 'master' of https://github.com/theolivenbaum/Electron.NET 2021-10-27 14:10:09 +02:00
rafael-aero
ad46b1a7a2 remove listeners on quitAndInstall to try fix macOS update issue 2021-10-27 14:10:07 +02:00
theolivenbaum
2297669e6d Update main.js 2021-10-27 09:11:33 +02:00
theolivenbaum
ae92973814 Update main.js 2021-10-26 22:58:54 +02:00
theolivenbaum
5ebfa2b0bd Update main.js 2021-10-26 21:34:35 +02:00
rafael-aero
1494c2f436 Update main.js 2021-10-26 18:15:37 +02:00
rafael-aero
84f027cd8d remove listeners on the call to before-quit-for-update 2021-10-26 16:27:44 +02:00
rafael-aero
f213ca4f8c move code for fixPath here 2021-10-26 15:58:55 +02:00
rafael-aero
22fa3f2780 Revert "Add fixPath to fix linux process spawn"
This reverts commit 1e50f203d8.
2021-10-26 15:41:02 +02:00
rafael-aero
b5cc631daf Revert "Update main.js"
This reverts commit b5ff42a148.
2021-10-26 15:41:00 +02:00
rafael-aero
b5ff42a148 Update main.js 2021-10-26 15:35:06 +02:00
rafael-aero
1e50f203d8 Add fixPath to fix linux process spawn
As suggested in https://github.com/electron/electron-packager/issues/603
2021-10-25 13:35:02 +02:00
rafael-aero
852b140525 Update to 15.3.0 2021-10-22 11:09:17 +02:00
rafael-aero
7e5903f5bc update to electron 15.1.2 2021-10-12 13:11:29 +02:00
rafael-aero
62003ae5fc Update BuildCommand.cs 2021-10-11 19:36:41 +02:00
Grey Wang
5cd152c1ed Fix build command logic when target is not specified 2021-10-09 20:41:12 +13:00
rafael-aero
228a5cef31 set missing return value
https://github.com/electron/electron/issues/31321
2021-10-07 18:13:32 +02:00
rafael-aero
c28355094e Update build-nuget.yaml 2021-10-07 17:54:28 +02:00
rafael-aero
329df38765 Update to Electron 15.1.1 2021-10-07 17:52:15 +02:00
AndreasJagiella-EH
5274fec200 Set PublishSingleFile default back to false for NET5 compatibility 2021-10-04 14:54:02 +02:00
Cristian Giagante
9892a90038 Adds help regarding to modify publish parameters 2021-09-26 19:54:25 -03:00
theolivenbaum
1d1e60bc63 Missed updating the nuget package version 2021-09-22 09:06:41 +02:00
theolivenbaum
21b6b14df5 Update Node to v16.9.6 2021-09-22 08:56:58 +02:00
theolivenbaum
2445b59c4d Update Electron to v15.0.0 2021-09-22 08:55:04 +02:00
rafael-aero
9a8584795b update to net6.0 2021-09-17 18:16:31 +02:00
rafael-aero
e6ea9883fd code cleanup 2021-09-17 16:05:40 +02:00
rafael-aero
e1edc764d6 update electron to 14.0.1 2021-09-16 19:39:16 +02:00
rafael-aero
51013d5825 code cleanup 2021-09-15 11:14:45 +02:00
rafael-aero
664d5f7236 Add method to get window by id 2021-09-15 11:02:54 +02:00
rafael-aero
75d7924251 Merge branch 'master' of https://github.com/theolivenbaum/Electron.NET 2021-09-15 10:58:45 +02:00
rafael-aero
c2904f3f68 Change second instance activation to raise event instead of trying to blindly open any window 2021-09-15 10:58:43 +02:00
theolivenbaum
adef39f3ec Change flags to nullable 2021-09-10 10:53:49 +02:00
theolivenbaum
836eebf256 Update browserWindows.js 2021-09-10 10:13:23 +02:00
theolivenbaum
124d24a19c Update browserWindows.ts 2021-09-10 10:12:56 +02:00
theolivenbaum
67ea8c768e Update BrowserWindow.cs 2021-09-10 10:11:41 +02:00
theolivenbaum
8604b50224 Add method to destroy all windows manually 2021-09-08 08:57:05 +02:00
theolivenbaum
5559fc61b1 force-destroy all windows on before-quit-for-update 2021-09-08 08:47:16 +02:00
theolivenbaum
9be80abfcf Add method to destroy splashscreen 2021-09-07 19:19:49 +02:00
theolivenbaum
6a4a7eff1c Workaround for electron freeze bug 2021-09-07 17:48:12 +02:00
theolivenbaum
a637174b93 typo 2021-09-07 15:00:35 +02:00
theolivenbaum
dc2662e52e Add way to set flags for Electron before the app starts 2021-09-07 14:36:57 +02:00
theolivenbaum
801616cd53 Let users set the color of the titlebar instead of just enabling it 2021-09-06 15:54:32 +02:00
theolivenbaum
9693c82792 Add TitleBarOverlay option 2021-09-06 15:18:59 +02:00
theolivenbaum
a3fb411d8a always keep default values when creating window 2021-09-06 12:39:32 +02:00
theolivenbaum
172f6ded3f Merge branch 'master' of https://github.com/theolivenbaum/Electron.NET 2021-09-06 11:45:01 +02:00
theolivenbaum
bbbc9e6f61 make splashscreen draggable 2021-09-06 11:44:57 +02:00
rafael-aero
236c31abe0 Merge branch 'master' of https://github.com/theolivenbaum/Electron.NET 2021-09-03 15:28:34 +02:00
rafael-aero
374d92f3b1 don't throw in case the tray was destroyed between calls 2021-09-03 15:28:32 +02:00
theolivenbaum
ea40249a9c refactor Socket to use a task completion source instead of a getter with locks 2021-09-02 20:37:22 +02:00
theolivenbaum
7f5db58edd fix deadlock case on emit before any Socket use 2021-09-02 20:06:01 +02:00
theolivenbaum
d18700f64d missing static flag 2021-09-02 18:29:02 +02:00
theolivenbaum
47f4516ae2 Add flag to check if the socket is connected 2021-09-02 18:20:11 +02:00
theolivenbaum
bb8965fa91 remove semaphore in favor of unique events per window /view create request 2021-09-02 17:24:07 +02:00
theolivenbaum
c229d49765 remove debug message 2021-09-02 16:45:20 +02:00
theolivenbaum
4fae2aeef2 fix ipc data serialization 2021-09-02 16:45:03 +02:00
theolivenbaum
5f4b1628e5 fix display serialization, serialize only window id when sending ipc message 2021-09-02 16:34:20 +02:00
theolivenbaum
25af4a7314 Update to Electron 14 2021-09-02 16:18:56 +02:00
rafael-aero
14ee45b88f Another attempt 2021-09-01 22:37:58 +02:00
rafael-aero
badc9f26b6 Revert "fix closed behaviour"
This reverts commit 4e7cebe519.
2021-09-01 22:25:50 +02:00
rafael-aero
4e7cebe519 fix closed behaviour 2021-09-01 22:10:44 +02:00
rafael-aero
ec74c7989a Update ipc.js 2021-09-01 21:31:30 +02:00
rafael-aero
a2579b221f fix wrong Id being passed - needed browser id, not webcontent id 2021-09-01 21:30:47 +02:00
rafael-aero
1e7ff5b6d6 fix getting id 2021-09-01 20:57:41 +02:00
rafael-aero
eac14427df Add event handler with sender id 2021-09-01 20:42:49 +02:00
rafael-aero
794248a83c fix creation of windows not being thread safe 2021-09-01 20:02:17 +02:00
rafael-aero
9a938dc680 use concurrent dictionary instead of list 2021-09-01 18:59:15 +02:00
rafael-aero
2d68ca5270 Fix LogError call 2021-09-01 18:29:20 +02:00
rafael-aero
548609f69b add handler for errors on socket.on calls 2021-09-01 18:28:44 +02:00
rafael-aero
7b5bac2083 Fix property assignment 2021-09-01 14:08:30 +02:00
rafael-aero
5ba10136e2 Add excludedFromShownWindowsMenu and TrafficLightPosition 2021-09-01 14:07:45 +02:00
tub5
aba77b1361 Update README.md
Fixed versions on the README
2021-08-31 11:56:26 +01:00
rafael-aero
bd45e23768 remove recreate behaviour from activate event on mac, and emit event to handler instead 2021-08-30 13:22:07 +02:00
rafael-aero
35b18a9501 ignore process closing if going for an update 2021-08-26 17:04:16 +02:00
rafael-aero
89d41a2750 restore serialization settings where it makes sense 2021-08-26 16:08:11 +02:00
rafael-aero
efdaf0e341 remove defaultvaluehandling setting as this breaks some cases
(like X:0 on browser view set bounds)
2021-08-26 15:59:52 +02:00
rafael-aero
0728577c40 missing using 2021-08-26 14:23:32 +02:00
rafael-aero
224bc1ef65 Add supported OS platform annotations 2021-08-26 14:22:54 +02:00
rafael-aero
7ad6803671 improve reconnect logic by waiting for reconnect before emit 2021-08-26 10:31:06 +02:00
rafael-aero
81a8367dac improve reconnect logic 2021-08-26 10:19:24 +02:00
rafael-aero
1161f59836 Update BridgeConnector.cs 2021-08-26 10:08:42 +02:00
rafael-aero
e7c56274e6 Update BridgeConnector.cs 2021-08-26 09:55:24 +02:00
rafael-aero
44d979fef4 Use ILogger instead of Console.WriteLine 2021-08-26 09:55:14 +02:00
theolivenbaum
2f0229235b fix for socket not being thread-safe 2021-08-26 08:40:36 +02:00
rafael-aero
18d425b042 Merge branch 'master' into switch-to-new-socket-lib 2021-08-25 17:08:53 +02:00
rafael-aero
5e82ae4246 add socket events to emit console messages 2021-08-25 13:38:30 +02:00
rafael-aero
48d5497045 Revert "Update main.js"
This reverts commit be41cae3bd.
2021-08-25 13:33:50 +02:00
rafael-aero
be41cae3bd Update main.js 2021-08-25 13:24:44 +02:00
rafael-aero
64b91fc235 Update main.js 2021-08-25 13:04:23 +02:00
rafael-aero
efec886f73 Update main.js 2021-08-25 11:33:32 +02:00
rafael-aero
8b03a6b006 remove stdio handling for detached case 2021-08-25 11:27:46 +02:00
rafael-aero
144a0a0ddc change argument name, detach process on creation 2021-08-25 11:14:21 +02:00
rafael-aero
8bbe6a96af Fix serialization of array of objects 2021-08-25 10:34:36 +02:00
rafael-aero
e39e34234d Update ProcessHelper.cs 2021-08-25 09:54:00 +02:00
rafael-aero
67c592a060 kill child process when electronize cli is killed 2021-08-25 09:38:37 +02:00
rafael-aero
bad59463a9 pass electron process id to child 2021-08-25 09:17:50 +02:00
rafael-aero
94efaf835e Merge branch 'master' of https://github.com/theolivenbaum/Electron.NET 2021-08-25 09:10:29 +02:00
rafael-aero
ac77643fc4 add variable to control kill behaviour 2021-08-25 09:10:27 +02:00
theolivenbaum
0393b0bd45 Merge branch 'master' into switch-to-new-socket-lib 2021-08-24 05:31:57 +02:00
theolivenbaum
953f1e2641 fix event names for when there are more than one window, view or webcontent Id 2021-08-24 05:31:46 +02:00
rafael-aero
fb99dbd5b5 add null return to avoid having to check for undefined 2021-08-23 18:28:00 +02:00
rafael-aero
fdbf7187b9 Update browserWindows.js 2021-08-23 15:30:47 +02:00
rafael-aero
9a680a41ac improve how we handle when window has been destroyed already 2021-08-23 14:59:41 +02:00
rafael-aero
f9693ce624 handle destroyed windows 2021-08-23 14:29:41 +02:00
rafael-aero
0090a7c239 fix wrong completed event name 2021-08-23 13:24:02 +02:00
rafael-aero
81431599ec Update ElectronNET.API.csproj 2021-08-23 13:01:38 +02:00
rafael-aero
31094f9d2b Remove unecessary JsonSerializer settings, fix default serializer 2021-08-23 11:57:42 +02:00
rafael-aero
bf48bc8227 replace remaining cases with OnResult, fix deserialization of json objects 2021-08-23 11:22:37 +02:00
rafael-aero
87d97efcfa Merge branch 'master' into switch-to-new-socket-lib 2021-08-21 09:17:43 +02:00
theolivenbaum
da9d9658f5 Update main.js 2021-08-21 09:17:20 +02:00
theolivenbaum
444c09fb4d Update main.js 2021-08-21 08:26:43 +02:00
rafael-aero
ca9bee7bf0 Merge branch 'master' into switch-to-new-socket-lib 2021-08-20 15:16:16 +02:00
rafael-aero
0aab352f86 remove yield call 2021-08-20 15:07:39 +02:00
rafael-aero
a8229f2fa9 add internal method to emit socket events synchronously, and use it for all exit, quit and relaunch methods 2021-08-20 15:06:58 +02:00
rafael-aero
9daaebcef6 Add timeout property for splashscreen 2021-08-20 14:56:47 +02:00
rafael-aero
67b59d95d4 fix quotes 2021-08-20 14:52:33 +02:00
rafael-aero
8f71480b3e Merge branch 'master' into switch-to-new-socket-lib 2021-08-20 14:49:56 +02:00
rafael-aero
133dcd6b65 Fix exit method 2021-08-20 14:49:49 +02:00
rafael-aero
d9a7411904 Merge branch 'master' into switch-to-new-socket-lib 2021-08-20 14:36:09 +02:00
rafael-aero
b42eba8a70 Handle non-zero exit codes from ASP.NET process 2021-08-20 14:36:02 +02:00
rafael-aero
e8e3649925 Merge branch 'master' into switch-to-new-socket-lib 2021-08-19 14:50:46 +02:00
rafael-aero
b6338ac7de log error messages from asp-net process 2021-08-19 14:50:30 +02:00
rafael-aero
b708b4b622 reset default values 2021-08-18 10:48:55 +02:00
rafael-aero
336c3b9400 cleanup for merge 2021-08-18 10:42:24 +02:00
rafael-aero
bd08938c49 Delete build-nuget.yaml 2021-08-18 10:32:41 +02:00
rafael-aero
cbe0637e84 Simplify repeated code with OnResult method, fix race condition with multiple calls to On/Off for the same event 2021-08-18 10:24:12 +02:00
rafael-aero
8063f49e4b run all continuations asyncronously 2021-08-17 16:28:07 +02:00
rafael-aero
d6b29f7350 avoid calling npm install if nothing changed 2021-08-09 17:43:54 +02:00
rafael-aero
237638a5b3 add command for simple build 2021-08-09 17:32:24 +02:00
Matt
b910807ced Log errors in the dotnet process 2021-08-04 17:33:09 +02:00
rafael-aero
7fe8f6e49e fix wrong object initializer 2021-07-21 17:04:29 +02:00
rafael-aero
c4ff481131 add debug option 2021-07-21 10:42:04 +02:00
rafael-aero
9107b161b3 Add prototype from-build-output command 2021-07-13 11:25:00 +02:00
rafael-aero
ec2261f1c5 Remove wrong ReleaseNoteInfo model 2021-07-13 09:08:31 +02:00
theolivenbaum
b03bc7c9eb Clean-up 2021-07-12 21:33:35 +02:00
theolivenbaum
e6214491cf Merge pull request #2 from theolivenbaum/remove-deprecated-socket-lib
Remove deprecated socket lib
2021-07-12 21:28:07 +02:00
theolivenbaum
95d614796e works 2021-07-12 21:27:40 +02:00
rafael-aero
126d39f4a5 wip 2021-07-12 19:50:39 +02:00
rafael-aero
8880e040f7 remove remaining .Result calls 2021-07-12 18:16:07 +02:00
rafael-aero
f200013165 add custom property handle for electronize start command 2021-07-12 17:05:26 +02:00
rafael-aero
82755e399d Add comments 2021-07-12 15:54:23 +02:00
rafael-aero
f07f2e9506 Update build-nuget.yaml 2021-07-12 15:53:02 +02:00
rafael-aero
83fd5a5d4b Add manual initialization methods 2021-07-12 15:52:30 +02:00
rafael-aero
6dee08379c Merge remote-tracking branch 'upstream/master' 2021-07-12 09:24:32 +02:00
rafael-aero
8f5a7856d5 use new Electron 12 default values 2021-06-28 16:30:24 +02:00
rafael-aero
f78573401a fix strange issue with capitalization of assembly name 2021-06-28 16:08:00 +02:00
rafael-aero
d8ba9d9372 change assembly name 2021-06-28 15:48:15 +02:00
rafael-aero
09cb7a640f Update EmbeddedFileHelper.cs 2021-06-28 15:43:55 +02:00
rafael-aero
2f3d2c00b6 print all resource names 2021-06-28 15:43:40 +02:00
rafael-aero
3b7b592ac8 fix name on resource path 2021-06-28 15:21:41 +02:00
rafael-aero
bcbe76211c Add option to set electron version 2021-06-28 15:04:26 +02:00
rafael-aero
505a5b2204 fix NPM install 2021-06-28 15:01:10 +02:00
rafael-aero
468a4fa35b fix package name 2021-06-28 14:35:59 +02:00
rafael-aero
94b5faafcd add publish to nuget 2021-06-28 14:31:33 +02:00
rafael-aero
f08711e41b Fix variables 2021-06-28 14:26:27 +02:00
theolivenbaum
1a6d50d77a Set up CI with Azure Pipelines
[skip ci]
2021-06-28 14:19:47 +02:00
rafael-aero
d188baaaff Merge remote-tracking branch 'MiniguyBrendan/master' 2021-06-28 14:11:08 +02:00
rafael-aero
916eecf117 Merge branch 'bug/578' 2021-06-28 14:08:45 +02:00
760 changed files with 22076 additions and 43467 deletions

84
.devops/build-nuget.yaml Normal file
View File

@@ -0,0 +1,84 @@
variables:
PackageVersion: 19.0.9.$(Build.BuildId)
projectAPI: './ElectronNET.API/ElectronNET.API.csproj'
projectCLI: './ElectronNET.CLI/ElectronNET.CLI.csproj'
trigger:
- master
pool:
vmImage: windows-latest
steps:
- checkout: self
submodules: true
fetchDepth: 10
- task: NuGetToolInstaller@1
- task: UseDotNet@2
displayName: 'Use .NET Core sdk'
inputs:
packageType: sdk
version: 6.0.100
installationPath: $(Agent.ToolsDirectory)/dotnet
- task: DotNetCoreCLI@2
displayName: 'restore nuget'
inputs:
command: 'restore'
projects: '$(projectAPI)'
- task: DotNetCoreCLI@2
displayName: 'restore nuget'
inputs:
command: 'restore'
projects: '$(projectCLI)'
- task: DotNetCoreCLI@2
inputs:
command: 'build'
projects: '$(projectAPI)'
arguments: '--configuration Release --force /property:Version=$(PackageVersion)'
- task: DotNetCoreCLI@2
inputs:
command: 'build'
projects: '$(projectCLI)'
arguments: '--configuration Release --force /property:Version=$(PackageVersion)'
- task: DotNetCoreCLI@2
inputs:
command: 'pack'
packagesToPack: '$(projectAPI)'
configuration: 'Release'
versioningScheme: 'off'
buildProperties: 'Version=$(PackageVersion)'
arguments: -IncludeReferencedProjects
- task: DotNetCoreCLI@2
inputs:
command: 'pack'
packagesToPack: '$(projectCLI)'
configuration: 'Release'
versioningScheme: 'off'
buildProperties: 'Version=$(PackageVersion)'
- task: NuGetCommand@2
displayName: 'push API to nuget'
inputs:
command: 'push'
packagesToPush: '$(Build.ArtifactStagingDirectory)/h5.ElectronNET.API.$(PackageVersion).nupkg'
nuGetFeedType: 'external'
publishFeedCredentials: 'nuget-curiosity'
- task: NuGetCommand@2
displayName: 'push CLI to nuget'
inputs:
command: 'push'
packagesToPush: '$(Build.ArtifactStagingDirectory)/h5.ElectronNET.CLI.$(PackageVersion).nupkg'
nuGetFeedType: 'external'
publishFeedCredentials: 'nuget-curiosity'

View File

@@ -1,137 +0,0 @@
# Contributing
## Project Scope
The Electron.NET project ultimately tries to provide a framework for developing cross-platform client applications on the basis of .NET and Electron. Anything that is related to this goal will be considered. The project aims to be as close to Electron with .NET as a basis as possible. If your contribution does not reflect that goal, the chances of accepting it are limited.
## Code License
This is an open source project falling under the [MIT License](../LICENSE). By using, distributing, or contributing to this project, you accept and agree that all code within the Electron.NET project and its libraries are licensed under MIT license.
## Becoming a Contributor
Usually appointing someone as a contributor follows this process:
1. An individual contributes actively via discussions (reporting bugs, giving feedback to existing or opening new issues) and / or pull requests
2. The individual is either directly asked, invited or asks for contributor rights on the project
3. The individual uses the contribution rights to sustain or increase the active contributions
Every contributor might have to sign the contributor's license agreement (CLA) to establish a legal trust between the project and its contributors.
## Working on Electron.NET
### Issue Discussion
Discussion of issues should be placed transparently in the issue tracker here on GitHub.
* [General issues, bugs, new features](https://github.com/ElectronNET/Electron.NET/issues)
* [General discussions, help, exchange of ideas](https://github.com/ElectronNET/Electron.NET/discussions)
### Modifying the code
Electron.NET and its libraries uses features from the latest versions of C# (e.g., C# 10). You will therefore need a C# compiler that is up for the job.
1. Fork and clone the repo.
2. First try to build the ElectronNET.Core library and see if you get the tests running.
3. You will be required to resolve some dependencies via NuGet.
The build system of Electron.NET uses NUKE.
### Code Conventions
Most parts in the Electron.NET project are fairly straight forward. Among these are:
* Always use statement blocks for control statements, e.g., in a for-loop, if-condition, ...
* You may use a simple (throw) statement in case of enforcing contracts on argument
* Be explicit about modifiers (some files follow an older convention of the code base, but we settled on the explicit style)
### Development Workflow
1. If no issue already exists for the work you'll be doing, create one to document the problem(s) being solved and self-assign.
2. Otherwise please let us know that you are working on the problem. Regular status updates (e.g. "still in progress", "no time anymore", "practically done", "pull request issued") are highly welcome.
3. Create a new branch—please don't work in the `main` branch directly. It is reserved for releases. We recommend naming the branch to match the issue being addressed (`feature/#777` or `issue-777`).
4. Add failing tests for the change you want to make. Tests are crucial and should be taken from W3C (or other specification).
5. Fix stuff. Always go from edge case to edge case.
6. All tests should pass now. Also your new implementation should not break existing tests.
7. Update the documentation to reflect any changes. (or document such changes in the original issue)
8. Push to your fork or push your issue-specific branch to the main repository, then submit a pull request against `develop`.
Just to illustrate the git workflow for Electron.NET a little bit more we've added the following graphs.
Initially, Electron.NET starts at the `main` branch. This branch should contain the latest stable (or released) version.
Here we now created a new branch called `develop`. This is the development branch.
Now active work is supposed to be done. Therefore a new branch should be created. Let's create one:
```sh
git checkout -b feature/#777
```
There may be many of these feature branches. Most of them are also pushed to the server for discussion or synchronization.
```sh
git push -u origin feature/#777
```
Now feature branches may be closed when they are done. Here we simply merge with the feature branch(es). For instance the following command takes the `feature/#777` branch from the server and merges it with the `develop` branch.
```sh
git checkout develop
git pull
git pull origin feature/#777
git push
```
Finally, we may have all the features that are needed to release a new version of Electron.NET. Here we tag the release. For instance for the 1.0 release we use `v1.0`.
```sh
git checkout main
git merge develop
git tag v1.0
```
(The last part is automatically performed by our CI system. Don't tag manually.)
### Versioning
The rules of [semver](http://semver.org/) don't necessarily apply here, but we will try to stay quite close to them.
Prior to version 1.0.0 we use the following scheme:
1. MINOR versions for reaching a feature milestone potentially combined with dramatic API changes
2. PATCH versions for refinements (e.g. performance improvements, bug fixes)
After releasing version 1.0.0 the scheme changes to become:
1. MAJOR versions at maintainers' discretion following significant changes to the codebase (e.g., API changes)
2. MINOR versions for backwards-compatible enhancements (e.g., performance improvements)
3. PATCH versions for backwards-compatible bug fixes (e.g., spec compliance bugs, support issues)
#### Code style
Regarding code style like indentation and whitespace, **follow the conventions you see used in the source already.** In general most of the [C# coding guidelines from Microsoft](https://msdn.microsoft.com/en-us/library/ff926074.aspx) are followed. This project prefers type inference with `var` to explicitly stating (redundant) information.
It is also important to keep a certain `async`-flow and to always use `ConfigureAwait(false)` in conjunction with an `await` expression.
## Backwards Compatibility
We always try to remain backwards compatible beyond the currently supported versions of .NET.
For instance, in December 2025 there have been activity to remove .NET 6 support from the codebase. We rejected this. Key points:
1. We have absolutely no need to drop `.net6` support. It doesn't hurt us in any way.
2. Many are still using `.net6`, including Electron.NET (non-Core) users. It doesn't make sense to force them to update two things at the same time (.NET + Electron.NET).
3. We MUST NOT and NEVER update `Microsoft.Build.Utilities.Core`. This will make Electron.NET stop working on older Visual Studio and MSBuild versions. There's are also no reasons to update it in the first place.
It's important to note that the Microsoft label of "Out of support" on .NET has almost no practical meaning. We've rarely (if ever) seen any bugs fixed in the same .NET version which mattered. The bugs that all new .NET versions have are much worse than mature .NET versions which are declared as "out of support". Keep in mind that the LTS matters most for active development / ongoing supported projects. If, e.g., a TV has been released a decade ago it most likely won't be patched. Still, you might want to deploy applications to it, which then naturally would involve being based on "out of support" versions of the framework.
TL;DR: Unless there is a technical reason (e.g., a crucial new API not being available) we should not drop "out of support" .NET versions. At the time of writing (December 2025) the minimum supported .NET version remains at `.net6`.
## Timeline
**All of this information is related to ElectronNET.Core pre-v1!**
We pretty much release whenever we have something new (i.e., do fixes such as a 0.1.1, or add new features, such as a 0.2.0) quite quickly.
We will go for a 1.0.0 release of this as early as ~mid of January 2026 (unless we find some critical things or want to extend the beta phase for ElectronNET.Core). This should be sufficient time to get some user input and have enough experience to call it stable.

2
.github/FUNDING.yml vendored
View File

@@ -1,6 +1,6 @@
# These are supported funding model platforms
github: [GregorBiswanger, FlorianRappl]
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username

BIN
.github/WikiLinks.exe vendored

Binary file not shown.

View File

@@ -1,43 +0,0 @@
name: Build and Publish
on: [push]
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
concurrency:
group: build-publish-${{ github.ref }}
cancel-in-progress: true
jobs:
Integration-Tests:
uses: ./.github/workflows/integration-tests.yml
name: '1'
Publish:
needs: [Integration-Tests]
runs-on: windows-latest
timeout-minutes: 10
name: '2 / Publish'
steps:
- uses: actions/checkout@v4
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
8.0.x
10.0.x
- name: Build
run: |
if ($env:GITHUB_REF -eq "refs/heads/main") {
.\build.ps1 -Target Publish
} elseif ($env:GITHUB_REF -eq "refs/heads/develop") {
.\build.ps1 -Target PrePublish
} else {
.\build.ps1
}

View File

@@ -1,39 +0,0 @@
name: PR Validation
on: [pull_request]
concurrency:
group: pr-validation-${{ github.ref }}
cancel-in-progress: true
jobs:
Whitespace-Check:
uses: ./.github/workflows/trailing-whitespace-check.yml
secrets: inherit
name: '1'
Tests:
needs: Whitespace-Check
uses: ./.github/workflows/integration-tests.yml
secrets: inherit
name: '2'
build:
needs: [Whitespace-Check, Tests]
runs-on: windows-latest
timeout-minutes: 10
name: '3 / Build'
steps:
- uses: actions/checkout@v4
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
8.0.x
10.0.x
- name: Build
run: .\build.ps1

View File

@@ -1,220 +0,0 @@
name: Tests
on:
workflow_call:
concurrency:
group: integration-tests-${{ github.ref }}
cancel-in-progress: true
jobs:
tests:
name: ${{ matrix.os }} API-${{ matrix.electronVersion }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu-24.04, windows-2022, windows-2025, macos-14, macos-15-intel, macos-26]
electronVersion: ['30.4.0', '38.2.2']
include:
- os: ubuntu-22.04
rid: linux-x64
- os: ubuntu-24.04
rid: linux-x64
- os: windows-2022
rid: win-x64
- os: windows-2025
rid: win-x64
- os: macos-14
rid: osx-arm64
- os: macos-15-intel
rid: osx-x64
- os: macos-26
rid: osx-arm64
env:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
DOTNET_NOLOGO: 1
CI: true
ELECTRON_ENABLE_LOGGING: 1
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Random delay (0-20 seconds)
shell: bash
run: |
DELAY=$((RANDOM % 21))
echo "Waiting for $DELAY seconds..."
sleep $DELAY
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
- name: Restore
run: dotnet restore -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} -p:ElectronVersion=${{ matrix.electronVersion }} src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj
- name: Build
run: dotnet build --no-restore -c Release -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} -p:ElectronVersion=${{ matrix.electronVersion }} src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj
- name: Install Linux GUI dependencies
if: runner.os == 'Linux'
run: |
set -e
sudo apt-get update
. /etc/os-release
if [ "$VERSION_ID" = "24.04" ]; then ALSA_PKG=libasound2t64; else ALSA_PKG=libasound2; fi
echo "Using ALSA package: $ALSA_PKG"
sudo apt-get install -y xvfb \
libgtk-3-0 libnss3 libgdk-pixbuf-2.0-0 libdrm2 libgbm1 libxss1 libxtst6 libatk-bridge2.0-0 libatk1.0-0 libatspi2.0-0 libx11-xcb1 "$ALSA_PKG"
- name: Run tests (Linux)
if: runner.os == 'Linux'
continue-on-error: true
run: |
mkdir -p test-results
xvfb-run -a dotnet test src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj \
-c Release --no-build -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} -p:ElectronVersion=${{ matrix.electronVersion }} \
--logger "trx;LogFileName=${{ matrix.os }}-electron-${{ matrix.electronVersion }}.trx" \
--logger "console;verbosity=detailed" \
--results-directory test-results
- name: Run tests (Windows)
if: runner.os == 'Windows'
continue-on-error: true
run: |
New-Item -ItemType Directory -Force -Path test-results | Out-Null
dotnet test src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj -c Release --no-build -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} -p:ElectronVersion=${{ matrix.electronVersion }} --logger "trx;LogFileName=${{ matrix.os }}-electron-${{ matrix.electronVersion }}.trx" --logger "console;verbosity=detailed" --results-directory test-results
- name: Run tests (macOS)
if: runner.os == 'macOS'
continue-on-error: true
run: |
mkdir -p test-results
dotnet test src/ElectronNET.IntegrationTests/ElectronNET.IntegrationTests.csproj -c Release --no-build -r ${{ matrix.rid }} -p:RuntimeIdentifier=${{ matrix.rid }} -p:ElectronVersion=${{ matrix.electronVersion }} --logger "trx;LogFileName=${{ matrix.os }}-electron-${{ matrix.electronVersion }}.trx" --logger "console;verbosity=detailed" --results-directory test-results
- name: Upload raw test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.os }}-electron-${{ matrix.electronVersion }}
path: test-results/*.trx
retention-days: 7
summary:
name: Test Results
runs-on: ubuntu-24.04
if: always()
needs: [tests]
permissions:
actions: read
contents: read
checks: write
pull-requests: write
steps:
- name: Download all test results
uses: actions/download-artifact@v4
with:
path: test-results
- name: Setup .NET (for CTRF conversion)
uses: actions/setup-dotnet@v4
with:
dotnet-version: '10.0.x'
- name: Install CTRF TRX→CTRF converter (dotnet tool)
run: |
dotnet new tool-manifest
dotnet tool install DotnetCtrfJsonReporter --local
- name: Convert TRX → CTRF and clean names (filePath=OS|Electron X.Y.Z)
shell: bash
run: |
set -euo pipefail
mkdir -p ctrf
shopt -s globstar nullglob
conv=0
for trx in test-results/**/*.trx; do
base="$(basename "$trx" .trx)" # e.g. ubuntu-22.04-electron-30.4.0
os="${base%%-electron-*}"
electron="${base#*-electron-}"
label="$os|Electron $electron"
outdir="ctrf/${label}"
mkdir -p "$outdir"
out="${outdir}/ctrf-report.json"
dotnet tool run DotnetCtrfJsonReporter -p "$trx" -d "$outdir" -f "ctrf-report.json"
jq --arg fp "$label" '.results.tests |= map(.filePath = $fp)' "$out" > "${out}.tmp" && mv "${out}.tmp" "$out"
echo "Converted & normalized $trx -> $out"
conv=$((conv+1))
done
echo "Processed $conv TRX file(s)"
- name: Publish Test Report
if: always()
uses: ctrf-io/github-test-reporter@v1
with:
report-path: 'ctrf/**/*.json'
summary: true
pull-request: false
status-check: false
status-check-name: 'Integration Tests'
use-suite-name: true
update-comment: true
always-group-by: true
overwrite-comment: true
exit-on-fail: true
group-by: 'suite'
upload-artifact: true
fetch-previous-results: true
summary-report: false
summary-delta-report: true
github-report: true
test-report: false
test-list-report: false
failed-report: true
failed-folded-report: false
skipped-report: true
suite-folded-report: true
suite-list-report: false
file-report: true
previous-results-report: true
insights-report: true
flaky-report: true
flaky-rate-report: true
fail-rate-report: false
slowest-report: false
report-order: 'summary-delta-report,failed-report,skipped-report,suite-folded-report,file-report,previous-results-report,github-report'
env:
GITHUB_TOKEN: ${{ github.token }}
- name: Save PR Number
if: github.event_name == 'pull_request'
run: echo "PR_NUMBER=${{ github.event.pull_request.number }}" >> $GITHUB_ENV
- name: Write PR Number to File
if: github.event_name == 'pull_request'
run: echo "$PR_NUMBER" > pr_number.txt
shell: bash
- name: Upload PR Number Artifact
if: github.event_name == 'pull_request'
uses: actions/upload-artifact@v4
with:
name: pr_number
path: pr_number.txt
- name: Summary
run: echo "All matrix test jobs completed."

View File

@@ -1,81 +0,0 @@
name: Create PR Comments
on:
workflow_run:
workflows: [ "PR Validation" ]
types: [completed]
permissions:
contents: read
actions: read
pull-requests: write
jobs:
pr-comment:
name: Post Test Result as PR comment
runs-on: ubuntu-24.04
if: github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion != 'cancelled'
steps:
- name: Download CTRF artifact
uses: dawidd6/action-download-artifact@v8
with:
github_token: ${{ github.token }}
run_id: ${{ github.event.workflow_run.id }}
name: ctrf-report
path: ctrf
- name: Download PR Number Artifact
uses: dawidd6/action-download-artifact@v8
with:
github_token: ${{ github.token }}
run_id: ${{ github.event.workflow_run.id }}
name: pr_number
path: pr_number
- name: Read PR Number
run: |
set -Eeuo pipefail
FILE='pr_number/pr_number.txt'
# Ensure file exists
if [ ! -f "$FILE" ] || [ -L "$FILE" ]; then
echo "Error: $FILE is missing or is not a regular file." >&2
exit 1
fi
# Chec file size
if [ "$(wc -c < "$FILE" | tr -d ' ')" -gt 200 ]; then
echo "Error: $FILE is too large." >&2
exit 1
fi
# Read first line
PR_NUMBER=""
IFS= read -r PR_NUMBER < "$FILE" || true
# Validate whether it's a number
if ! [[ "$PR_NUMBER" =~ ^[0-9]{1,10}$ ]]; then
echo "Error: PR_NUMBER is not a valid integer on the first line." >&2
exit 1
fi
printf 'PR_NUMBER=%s\n' "$PR_NUMBER" >> "$GITHUB_ENV"
- name: Post PR Comment
uses: ctrf-io/github-test-reporter@v1
with:
report-path: 'ctrf/**/*.json'
issue: ${{ env.PR_NUMBER }}
summary: true
pull-request: true
use-suite-name: true
update-comment: true
always-group-by: true
overwrite-comment: true
upload-artifact: false
pull-request-report: true
env:
GITHUB_TOKEN: ${{ github.token }}

View File

@@ -1,59 +0,0 @@
name: Publish wiki
on:
push:
branches: [electronnet_core, main]
workflow_dispatch:
concurrency:
group: publish-wiki
cancel-in-progress: true
permissions:
contents: write
jobs:
publish-wiki:
runs-on: windows-latest
steps:
- uses: actions/checkout@v3
- name: Remove level 1 headings from Markdown files
shell: bash
run: |
find docs/ -name '*.md' -exec sed -i '1d' {} \;
- name: Move all files to root folder
shell: bash
run: |
mv docs/*/* docs/
- name: Delete unwanted files
shell: bash
run: |
# rm docs/*.xlsm
# rm docs/*.pptx
rm docs/*.shproj
- name: Stripping file extensions....
uses: softworkz/strip-markdown-extensions-from-links-action@main
with:
path: ./docs/
- name: Copy Changelog
shell: bash
run: |
cp Changelog.md docs/RelInfo/ 2>/dev/null || true
- name: Copy images to wiki/wiki folder
shell: bash
run: |
mkdir docs/wiki
cp docs/*.svg docs/wiki/ 2>/dev/null || true
cp docs/*.png docs/wiki/ 2>/dev/null || true
cp docs/*.jpg docs/wiki/ 2>/dev/null || true
cp docs/*.gif docs/wiki/ 2>/dev/null || true
cp docs/*.mp4 docs/wiki/ 2>/dev/null || true
- name: Commit and push changes
run: |
git config --global user.name "GitHub Action"
git config --global user.email "action@github.com"
git add -A
git commit -m "Automatically update Markdown files" || echo "No changes to commit"
- uses: Andrew-Chen-Wang/github-wiki-action@v4.4.0
with:
path: docs/
ignore: |
'**/*.xlsm'
'**/*.pptx'
'**/*.shproj'

View File

@@ -1,49 +0,0 @@
name: Tests auto-rerun
on:
workflow_run:
workflows: [ "PR Validation", "Build and Publish" ]
types: [ completed ]
jobs:
rerun-failed-matrix-jobs-once:
if: >
${{
github.event.workflow_run.conclusion == 'failure' &&
github.event.workflow_run.run_attempt == 1
}}
runs-on: ubuntu-24.04
permissions:
actions: write
contents: read
steps:
- name: Decide whether to rerun (only if matrix jobs failed)
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
RUN_ID: ${{ github.event.workflow_run.id }}
run: |
echo "Inspecting jobs of workflow run $RUN_ID in $REPO"
jobs_json="$(gh api -R $REPO repos/$REPO/actions/runs/$RUN_ID/jobs)"
echo "Jobs and conclusions:"
echo "$jobs_json" | jq '.jobs[] | {name: .name, conclusion: .conclusion}'
failed_matrix_jobs=$(echo "$jobs_json" | jq -r '
[ .jobs[]
| select(.conclusion == "failure"
and (.name | contains(" API-")))
]
| length // 0
')
failed_matrix_jobs=${failed_matrix_jobs:-0}
if [ "${failed_matrix_jobs}" -gt 0 ]; then
echo "Detected failing Integration Tests jobs re-running failed jobs for this run."
gh run rerun -R "$REPO" "$RUN_ID" --failed
else
echo "Only non-matrix jobs (like Test Results) failed not auto-rerunning."
fi

View File

@@ -1,84 +0,0 @@
name: Whitespace Check
on:
workflow_call:
jobs:
check-whitespace:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Check for trailing whitespace
run: |
echo "Checking for trailing whitespace in changed files..."
# Get the base branch
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
# Get list of changed files (excluding deleted files)
CHANGED_FILES=$(git diff --name-only --diff-filter=d "$BASE_SHA" "$HEAD_SHA")
if [ -z "$CHANGED_FILES" ]; then
echo "No files to check."
exit 0
fi
# File patterns to check (text files)
PATTERNS="\.cs$|\.csproj$|\.sln$|\.ts$|\.html$|\.css$|\.scss$"
# Directories and file patterns to exclude
EXCLUDE_PATTERNS="(^|\/)(\.|node_modules|bin|obj|artifacts|packages|\.vs|\.nuke\/temp)($|\/)"
ERRORS_FOUND=0
TEMP_FILE=$(mktemp)
while IFS= read -r file; do
# Skip if file doesn't exist (shouldn't happen with --diff-filter=d, but just in case)
if [ ! -f "$file" ]; then
continue
fi
# Check if file matches patterns to check
if ! echo "$file" | grep -qE "$PATTERNS"; then
continue
fi
# Check if file should be excluded
if echo "$file" | grep -qE "$EXCLUDE_PATTERNS"; then
continue
fi
# Find trailing whitespace lines, excluding XML doc placeholder lines that are exactly "/// " (one space)
MATCHES=$(grep -n '[[:space:]]$' "$file" | grep -vE '^[0-9]+:[[:space:]]*/// $' || true)
if [ -n "$MATCHES" ]; then
echo "❌ Trailing whitespace found in: $file"
echo "$MATCHES" | head -10
TOTAL=$(echo "$MATCHES" | wc -l)
if [ "$TOTAL" -gt 10 ]; then
echo " ... and $(($TOTAL - 10)) more lines"
fi
echo "1" >> "$TEMP_FILE"
fi
done <<< "$CHANGED_FILES"
ERRORS_FOUND=$(wc -l < "$TEMP_FILE" 2>/dev/null || echo "0")
rm -f "$TEMP_FILE"
if [ "$ERRORS_FOUND" -gt 0 ]; then
echo ""
echo "❌ Found trailing whitespace in $ERRORS_FOUND file(s)."
echo "Please remove trailing whitespace from the files listed above."
exit 1
else
echo "✅ No trailing whitespace found in changed files."
exit 0
fi

6
.gitignore vendored
View File

@@ -44,7 +44,7 @@ dlldata.c
project.lock.json
project.fragment.lock.json
artifacts/
!/artifacts/.gitkeep
!/artifacts/readme.md
*_i.c
*_p.c
@@ -263,7 +263,3 @@ __pycache__/
# Mac Only settings file
.DS_Store
# Nuke build tool
.nuke/temp
/publish.cmd

View File

@@ -1,137 +0,0 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"definitions": {
"Host": {
"type": "string",
"enum": [
"AppVeyor",
"AzurePipelines",
"Bamboo",
"Bitbucket",
"Bitrise",
"GitHubActions",
"GitLab",
"Jenkins",
"Rider",
"SpaceAutomation",
"TeamCity",
"Terminal",
"TravisCI",
"VisualStudio",
"VSCode"
]
},
"ExecutableTarget": {
"type": "string",
"enum": [
"Clean",
"Compile",
"Default",
"Package",
"PrePublish",
"Publish",
"PublishPackages",
"PublishPreRelease",
"PublishRelease",
"Restore",
"RunUnitTests"
]
},
"Verbosity": {
"type": "string",
"description": "",
"enum": [
"Verbose",
"Normal",
"Minimal",
"Quiet"
]
},
"NukeBuild": {
"properties": {
"Continue": {
"type": "boolean",
"description": "Indicates to continue a previously failed build attempt"
},
"Help": {
"type": "boolean",
"description": "Shows the help text for this build assembly"
},
"Host": {
"description": "Host for execution. Default is 'automatic'",
"$ref": "#/definitions/Host"
},
"NoLogo": {
"type": "boolean",
"description": "Disables displaying the NUKE logo"
},
"Partition": {
"type": "string",
"description": "Partition to use on CI"
},
"Plan": {
"type": "boolean",
"description": "Shows the execution plan (HTML)"
},
"Profile": {
"type": "array",
"description": "Defines the profiles to load",
"items": {
"type": "string"
}
},
"Root": {
"type": "string",
"description": "Root directory during build execution"
},
"Skip": {
"type": "array",
"description": "List of targets to be skipped. Empty list skips all dependencies",
"items": {
"$ref": "#/definitions/ExecutableTarget"
}
},
"Target": {
"type": "array",
"description": "List of targets to be invoked. Default is '{default_target}'",
"items": {
"$ref": "#/definitions/ExecutableTarget"
}
},
"Verbosity": {
"description": "Logging verbosity during build execution. Default is 'Normal'",
"$ref": "#/definitions/Verbosity"
}
}
}
},
"allOf": [
{
"properties": {
"CommonPropsFilePath": {
"type": "string",
"description": "common.props file path - to determine the configured version"
},
"Configuration": {
"type": "string",
"description": "Configuration to build - Default is 'Debug' (local) or 'Release' (server)",
"enum": [
"Debug",
"Release"
]
},
"ReleaseNotesFilePath": {
"type": "string",
"description": "ReleaseNotesFilePath - To determine the lates changelog version"
},
"Solution": {
"type": "string",
"description": "Path to a solution file that is automatically loaded"
}
}
},
{
"$ref": "#/definitions/NukeBuild"
}
]
}

View File

@@ -1,4 +0,0 @@
{
"$schema": "./build.schema.json",
"Solution": "src/ElectronNET.Lean.sln"
}

8
.travis.yml Normal file
View File

@@ -0,0 +1,8 @@
language: csharp
mono: none
dist: xenial
dotnet: 3.1
before_script:
- export PATH="$PATH:/home/travis/.dotnet/tools"
script:
- ./buildAll.sh

4
.vscode/launch.json vendored
View File

@@ -10,9 +10,9 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceRoot}/src/ElectronNET.CLI/bin/Debug/net8.0/dotnet-electronize.dll",
"program": "${workspaceRoot}/ElectronNET.CLI/bin/Debug/netcoreapp2.0/dotnet-electronize.dll",
"args": [],
"cwd": "${workspaceRoot}/src/ElectronNET.CLI",
"cwd": "${workspaceRoot}/ElectronNET.CLI",
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
"console": "internalConsole",
"stopAtEntry": false,

37
.vscode/tasks.json vendored
View File

@@ -1,18 +1,21 @@
{
"version": "2.0.0",
"command": "dotnet",
"args": [],
"tasks": [
{
"label": "build",
"type": "shell",
"command": "dotnet",
"args": ["build", "${workspaceRoot}/src/ElectronNET.CLI/ElectronNET.CLI.csproj"],
"problemMatcher": "$msCompile",
"group": {
"_id": "build",
"isDefault": false
}
}
]
}
"version": "2.0.0",
"command": "dotnet",
"args": [],
"tasks": [
{
"label": "build",
"type": "shell",
"command": "dotnet",
"args": [
"build",
"${workspaceRoot}/ElectronNET.CLI/ElectronNET.CLI.csproj"
],
"problemMatcher": "$msCompile",
"group": {
"_id": "build",
"isDefault": false
}
}
]
}

16
.vscode/tasks.json.old vendored Normal file
View File

@@ -0,0 +1,16 @@
{
"version": "0.1.0",
"command": "dotnet",
"isShellCommand": true,
"args": [],
"tasks": [
{
"taskName": "build",
"args": [
"${workspaceRoot}/ElectronNET.CLI/ElectronNET.CLI.csproj"
],
"isBuildCommand": true,
"problemMatcher": "$msCompile"
}
]
}

View File

@@ -1,132 +1,374 @@
# 0.4.0
# Not released
## ElectronNET.Core
# 18.6.1
- Fixed ElectronSingleInstance handling (#996) @softworkz
- Fixed `PackageId` handling (#993) @softworkz
- Added cross-platform npm restore and check mismatch on publish (#988) @softworkz
ElectronNET.CLI:
# 0.3.1
* New Feature: Support for additional dotnet publish flags (thanks [danatcofo](https://github.com/danatcofo)) [\#655](https://github.com/ElectronNET/Electron.NET/pull/655)
* New Feature: Support Apple Silicon Natively (thanks [bman46](https://github.com/bman46)) [\#624](https://github.com/ElectronNET/Electron.NET/pull/624)
## ElectronNET.Core
ElectronNET.API:
- Fixed issue transforming the project ID (#989, #990) @softworkz
* New Feature: Support for .NET 6 (thanks [danatcofo](https://github.com/danatcofo)) [\#636](https://github.com/ElectronNET/Electron.NET/pull/636)
* New Feature: Switch to async socket lib (thanks [theolivenbaum](https://github.com/theolivenbaum)) [\#595](https://github.com/ElectronNET/Electron.NET/pull/595)
* New Feature: Conversion to use ImageSharp rather than System.Drawing.Common (thanks [danatcofo](https://github.com/danatcofo)) [\#658](https://github.com/ElectronNET/Electron.NET/pull/658)
* New Feature: Support DI and Mocking better + Support launching app with file for win and linux (thanks [danatcofo](https://github.com/danatcofo)) [\#656](https://github.com/ElectronNET/Electron.NET/pull/656)
* New Feature: Support launching app with file for win and linux (thanks [schaveyt](https://github.com/schaveyt)) [\#648](https://github.com/ElectronNET/Electron.NET/pull/648)
* New Feature: Add ability to set a window's parent using BrowserWindowOptions (thanks [MutatedGamer](https://github.com/MutatedGamer)) [\#673](https://github.com/ElectronNET/Electron.NET/pull/673)
* New Feature: changed the processing of loadUrl at CreateWindowAsync (thanks [yannikHoeflich](https://github.com/yannikHoeflich)) [\#631](https://github.com/ElectronNET/Electron.NET/pull/631)
* New Feature: Recent Document Support for MacOS (thanks [danatcofo](https://github.com/danatcofo)) [\#634](https://github.com/ElectronNET/Electron.NET/pull/634)
* New Feature: Support DI and Mocking better (thanks [danatcofo](https://github.com/danatcofo)) [\#633](https://github.com/ElectronNET/Electron.NET/pull/633)
* New Feature: Allow ignoring certificate errors (thanks [javierlarota](https://github.com/javierlarota)) [\#626](https://github.com/ElectronNET/Electron.NET/pull/626)
* New Feature: Log errors in the dotnet process (thanks [Meberem](https://github.com/Meberem)) [\#592](https://github.com/ElectronNET/Electron.NET/pull/592)
* Fixed bug: Error on reloading a window after a second window is closed #664 (thanks [danatcofo](https://github.com/danatcofo)) [\#668](https://github.com/ElectronNET/Electron.NET/pull/668)
# 0.3.0
# Released
## ElectronNET.Core
# 13.5.1
- Updated infrastructure (#937, #939) @softworkz
- Updated all model classes to Electron API 39.2 (#949) @softworkz
- Fixed output path for `electron-builder` (#942) @softworkz
- Fixed floating point display resolution (#944) @softworkz
- Fixed error in case of missing electron-host-hook (#978)
- Fixed previous API break using exposed `JsonElement` objects (#938) @softworkz
- Fixed and improved several test cases (#962) @softworkz
- Fixed startup of Electron.NET from VS Code Debug Adapter (#952)
- Fixed the `BrowserWindowOptions` (#945) @softworkz
- Fixed example for `AutoMenuHide` to reflect platform capabilities (#982) @markatosi
- Added several migration checks for publishing (#966) @softworkz
- Added more test runners for E2E tests (#950, #951) @agracio
- Added dynamic updates for tray menu (#973) @davidroth
- Added matrix tests with 6 runners and 2 electron version (#948) @softworkz
- Added additional APIs for WebContents (#958) @agracio
- Added documentation for MacOS package publish (#983) @markatosi
- Added sample application for `ElectronHostHook` (#967) @adityashirsatrao007
ElectronNET.CLI:
# 0.2.0
* New Feature: Using exit code instead of seek for the term 'error' (thanks [TSrgy](https://github.com/TSrgy)) [\#562](https://github.com/ElectronNET/Electron.NET/pull/562)
* Fixed bug: Allow for property overrides to be passed in (thanks [danatcofo](https://github.com/danatcofo)) [\#531](https://github.com/ElectronNET/Electron.NET/pull/531)
Use `/p:propertyName=value` or `/property:propertyName=value` to pass in property overrides. This is equivalent to the `-p:` option documented here: [https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish](https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-publish)
* Fixed bug: Add ability to pass an argument for "Version" for both the "dotnet publish" and "electron-builder" commands (thanks [tub5](https://github.com/tub5)) [\#546](https://github.com/ElectronNET/Electron.NET/pull/546)
* Fixed bug: Version flag not persisting with the referenced executable (thanks [tub5](https://github.com/tub5)) [\#585](https://github.com/ElectronNET/Electron.NET/pull/585)
* Fixed bug: Changes PublishSingleFile default to false for NET5 compatibility (thanks [cristiangiagante](https://github.com/cristiangiagante)) [\#570](https://github.com/ElectronNET/Electron.NET/pull/570)
ElectronNET.API:
* New Feature: Native Electron 13.1.5 support, but not all new features (we search contributors)
* Breaking API Changes (from native Electron 13.1.5):
- `Shell.MoveItemToTrashAsync` renamed with `Shell.TrashItemAsync`
- The deprecated extension APIs have been removed: `BrowserWindow.GetAllExtensionsAsync()`, `BrowserWindow.RemoveExtension()`, `BrowserWindow.AddExtensionAsync()`. Use the session APIs instead: `Session.GetAllExtensionsAsync()`, `Session.RemoveExtension()`, `Session.LoadExtensionAsync()`.
* New Feature: singleInstance handle command line arguments [\#520](https://github.com/ElectronNET/Electron.NET/issues/520)
* New Feature: Add WebContents [insertCSS](https://www.electronjs.org/docs/api/web-contents#contentsinsertcsscss-options) functionality (thanks [nfichter](https://github.com/nfichter)) [\#559](https://github.com/ElectronNET/Electron.NET/pull/559)
* New Feature: Allow IpcMain to send IPC messages to BrowserViews (thanks [nfichter](https://github.com/nfichter)) [\#560](https://github.com/ElectronNET/Electron.NET/pull/560)
* New Feature: Add support for proxies that require basic username/password authentication (thanks [nfichter](https://github.com/nfichter)) [\#561](https://github.com/ElectronNET/Electron.NET/pull/561)
* New Feature: Add PostData to LoadURLOptions to allow http-posts in LoadURL calls (thanks [Funkrusha](https://github.com/Funkrusha)) [\#547](https://github.com/ElectronNET/Electron.NET/pull/547)
* Fixed bug: Fix splash screen interaction causing crashes, ghost dragging, and resizable behavior #540 (thanks [MiniguyBrendan](https://github.com/MiniguyBrendan)) [\#540](https://github.com/ElectronNET/Electron.NET/pull/540)
* Fixed bug: Vibrancy serialization fix (thanks [tantumalice](https://github.com/tantumalice)) [\#573](https://github.com/ElectronNET/Electron.NET/pull/573)
## ElectronNET.Core
# 11.5.1
- Updated dependencies (#930) @softworkz
- Updated integration tests (#931) @softworkz
- Updated `ElectronNET.Host` (#935) @softworkz
- Removed transition period specific build configuration (#928) @softworkz
- Added `IsRunningBlazor` option to `BrowserWindowOptions` (#926)
- Added platform support attributes (#929) @softworkz
ElectronNET.CLI:
# 0.1.0
* New Feature: Added new build and start commandline options for single exe (thanks [nathanwienand](https://github.com/nathanwienand)) [\#506](https://github.com/ElectronNET/Electron.NET/pull/506)
* New Feature: Set a description of the app in `electron.manifest.json` (thanks [BurtsevC](https://github.com/BurtsevC)) [\#433](https://github.com/ElectronNET/Electron.NET/pull/433)
* New Feature: Set a target for the start command (thanks [gabecook](https://github.com/gabecook)) [\#463](https://github.com/ElectronNET/Electron.NET/pull/463)
* New Feature: `electronize init` support for F# projects (thanks [kojo12228](https://github.com/kojo12228)) [\#457](https://github.com/ElectronNET/Electron.NET/pull/457)
* New Feature: Linux support for the buildAll.sh (thanks [duncanawoods](https://github.com/duncanawoods)) [\#465](https://github.com/ElectronNET/Electron.NET/pull/465)
* Fixed bug: ERR_UNKNOWN_URL_SCHEME by intercepting file:// protocol (thanks [duncanawoods](https://github.com/duncanawoods)) [\#467](https://github.com/ElectronNET/Electron.NET/pull/467)
## ElectronNET.Core
ElectronNET.API:
- Updated `PrintToPDFOptions` to also allow specifying the `PageSize` with an object (#769)
- Updated splashscreen image to have 0 margin (#622)
- Updated the IPC API w.r.t. naming and consistency (#905) @agracio
- Updated the IPC bridge w.r.t. synchronization and thread-safety (#918) @agracio
- Updated serialization to use `System.Text.Json` replacing `Newtonsoft.Json` (#917) @Denny09310
- Fixed parameter handling for the `sendToIpcRenderer` function (#922) @softworkz
- Fixed synchronization on removing event handlers (#921) @softworkz
- Fixed creation of windows with `contextIsolation` enabled (#906) @NimbusFox
- Fixed single instance behavior using the `ElectronSingleInstance` property (#901)
- Fixed potential race conditions (#908) @softworkz
- Added option to use `ElectronSplashScreen` with an HTML file (#799)
- Added option to provide floating point value as aspect ratios with `SetAspectRatio` (#793)
- Added option to provide `TitleBarOverlay` as an object (#911) @Denny09310
- Added `TitleBarOverlay` property to `BrowserWindowOptions` (#909)
- Added `RoundedCorners` property to `BrowserWindowOptions`
- Added integration tests and robustness checks (#913) @softworkz
- Added .NET 10 as an explicit target
* New Feature: Native Electron 11.1.1 support, but not all new features (we search contributors)
* Breaking API Changes (from native Electron 11.0): - Removed: BrowserView.{destroy, fromId, fromWebContents, getAllViews} and id property of BrowserView
* New Feature: Upgrade to .NET 5 (thanks [scottkuhl](https://github.com/scottkuhl)) [\#509](https://github.com/ElectronNET/Electron.NET/pull/509)
* New Feature: Extension Method for adding the Electron static class members to the standard MS DI Containers, this is a QOL issue only. `services.AddElectron()` (thanks [danatcofo](https://github.com/danatcofo )) [\#528](https://github.com/ElectronNET/Electron.NET/pull/528)
* New Feature: SetMenu completed for the Dock (MacOS) (thanks [danatcofo](https://github.com/danatcofo )) [\#528](https://github.com/ElectronNET/Electron.NET/pull/528)
# 0.0.18
Example for the Dock Menu
## ElectronNET.Core
`Electron.Dock.SetMenu(new [] {
new MenuItem {
Label = "Dock Menu Item",
Click = () => {
// do something
}
},
});`
### Highlights
Example for consuming the activate event (MacOs only)
- **Complete MSBuild Integration**: Eliminated CLI tool dependency, moved all build processes to MSBuild with deep Visual Studio integration
- **Modernized Architecture**: Restructured process lifecycle with .NET launching first and running Electron as child process for better control and reliability
- **Cross-Platform Development**: Build and debug Linux applications directly from Windows Visual Studio via WSL integration
- **Flexible Electron Versioning**: Removed version lock-in, users can now select any Electron version with build-time validation
- **Enhanced Debugging Experience**: ASP.NET-first debugging with Hot Reload support and improved process termination handling
- **Console App Support**: No longer requires ASP.NET - now works with simple console applications for file system or remote server HTML/JS
`Electron.App.On("activate", obj => {
var hasWindows = (bool)obj;
// do something
});`
### Build System & Project Structure
* New Feature: On and Once implementations for the App and Tray to cover the plethora of events that are not mapped explicitly in those two modules. (thanks [danatcofo](https://github.com/danatcofo )) [\#528](https://github.com/ElectronNET/Electron.NET/pull/528)
* New Feature: Adding the `EnableRemoteModule` property to the WebPreferences object. As of Electron 10, this property defaulted to false and without it exposed you can't use the remote module within a window. (thanks [danatcofo](https://github.com/danatcofo )) [\#528](https://github.com/ElectronNET/Electron.NET/pull/528)
* New Feature: Adding a configurable default electron port. (thanks [aarong-av](https://github.com/aarong-av)) [\#505](https://github.com/ElectronNET/Electron.NET/pull/505)
* New Feature: Added support for launching the application with a file on MacOS (thanks [dlitty](https://github.com/dlitty)) [\#478](https://github.com/ElectronNET/Electron.NET/pull/478)
* Improved: Avoid Blocking Calls in App and AutoUpdater (thanks [freosc](https://github.com/freosc)) [\#474](https://github.com/ElectronNET/Electron.NET/pull/474)
* Fixed bug: Maintain references between socket.io connection events (thanks [danatcofo](https://github.com/danatcofo )) [\#468](https://github.com/ElectronNET/Electron.NET/pull/486)
* Fixed bug: Set default WebPreferences.DefaultFontSize (thanks [duncanawoods](https://github.com/duncanawoods)) [\#468](https://github.com/ElectronNET/Electron.NET/pull/468)
- Eliminated electron.manifest.json configuration file, replaced with MSBuild project properties
- Introduced new package structure: ElectronNET.Core (main package), ElectronNET.Core.Api (API definitions), ElectronNET.Core.AspNet (ASP.NET integration)
- Added Runtime Identifier (RID) selection as part of project configuration
- Restructured build folder layout to use standard .NET format (bin\net8.0\win-x64) instead of bin\Desktop
- Implemented incremental build support for Electron assets to improve build performance
- Added custom MSBuild tasks for Electron-specific build operations
# 9.31.2
### Development Experience
* Electron-Builder fixed for Windows builds.
- Implemented unpackaged run-mode for development using regular .NET builds with unpackaged Electron configuration
- Added support for building Linux packages on Windows via WSL integration
- Enabled running and debugging Linux application outputs on Windows through WSL
- Integrated TypeScript compilation with ASP.NET tooling for consistent builds
- Added process orchestration supporting 8 different launch scenarios (packaged/unpackaged × console/ASP.NET × dotnet-first/electron-first)
# 9.31.1
### Debugging & Runtime
ElectronNET.CLI:
- Dramatically improved debugging experience with ASP.NET-first launch mode
- Added Hot Reload support for ASP.NET code during development
- Implemented proper process termination handling for all exit scenarios
- Minimized startup times through optimized build and launch procedures
* New Feature: Added config parameter (thanks [konstantingross](https://github.com/konstantingross)) [\#409](https://github.com/ElectronNET/Electron.NET/pull/409)
* New Feature: Set the configuration environment with the electron.manifest.json file.
* Fixed bug: Custom user path removed and replaced by the correct directory with VS macro (When ElectronNET.CLI is the Startup Project, press F5 (Debug) and the ElectronNET.WebApp starts correctly without error!) (thanks [konstantingross](https://github.com/konstantingross)) [\#409](https://github.com/ElectronNET/Electron.NET/pull/409)
### Technical Improvements
ElectronNET.API:
- Enhanced splash screen handling with automatic path resolution
- Improved ElectronHostHook integration as proper npm package dependency
- Updated to latest TypeScript version with ESLint configuration
- Added support for custom main.js files in projects
- Implemented version management through common.props file
- Added build-time Electron version compatibility validation
* New Feature: Native Electron 9.0.3 support, but not all new features (we search contributors)
* New Feature: PowerMonitor API Support (thanks [gustavo-lara-molina](https://github.com/gustavo-lara-molina)) [\#399](https://github.com/ElectronNET/Electron.NET/pull/399) [\#423](https://github.com/ElectronNET/Electron.NET/pull/423)
* New Feature: NativeTheme API Support (thanks [konstantingross](https://github.com/konstantingross)) [\#402](https://github.com/ElectronNET/Electron.NET/pull/402)
* New Feature: Cookie API Support (thanks [freosc](https://github.com/freosc)) [\#413](https://github.com/ElectronNET/Electron.NET/pull/413)
* Changed Feature: Removed dock methods from App API and moved to Dock API (thanks [konstantingross](https://github.com/konstantingross)) [\#422](https://github.com/ElectronNET/Electron.NET/pull/422)
* App-Api Enhancement: MenuItems with Submenus need an submenu type workaround [\#412](https://github.com/ElectronNET/Electron.NET/issues/412)
* App-Api Enhancement: Added UserAgentFallback (thanks [Mandrakia](https://github.com/Mandrakia)) [\#406](https://github.com/ElectronNET/Electron.NET/pull/406)
* App-Api Enhancement: Summaries rewritten, new App.IsReady / App.HasSingleInstanceLock property, App.Ready event, App.Focus with force parameter method, many parameters changes (thanks [konstantingross](https://github.com/konstantingross)) [\#415](https://github.com/ElectronNET/Electron.NET/pull/415) [\#422](https://github.com/ElectronNET/Electron.NET/pull/422)
* App-Api Enhancement: New App.IsReady property and App.Ready event (thanks [konstantingross](https://github.com/konstantingross)) [\#415](https://github.com/ElectronNET/Electron.NET/pull/415)
* Shell-Api Enhancement: API fixes for Electron 9.0.0 / Added missing parameters / Summaries rewritten (thanks [konstantingross](https://github.com/konstantingross)) [\#417](https://github.com/ElectronNET/Electron.NET/pull/417) [\#418](https://github.com/ElectronNET/Electron.NET/pull/418)
* Notification-Api Enhancement: Added missing properties in Notifications (thanks [konstantingross](https://github.com/konstantingross)) [\#410](https://github.com/ElectronNET/Electron.NET/pull/410)
* BrowserWindows-Api Enhancement: Add missing API call for SetProgressBar options (thanks [konstantingross](https://github.com/konstantingross)) [\#416](https://github.com/ElectronNET/Electron.NET/pull/416)
* BrowserWindow Enhancement: Add BrowserWindow.GetNativeWindowHandle() (thanks [kdlslyv](https://github.com/kdlslyv)) [\#429](https://github.com/ElectronNET/Electron.NET/pull/429)
* HostHook-Api Enhancement: HostHook.CallAsync should use TaskCompletionSource.SetException instead of throwing exception (thanks [Fre V](https://github.com/freosc)) [\#430](https://github.com/ElectronNET/Electron.NET/pull/430)
* MacOS Enhancement: Application exit logic (thanks [dafergu2](https://github.com/dafergu2)) [\#405](https://github.com/ElectronNET/Electron.NET/pull/405)
* Fixed bug: ElectronNET.API.Entities.WebPreferences.ContextIsolation [DefaultValue(true)] [\#411](https://github.com/ElectronNET/Electron.NET/issues/411)
### Package & Distribution
ElectronNET.WebApp (internal use):
* Improvement debugging and testing new API calls (without install ElectronNET.CLI) (thanks [konstantingross](https://github.com/konstantingross)) [\#425](https://github.com/ElectronNET/Electron.NET/pull/425)
* Fixed bug: Cannot find modules in ElectronHostHook (thanks [konstantingross](https://github.com/konstantingross)) [\#425](https://github.com/ElectronNET/Electron.NET/pull/425)
- Integrated MSBuild publishing mechanisms for creating Electron packages
- Added folder publishing support with improved parameter handling
- Implemented automated package.json generation from MSBuild properties
- Added GitHub release automation with proper versioning
- Reduced package sizes by eliminating unnecessary TypeScript dependencies
Thank you for donation [Phil Seeman](https://github.com/mpnow) ❤
### Migration & Compatibility
# 8.31.2
- Maintained backward compatibility for existing ElectronHostHook implementations
- Removed ASP.NET requirement: Now works with simple console applications for file system or remote server HTML/JS scenarios
- Added support for both console and ASP.NET Core application types
- Preserved all existing Electron API functionality while modernizing architecture
- Added migration path for existing projects through updated package structure
ElectronNET.CLI:
* New Feature: Deactivate PublishReadyToRun for build or start [\#395](https://github.com/ElectronNET/Electron.NET/issues/395)
`electronize build /target win /PublishReadyToRun false`
`electronize start /PublishReadyToRun false`
* Fixed bug: Application window doesn't open after packaging [\#387](https://github.com/ElectronNET/Electron.NET/issues/387)
This represents a comprehensive modernization of Electron.NET, addressing the major pain points around debugging, build complexity, and platform limitations while maintaining full API compatibility.
ElectronNET.API:
* New Feature: NativeImage Support (thanks [ThrDev](https://github.com/ThrDev)) [\#394](https://github.com/ElectronNET/Electron.NET/pull/394)
* New Feature: Update menu items for context menu and system tray on-the-fly. [\#270](https://github.com/ElectronNET/Electron.NET/pull/270)
# 8.31.1
ElectronNET.CLI:
* New Feature: Set a name and author of the app in `electron.manifest.json` [\#348](https://github.com/ElectronNET/Electron.NET/issues/348#issuecomment-615977950) [\#310](https://github.com/ElectronNET/Electron.NET/issues/310#issuecomment-617361086)
* New Feature: Live reload (thanks [syedadeel2](https://github.com/syedadeel2)) [\#390](https://github.com/ElectronNET/Electron.NET/pull/390)
`electronize start /watch`
* New Feature: Every new window will created with an clear cache [\#273](https://github.com/ElectronNET/Electron.NET/issues/273)
`electronize start /clear-cache`
ElectronNET.API:
* New Feature: Native Electron 8.2.3 support, but not all new features (we search contributors)
* New Feature: We incease the startup time for ~25-36% [\#356](https://github.com/ElectronNET/Electron.NET/issues/356)
* New Feature: Added print capability (thanks [x-xx-o](https://github.com/x-xx-o)) [\#355](https://github.com/ElectronNET/Electron.NET/pull/355)
* New Feature: BrowserView API [\#371](https://github.com/ElectronNET/Electron.NET/issues/371)
* Changed App.GetNameAsync and App.SetNameAsync to the App.Name Property [\#350](https://github.com/ElectronNET/Electron.NET/issues/350)
* Fixed bug: Splash Screen disappearing on click [\#357](https://github.com/ElectronNET/Electron.NET/issues/357)
* Fixed bug: Start MenuRole enum at 1 (thanks [jjuback](https://github.com/jjuback)) [\#369](https://github.com/ElectronNET/Electron.NET/pull/369)
* Fixed bug: BridgeConnector not connected (spam console) [\#347](https://github.com/ElectronNET/Electron.NET/issues/347)
* Fixed bug: BrowserWindowOptions is not setting Width and Height properly [\#373](https://github.com/ElectronNET/Electron.NET/issues/373)
* Fixed bug: IpcMain.Once(string) is not one time use, is not removing listener [\#366](https://github.com/ElectronNET/Electron.NET/issues/366)
* Fixed bug: IpcMain.RemoveAllListeners(string) is not removing the listeners [\#365](https://github.com/ElectronNET/Electron.NET/issues/365)
* Fixed bug: GetLoginItemSettingsAsync does not work [\#352](https://github.com/ElectronNET/Electron.NET/issues/352)
* Fixed bug: Using OnReadyToShow to display the main window in Blazor does not seem to work with Show set to false [\#361](https://github.com/ElectronNET/Electron.NET/issues/361)
* Fixed bug: Unable to disable WebSecurity along with NodeIntegration enabled [\#389](https://github.com/ElectronNET/Electron.NET/issues/389)
# 7.30.2
ElectronNET.CLI:
* New Feature: Different manifest file support [\#340](https://github.com/ElectronNET/Electron.NET/issues/340)
* Create a additional manifest file: `electronize init /manifest test`
* Start the app with your additional manifest file: `electronize start /manifest electron.manifest.test.json`
* Build the app with your additional manifest file: `electronize build /target win /manifest electron.manifest.test.json`.
* New Feature: Command Line support [\#337](https://github.com/ElectronNET/Electron.NET/issues/337)
* You can start the app with: `electronize start /args --dog=woof --test=true`
* Or as binary: `myapp.exe /args --dog=woof --test=true`
* Fixed bug: Start process with listen port 8000 error. [\#308](https://github.com/ElectronNET/Electron.NET/issues/308) (thanks [thecodejedi](https://github.com/thecodejedi))
* Fixed bug: `electronize build` with no arguments would throw a `KeyNotFoundException`. (thanks [jamiebrynes7](https://github.com/jamiebrynes7))
ElectronNET.API:
* New Feature: Electron 7.1.2 support, but not all new features (we search contributors) [\#341](https://github.com/ElectronNET/Electron.NET/issues/341)
* New Feature: Electron.App.CommandLine API [\#337](https://github.com/ElectronNET/Electron.NET/issues/337)
* New Feature: Support of BrowserWindow.AddExtension, BrowserWindow.RemoveExtension, BrowserWindow.GetExtensions (thanks [Daddoon](https://github.com/Daddoon))
Thank you for donation [robertmclaws](https://github.com/robertmclaws) ❤
# 5.30.1
ElectronNET.CLI:
* Move to .NET Core 3.0
* Use npm npx instead of global installations (thanks [jimbuck](https://github.com/jimbuck))
ElectronNET.API:
* Move to .NET Core 3.0
* New Feature: Add BrowserWindow.RemoveMenu() (thanks [hack2root](https://github.com/hack2root))
Thanks to [MaherJendoubi](https://github.com/MaherJendoubi), [kant2002](https://github.com/kant2002), [raz-canva](https://github.com/raz-canva) and [Daddoon](https://github.com/Daddoon) to give .NET Core 3.0 feedback!
# 5.22.14
ElectronNET.CLI:
* Fixed bug: Build fails with latest electron-builder version [\#288](https://github.com/ElectronNET/Electron.NET/issues/288)
ElectronNET.API:
* New Feature: Full support for Auto Updater [(Based on electron-updater - Version 4.0.6)](https://www.electron.build/auto-update)
* New Feature: Support for set a custom static Port to ASP.NET Backend [\#155](https://github.com/ElectronNET/Electron.NET/issues/155)
* Fixed bug: Electron tray icon TypeError ([Electron original issue](https://github.com/electron/electron/issues/7657)) (thanks [Tum4ik](https://github.com/Tum4ik))
* Fixed bug: Wrong tray icon path in the application built via `electronize build` command (thanks [Tum4ik](https://github.com/Tum4ik))
* Fixed bug: fix async issue where same port is considered open [\#261](https://github.com/ElectronNET/Electron.NET/issues/261) (thanks [netpoetica](https://github.com/netpoetica))
ElectronNET.WebApp:
* Fixed usage of the `Electron.Tray.Show` according fixed bugs in the ElectronNET.CLI (thanks [Tum4ik](https://github.com/Tum4ik))
# 5.22.13
ElectronNET.API:
* Fixed bug: Menu Item visibility [\#257](https://github.com/ElectronNET/Electron.NET/issues/257)
* Fixed bug: electron.manifest.json - singleInstance not working [\#258](https://github.com/ElectronNET/Electron.NET/issues/258)
* Fixed security issue: ASP.NET Core process is now bound to 127.0.0.1 instead of the broader localhost [\#258](https://github.com/ElectronNET/Electron.NET/pull/266)
# 5.22.12
ElectronNET.CLI:
* New Feature: Changed from **electron packager** to [**electron builder**](https://www.electron.build/)
* New Feature: 'add hosthook' command for add a ElectronHostHook-Directory
* Fixed bug: 'Unexpected firewall warnings' [\#181](https://github.com/ElectronNET/Electron.NET/issues/181)
* Fixed bug: 'found 8 vulnerabilities (1 low, 5 moderate, 2 high)' [\#199](https://github.com/ElectronNET/Electron.NET/pull/199)
* Merged pull request: Call electronize from the Path instead of via dotnet in launchSettings.json [\#243](https://github.com/ElectronNET/Electron.NET/pull/243) (thanks [grbd](https://github.com/grbd))
ElectronNET.API:
* New Feature: Electron 5.0.1 support, but not all new features
* New Feature: Auto Updater [(Based on electron-updater)](https://www.electron.build/auto-update)
* New Feature: Splashscreen-Support
* New Feature: HostHook-API for execute own TypeScript/JavaScript code on native Electron Main-Process
* New Feature: Session-API functions
* Fixed bug: Node process running after stopping app [\#96](https://github.com/ElectronNET/Electron.NET/issues/96)
* Fixed bug: 'X and Y options to not work on Windows 10' [\#193](https://github.com/ElectronNET/Electron.NET/issues/193)
* Fixed bug: Unable to clear cache [\#66](https://github.com/ElectronNET/Electron.NET/issues/66)
* Merged pull request: Fix BrowserWindow::SetMenu [\#231](https://github.com/ElectronNET/Electron.NET/pull/231) thanks (thanks [CodeKenpachi](https://github.com/CodeKenpachi))
* Merged pull request: FIX application hangs after socket reconnect [\#233](https://github.com/ElectronNET/Electron.NET/pull/233) (thanks [pedromrpinto](https://github.com/pedromrpinto))
* Merged pull request: Reduce chance of detecting false positives when scanning subprocesses for errors. [\#236](https://github.com/ElectronNET/Electron.NET/pull/236) (thanks [BorisTheBrave](https://github.com/BorisTheBrave))
* Merged pull request: Updates the C# API to accept floating point as in JS. [\#240](https://github.com/ElectronNET/Electron.NET/pull/240) (thanks [BorisTheBrave](https://github.com/BorisTheBrave))
* Merged pull request: buildReleaseNuGetPackages should leave you in the same directory you … [\#241](https://github.com/ElectronNET/Electron.NET/pull/241) (thanks [BorisTheBrave](https://github.com/BorisTheBrave))
ElectronNET.WebApp:
* Implemented a sample for the new HostHook-API
* Fixed bug: 'Electron.NET API Demo: unable to copy code?' [\#247](https://github.com/ElectronNET/Electron.NET/issues/247)
# 0.0.11
ElectronNET.CLI:
* Invoke 'npm install' without --prod flag to install needed devDependencies as well.
* Enable SourceLink
* NuGet Package License Information updated (deprecation of licenseUrl)
ElectronNET.API:
* Documentation added for WebContents.GetUrl()
* Enable SourceLink
* NuGet Package License Information updated (deprecation of licenseUrl)
# 0.0.10
ElectronNET.API:
* manifestJsonFilePath fixed (thanks @smack0007)
* Use Electron release 3.0.0 and updated packages (thanks @deinok)
* fixes for Socket interaction (thanks @mojinxun)
* Fixing SingleInstances (thanks @yaofeng)
* Enhance WebContent.GetUrl (thanks @ru-sh)
ElectronNET.CLI:
* Show Resultcode for better debugging when using Build/Start Command
* ElectronNET.CLI is now a global dotnet tool
# 0.0.9
ElectronNET.API:
* Better Async handling - thanks @danielmarbach
ElectronNET.CLI:
* More options on the 'build' command, e.g. for a 32bit debug build with electron prune: build /target custom win7-x86;win32 /dotnet-configuration Debug /electron-arch ia32 /electron-params "--prune=true "
* .NET Core project is now built with Release configuration but can be adjusted with the new params.
* Be aware: "Breaking" (but because of the alpha status of this project, we won't use SemVer)
# 0.0.8
This version was skipped because we unfortunately released a pre-version of this on NuGet.
# 0.0.7
ElectronNET.CLI:
* Fixed electronize start for macos/linux - thanks @yamachu
* Skip NPM install on start when node_modules directory already exists
# 0.0.6
ElectronNET.CLI:
* nuget packages are now release bits and have the correct assembly version
* Version command
* better devCleanup.cmd
* Better Platform Support Issue - thanks to @Petermarcu
* Start Command should now work on OSX/Linux - thanks to @r105m
ElectronNET.API:
* Thread-Safe methods - thanks to @yeskunall
# 0.0.5
ElectronNET.API:
* The last nuget package didn't contain the actual webpreferences settings with defaults - hopefully now.
# 0.0.4
ElectronNET.CLI:
* dotnet electronize start fixed
ElectronNET.API:
* WebPreferences settings with default values
# 0.0.3
ElectronNET.CLI:
* Init with Debug profile
* Build for all platforms (well... for newest OSX/Linux/Windows)
ElectronNET.API:
* Moar XML documentation
* Hybrid support (e.g. running as normal website and electron app)
* Event bugfixing
# 0.0.2
ElectronNET.CLI:
* Added Init to Help page
* Added XML documentation to NuGet output
* Maybe fixed for https://github.com/GregorBiswanger/Electron.NET/issues/2
ElectronNET.API:
* Add XML documentation to NuGet output
* Implemented Notification-, Dialog- & Tray-API
# 0.0.1
* init everything and basic functionality

832
src/ElectronNET.API/API/App.cs → ElectronNET.API/App.cs Normal file → Executable file

File diff suppressed because it is too large Load Diff

474
ElectronNET.API/AutoUpdater.cs Executable file
View File

@@ -0,0 +1,474 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ElectronNET.API.Interfaces;
using ElectronNET.API;
namespace ElectronNET.API
{
/// <summary>
/// Enable apps to automatically update themselves. Based on electron-updater.
/// </summary>
public sealed class AutoUpdater : IAutoUpdater
{
/// <summary>
/// Whether to automatically download an update when it is found. (Default is true)
/// </summary>
public Task<bool> IsAutoDownloadEnabledAsync => BridgeConnector.OnResult<bool>("autoUpdater-autoDownload-get", "autoUpdater-autoDownload-get-reply");
/// <summary>
/// Whether to automatically install a downloaded update on app quit (if `QuitAndInstall` was not called before).
///
/// Applicable only on Windows and Linux.
/// </summary>
public Task<bool> IsAutoInstallOnAppQuitEnabledAsync => BridgeConnector.OnResult<bool>("autoUpdater-autoInstallOnAppQuit-get", "autoUpdater-autoInstallOnAppQuit-get-reply");
/// <summary>
/// *GitHub provider only.* Whether to allow update to pre-release versions.
/// Defaults to "true" if application version contains prerelease components (e.g. "0.12.1-alpha.1", here "alpha" is a prerelease component), otherwise "false".
///
/// If "true", downgrade will be allowed("allowDowngrade" will be set to "true").
/// </summary>
public Task<bool> IsAllowPrereleaseEnabledAsync => BridgeConnector.OnResult<bool>("autoUpdater-allowPrerelease-get", "autoUpdater-allowPrerelease-get-reply");
/// <summary>
/// *GitHub provider only.*
/// Get all release notes (from current version to latest), not just the latest (Default is false).
/// </summary>
public Task<bool> IsFullChangeLogEnabledAsync => BridgeConnector.OnResult<bool>("autoUpdater-fullChangelog-get", "autoUpdater-fullChangelog-get-reply");
public Task<bool> IsAllowDowngradeEnabledAsync => BridgeConnector.OnResult<bool>("autoUpdater-allowDowngrade-get", "autoUpdater-allowDowngrade-get-reply");
/// <summary>
/// Whether to automatically download an update when it is found. (Default is true)
/// </summary>
public bool AutoDownload
{
set
{
BridgeConnector.Emit("autoUpdater-autoDownload-set", value);
}
}
/// <summary>
/// Whether to automatically install a downloaded update on app quit (if `QuitAndInstall` was not called before).
///
/// Applicable only on Windows and Linux.
/// </summary>
public bool AutoInstallOnAppQuit
{
set
{
BridgeConnector.Emit("autoUpdater-autoInstallOnAppQuit-set", value);
}
}
/// <summary>
/// *GitHub provider only.* Whether to allow update to pre-release versions.
/// Defaults to "true" if application version contains prerelease components (e.g. "0.12.1-alpha.1", here "alpha" is a prerelease component), otherwise "false".
///
/// If "true", downgrade will be allowed("allowDowngrade" will be set to "true").
/// </summary>
public bool AllowPrerelease
{
set
{
BridgeConnector.Emit("autoUpdater-allowPrerelease-set", value);
}
}
/// <summary>
/// *GitHub provider only.*
/// Get all release notes (from current version to latest), not just the latest (Default is false).
/// </summary>
public bool FullChangelog
{
set
{
BridgeConnector.Emit("autoUpdater-fullChangelog-set", value);
}
}
/// <summary>
/// Whether to allow version downgrade (when a user from the beta channel wants to go back to the stable channel).
/// Taken in account only if channel differs (pre-release version component in terms of semantic versioning).
/// Default is false.
/// </summary>
public bool AllowDowngrade
{
set
{
BridgeConnector.Emit("autoUpdater-allowDowngrade-set", value);
}
}
/// <summary>
/// For test only.
/// </summary>
public Task<string> GetUpdateConfigPathAsync => BridgeConnector.OnResult<string>("autoUpdater-updateConfigPath-get", "autoUpdater-updateConfigPath-get-reply");
/// <summary>
/// The current application version
/// </summary>
public Task<SemVer> GetCurrentVersionAsync => BridgeConnector.OnResult<SemVer>("autoUpdater-updateConcurrentVersionfigPath-get", "autoUpdater-currentVersion-get-reply");
/// <summary>
/// Get the update channel. Not applicable for GitHub.
/// Doesnt return channel from the update configuration, only if was previously set.
/// </summary>
public Task<string> GetChannelAsync => BridgeConnector.OnResult<string>("autoUpdater-channel-get", "autoUpdater-channel-get-reply");
/// <summary>
/// The request headers.
/// </summary>
public Task<Dictionary<string, string>> GetRequestHeadersAsync => BridgeConnector.OnResult<Dictionary<string, string>>("autoUpdater-requestHeaders-get", "autoUpdater-requestHeaders-get-reply");
/// <summary>
/// The request headers.
/// </summary>
public Dictionary<string, string> RequestHeaders
{
set
{
BridgeConnector.Emit("autoUpdater-requestHeaders-set", value);
}
}
/// <summary>
/// Emitted when there is an error while updating.
/// </summary>
public event Action<string> OnError
{
add
{
if (_error == null)
{
BridgeConnector.On<string>("autoUpdater-error" + GetHashCode(), (message) =>
{
_error(message.ToString());
});
BridgeConnector.Emit("register-autoUpdater-error-event", GetHashCode());
}
_error += value;
}
remove
{
_error -= value;
if (_error == null)
BridgeConnector.Off("autoUpdater-error" + GetHashCode());
}
}
private event Action<string> _error;
/// <summary>
/// Emitted when checking if an update has started.
/// </summary>
public event Action OnCheckingForUpdate
{
add
{
if (_checkingForUpdate == null)
{
BridgeConnector.On("autoUpdater-checking-for-update" + GetHashCode(), () =>
{
_checkingForUpdate();
});
BridgeConnector.Emit("register-autoUpdater-checking-for-update-event", GetHashCode());
}
_checkingForUpdate += value;
}
remove
{
_checkingForUpdate -= value;
if (_checkingForUpdate == null)
BridgeConnector.Off("autoUpdater-checking-for-update" + GetHashCode());
}
}
private event Action _checkingForUpdate;
/// <summary>
/// Emitted when there is an available update.
/// The update is downloaded automatically if AutoDownload is true.
/// </summary>
public event Action<UpdateInfo> OnUpdateAvailable
{
add
{
if (_updateAvailable == null)
{
BridgeConnector.On<UpdateInfo>("autoUpdater-update-available" + GetHashCode(), (updateInfo) =>
{
_updateAvailable(updateInfo);
});
BridgeConnector.Emit("register-autoUpdater-update-available-event", GetHashCode());
}
_updateAvailable += value;
}
remove
{
_updateAvailable -= value;
if (_updateAvailable == null)
BridgeConnector.Off("autoUpdater-update-available" + GetHashCode());
}
}
private event Action<UpdateInfo> _updateAvailable;
/// <summary>
/// Emitted when there is no available update.
/// </summary>
public event Action<UpdateInfo> OnUpdateNotAvailable
{
add
{
if (_updateNotAvailable == null)
{
BridgeConnector.On<UpdateInfo>("autoUpdater-update-not-available" + GetHashCode(), (updateInfo) =>
{
_updateNotAvailable(updateInfo);
});
BridgeConnector.Emit("register-autoUpdater-update-not-available-event", GetHashCode());
}
_updateNotAvailable += value;
}
remove
{
_updateNotAvailable -= value;
if (_updateNotAvailable == null)
BridgeConnector.Off("autoUpdater-update-not-available" + GetHashCode());
}
}
private event Action<UpdateInfo> _updateNotAvailable;
/// <summary>
/// Emitted on download progress.
/// </summary>
public event Action<ProgressInfo> OnDownloadProgress
{
add
{
if (_downloadProgress == null)
{
BridgeConnector.On<ProgressInfo>("autoUpdater-download-progress" + GetHashCode(), (progressInfo) =>
{
_downloadProgress(progressInfo);
});
BridgeConnector.Emit("register-autoUpdater-download-progress-event", GetHashCode());
}
_downloadProgress += value;
}
remove
{
_downloadProgress -= value;
if (_downloadProgress == null)
BridgeConnector.Off("autoUpdater-download-progress" + GetHashCode());
}
}
private event Action<ProgressInfo> _downloadProgress;
/// <summary>
/// Emitted on download complete.
/// </summary>
public event Action<UpdateInfo> OnUpdateDownloaded
{
add
{
if (_updateDownloaded == null)
{
BridgeConnector.On<UpdateInfo>("autoUpdater-update-downloaded" + GetHashCode(), (updateInfo) =>
{
_updateDownloaded(updateInfo);
});
BridgeConnector.Emit("register-autoUpdater-update-downloaded-event", GetHashCode());
}
_updateDownloaded += value;
}
remove
{
_updateDownloaded -= value;
if (_updateDownloaded == null)
BridgeConnector.Off("autoUpdater-update-downloaded" + GetHashCode());
}
}
private event Action<UpdateInfo> _updateDownloaded;
private static AutoUpdater _autoUpdater;
private static readonly object _syncRoot = new();
internal AutoUpdater() { }
internal static AutoUpdater Instance
{
get
{
if (_autoUpdater == null)
{
lock (_syncRoot)
{
if (_autoUpdater == null)
{
_autoUpdater = new AutoUpdater();
}
}
}
return _autoUpdater;
}
}
/// <summary>
/// Asks the server whether there is an update.
/// </summary>
/// <returns></returns>
public Task<UpdateCheckResult> CheckForUpdatesAsync()
{
var taskCompletionSource = new TaskCompletionSource<UpdateCheckResult>(TaskCreationOptions.RunContinuationsAsynchronously);
string guid = Guid.NewGuid().ToString();
BridgeConnector.On<UpdateCheckResult>("autoUpdaterCheckForUpdatesComplete" + guid, (updateCheckResult) =>
{
try
{
BridgeConnector.Off("autoUpdaterCheckForUpdatesComplete" + guid);
BridgeConnector.Off("autoUpdaterCheckForUpdatesError" + guid);
taskCompletionSource.SetResult(updateCheckResult);
}
catch (Exception ex)
{
taskCompletionSource.SetException(ex);
}
});
BridgeConnector.On<string>("autoUpdaterCheckForUpdatesError" + guid, (error) =>
{
BridgeConnector.Off("autoUpdaterCheckForUpdatesComplete" + guid);
BridgeConnector.Off("autoUpdaterCheckForUpdatesError" + guid);
string message = "An error occurred in CheckForUpdatesAsync";
if (error != null && !string.IsNullOrEmpty(error.ToString()))
message = JsonConvert.SerializeObject(error);
taskCompletionSource.SetException(new Exception(message));
});
BridgeConnector.Emit("autoUpdaterCheckForUpdates", guid);
return taskCompletionSource.Task;
}
/// <summary>
/// Asks the server whether there is an update.
///
/// This will immediately download an update, then install when the app quits.
/// </summary>
/// <returns></returns>
public Task<UpdateCheckResult> CheckForUpdatesAndNotifyAsync()
{
var taskCompletionSource = new TaskCompletionSource<UpdateCheckResult>(TaskCreationOptions.RunContinuationsAsynchronously);
string guid = Guid.NewGuid().ToString();
BridgeConnector.On<UpdateCheckResult>("autoUpdaterCheckForUpdatesAndNotifyComplete" + guid, (updateCheckResult) =>
{
try
{
BridgeConnector.Off("autoUpdaterCheckForUpdatesAndNotifyComplete" + guid);
BridgeConnector.Off("autoUpdaterCheckForUpdatesAndNotifyError" + guid);
if (updateCheckResult == null)
taskCompletionSource.SetResult(null);
else
taskCompletionSource.SetResult(updateCheckResult);
}
catch (Exception ex)
{
taskCompletionSource.SetException(ex);
}
});
BridgeConnector.On<string>("autoUpdaterCheckForUpdatesAndNotifyError" + guid, (error) =>
{
BridgeConnector.Off("autoUpdaterCheckForUpdatesAndNotifyComplete" + guid);
BridgeConnector.Off("autoUpdaterCheckForUpdatesAndNotifyError" + guid);
string message = "An error occurred in autoUpdaterCheckForUpdatesAndNotify";
if (error != null)
message = JsonConvert.SerializeObject(error);
taskCompletionSource.SetException(new Exception(message));
});
BridgeConnector.Emit("autoUpdaterCheckForUpdatesAndNotify", guid);
return taskCompletionSource.Task;
}
/// <summary>
/// Restarts the app and installs the update after it has been downloaded.
/// It should only be called after `update-downloaded` has been emitted.
///
/// Note: QuitAndInstall() will close all application windows first and only emit `before-quit` event on `app` after that.
/// This is different from the normal quit event sequence.
/// </summary>
/// <param name="isSilent">*windows-only* Runs the installer in silent mode. Defaults to `false`.</param>
/// <param name="isForceRunAfter">Run the app after finish even on silent install. Not applicable for macOS. Ignored if `isSilent` is set to `false`.</param>
public void QuitAndInstall(bool isSilent = false, bool isForceRunAfter = false)
{
BridgeConnector.EmitSync("prepare-for-update");
BridgeConnector.EmitSync("autoUpdaterQuitAndInstall", isSilent, isForceRunAfter);
}
/// <summary>
/// Start downloading update manually. You can use this method if "AutoDownload" option is set to "false".
/// </summary>
/// <returns>Path to downloaded file.</returns>
public Task<string> DownloadUpdateAsync()
{
var taskCompletionSource = new TaskCompletionSource<string>(TaskCreationOptions.RunContinuationsAsynchronously);
string guid = Guid.NewGuid().ToString();
BridgeConnector.On<string>("autoUpdaterDownloadUpdateComplete" + guid, (downloadedPath) =>
{
BridgeConnector.Off("autoUpdaterDownloadUpdateComplete" + guid);
taskCompletionSource.SetResult(downloadedPath.ToString());
});
BridgeConnector.Emit("autoUpdaterDownloadUpdate", guid);
return taskCompletionSource.Task;
}
/// <summary>
/// Feed URL.
/// </summary>
/// <returns>Feed URL.</returns>
public Task<string> GetFeedURLAsync()
{
var taskCompletionSource = new TaskCompletionSource<string>(TaskCreationOptions.RunContinuationsAsynchronously);
string guid = Guid.NewGuid().ToString();
BridgeConnector.On<string>("autoUpdaterGetFeedURLComplete" + guid, (downloadedPath) =>
{
BridgeConnector.Off("autoUpdaterGetFeedURLComplete" + guid);
taskCompletionSource.SetResult(downloadedPath.ToString());
});
BridgeConnector.Emit("autoUpdaterGetFeedURL", guid);
return taskCompletionSource.Task;
}
}
}

View File

@@ -0,0 +1,551 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Nito.AsyncEx;
using SocketIOClient;
using SocketIOClient.Newtonsoft.Json;
namespace ElectronNET.API
{
internal static class BridgeConnector
{
internal static class EventTasks<T>
{
//Although SocketIO already manage event handlers, we need to manage this here as well for the OnResult calls,
//because SocketIO will simply replace the existing event handler on every call to On(key, ...) , which means there is
//a race condition between On / Off calls that can lead to tasks deadlocking forever without ever triggering their On handler
private static readonly Dictionary<string, TaskCompletionSource<T>> _taskCompletionSources = new();
private static readonly Dictionary<string, string> _eventKeys = new();
private static readonly object _lock = new();
/// <summary>
/// Get or add a new TaskCompletionSource<typeparamref name="T"/> for a given event key
/// </summary>
/// <param name="key"></param>
/// <param name="eventKey"></param>
/// <param name="taskCompletionSource"></param>
/// <param name="waitThisFirstAndThenTryAgain"></param>
/// <returns>Returns true if a new TaskCompletionSource<typeparamref name="T"/> was added to the dictionary</returns>
internal static bool TryGetOrAdd(string key, string eventKey, out TaskCompletionSource<T> taskCompletionSource, out Task waitThisFirstAndThenTryAgain)
{
lock (_lock)
{
if (!_taskCompletionSources.TryGetValue(key, out taskCompletionSource))
{
taskCompletionSource = new(TaskCreationOptions.RunContinuationsAsynchronously);
_taskCompletionSources[key] = taskCompletionSource;
_eventKeys[key] = eventKey;
waitThisFirstAndThenTryAgain = null;
return true; //Was added, so we need to also register the socket events
}
if (_eventKeys.TryGetValue(key, out var existingEventKey) && existingEventKey == eventKey)
{
waitThisFirstAndThenTryAgain = null;
return false; //No need to register the socket events twice
}
waitThisFirstAndThenTryAgain = taskCompletionSource.Task; //Will need to try again after the previous existing one is done
taskCompletionSource = null;
return true; //Need to register the socket events, but must first await the previous task to complete
}
}
/// <summary>
/// Clean up the TaskCompletionSource<typeparamref name="T"/> from the dictionary if and only if it is the same as the passed argument
/// </summary>
/// <param name="key"></param>
/// <param name="eventKey"></param>
/// <param name="taskCompletionSource"></param>
internal static void DoneWith(string key, string eventKey, TaskCompletionSource<T> taskCompletionSource)
{
lock (_lock)
{
if (_taskCompletionSources.TryGetValue(key, out var existingTaskCompletionSource)
&& ReferenceEquals(existingTaskCompletionSource, taskCompletionSource))
{
_taskCompletionSources.Remove(key);
}
if (_eventKeys.TryGetValue(key, out var existingEventKey) && existingEventKey == eventKey)
{
_eventKeys.Remove(key);
}
}
}
}
private static SocketIO _socket;
private static readonly object _syncRoot = new();
private static readonly SemaphoreSlim _socketSemaphoreEmit = new(1, 1);
private static readonly SemaphoreSlim _socketSemaphoreHandlers = new(1, 1);
private static AsyncManualResetEvent _connectedSocketEvent = new AsyncManualResetEvent();
private static Dictionary<string, Action<SocketIOResponse>> _eventHandlers = new();
private static Task<SocketIO> _waitForConnection
{
get
{
EnsureSocketTaskIsCreated();
return GetSocket();
}
}
private static async Task<SocketIO> GetSocket()
{
await _connectedSocketEvent.WaitAsync();
return _socket;
}
public static bool IsConnected => _waitForConnection is Task task && task.IsCompletedSuccessfully;
public static void Emit(string eventString, params object[] args)
{
//We don't care about waiting for the event to be emitted, so this doesn't need to be async
Task.Run(() => EmitAsync(eventString, args));
}
private static async Task EmitAsync(string eventString, object[] args)
{
if (App.SocketDebug)
{
Log("Sending event {0}", eventString);
}
var socket = await _waitForConnection;
await _socketSemaphoreEmit.WaitAsync();
try
{
await socket.EmitAsync(eventString, args);
}
finally
{
_socketSemaphoreEmit.Release();
}
if (App.SocketDebug)
{
Log($"Sent event {eventString}");
}
}
/// <summary>
/// This method is only used on places where we need to be sure the event was sent on the socket, such as Quit, Exit, Relaunch and QuitAndInstall methods
/// </summary>
/// <param name="eventString"></param>
/// <param name="args"></param>
internal static void EmitSync(string eventString, params object[] args)
{
if (App.SocketDebug)
{
Log("Sending event {0}", eventString);
}
Task.Run(async () =>
{
var socket = await _waitForConnection;
try
{
await _socketSemaphoreEmit.WaitAsync();
await socket.EmitAsync(eventString, args);
}
finally
{
_socketSemaphoreEmit.Release();
}
}).Wait();
if (App.SocketDebug)
{
Log("Sent event {0}", eventString);
}
}
public static void Off(string eventString)
{
EnsureSocketTaskIsCreated();
_socketSemaphoreHandlers.Wait();
try
{
if (_eventHandlers.ContainsKey(eventString))
{
_eventHandlers.Remove(eventString);
}
_socket.Off(eventString);
}
finally
{
_socketSemaphoreHandlers.Release();
}
}
public static void On(string eventString, Action fn)
{
EnsureSocketTaskIsCreated();
_socketSemaphoreHandlers.Wait();
try
{
if (_eventHandlers.ContainsKey(eventString))
{
_eventHandlers.Remove(eventString);
}
_eventHandlers.Add(eventString, _ =>
{
try
{
fn();
}
catch (Exception E)
{
LogError(E, "Error running handler for event {0}", eventString);
}
});
_socket.On(eventString, _eventHandlers[eventString]);
}
finally
{
_socketSemaphoreHandlers.Release();
}
}
public static void On<T>(string eventString, Action<T> fn)
{
EnsureSocketTaskIsCreated();
_socketSemaphoreHandlers.Wait();
try
{
if (_eventHandlers.ContainsKey(eventString))
{
_eventHandlers.Remove(eventString);
}
_eventHandlers.Add(eventString, o =>
{
try
{
fn(o.GetValue<T>(0));
}
catch (Exception E)
{
LogError(E, "Error running handler for event {0}", eventString);
}
});
_socket.On(eventString, _eventHandlers[eventString]);
}
finally
{
_socketSemaphoreHandlers.Release();
}
}
private static void RehookHandlers(SocketIO newSocket)
{
_socketSemaphoreHandlers.Wait();
try
{
foreach (var kv in _eventHandlers)
{
newSocket.On(kv.Key, kv.Value);
}
}
finally
{
_socketSemaphoreHandlers.Release();
}
}
public static void Once<T>(string eventString, Action<T> fn)
{
On<T>(eventString, (o) =>
{
Off(eventString);
fn(o);
});
}
public static async Task<T> OnResult<T>(string triggerEvent, string completedEvent, params object[] args)
{
string eventKey = completedEvent;
if (args is object && args.Length > 0) // If there are arguments passed, we generate a unique event key with the arguments
// this allow us to wait for previous events first before registering new ones
{
var hash = new HashCode();
foreach (var obj in args)
{
hash.Add(obj);
}
eventKey = $"{eventKey}-{(uint)hash.ToHashCode()}";
}
if (EventTasks<T>.TryGetOrAdd(completedEvent, eventKey, out var taskCompletionSource, out var waitThisFirstAndThenTryAgain))
{
if (waitThisFirstAndThenTryAgain is object)
{
//There was a pending call with different parameters, so we need to wait that first and then call here again
try
{
await waitThisFirstAndThenTryAgain;
}
catch
{
//Ignore any exceptions here so we can set a new event below
//The exception will also be visible to the original first caller due to taskCompletionSource.Task
}
//Try again to set the event
return await OnResult<T>(triggerEvent, completedEvent, args);
}
else
{
//A new TaskCompletionSource was added, so we need to register the completed event here
On<T>(completedEvent, (result) =>
{
Off(completedEvent);
taskCompletionSource.SetResult(result);
EventTasks<T>.DoneWith(completedEvent, eventKey, taskCompletionSource);
});
await EmitAsync(triggerEvent, args);
}
}
return await taskCompletionSource.Task;
}
public static async Task<T> OnResult<T>(string triggerEvent, string completedEvent, CancellationToken cancellationToken, params object[] args)
{
string eventKey = completedEvent;
if (args is object && args.Length > 0) // If there are arguments passed, we generate a unique event key with the arguments
// this allow us to wait for previous events first before registering new ones
{
var hash = new HashCode();
foreach (var obj in args)
{
hash.Add(obj);
}
eventKey = $"{eventKey}-{(uint)hash.ToHashCode()}";
}
if (EventTasks<T>.TryGetOrAdd(completedEvent, eventKey, out var taskCompletionSource, out var waitThisFirstAndThenTryAgain))
{
if (waitThisFirstAndThenTryAgain is object)
{
//There was a pending call with different parameters, so we need to wait that first and then call here again
try
{
await Task.Run(() => waitThisFirstAndThenTryAgain, cancellationToken);
}
catch
{
//Ignore any exceptions here so we can set a new event below
//The exception will also be visible to the original first caller due to taskCompletionSource.Task
}
//Try again to set the event
return await OnResult<T>(triggerEvent, completedEvent, cancellationToken, args);
}
else
{
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
{
//A new TaskCompletionSource was added, so we need to register the completed event here
On<T>(completedEvent, (result) =>
{
Off(completedEvent);
taskCompletionSource.SetResult(result);
EventTasks<T>.DoneWith(completedEvent, eventKey, taskCompletionSource);
});
Emit(triggerEvent, args);
}
}
}
return await taskCompletionSource.Task;
}
internal static void Log(string formatString, params object[] args)
{
if (Logger is object)
{
Logger.LogInformation(formatString, args);
}
else
{
Console.WriteLine(formatString, args);
}
}
internal static void LogError(Exception E, string formatString, params object[] args)
{
if (Logger is object)
{
Logger.LogError(E, formatString, args);
}
else
{
Console.WriteLine(formatString, args);
Console.WriteLine(E.ToString());
}
}
private static Thread _backgroundMonitorThread;
private static void EnsureSocketTaskIsCreated()
{
if (_socket is null)
{
if (string.IsNullOrWhiteSpace(AuthKey))
{
throw new Exception("You must call Electron.ReadAuth() first thing on your main entry point.");
}
if (HybridSupport.IsElectronActive)
{
lock (_syncRoot)
{
if (_socket is null)
{
if (HybridSupport.IsElectronActive)
{
var socket = new SocketIO($"http://localhost:{BridgeSettings.SocketPort}", new SocketIOOptions()
{
EIO = 4,
Reconnection = true,
ReconnectionAttempts = int.MaxValue,
ReconnectionDelay = 500,
ReconnectionDelayMax = 2000,
RandomizationFactor = 0.5,
ConnectionTimeout = TimeSpan.FromSeconds(10),
Transport = SocketIOClient.Transport.TransportProtocol.WebSocket
});
socket.JsonSerializer = new CamelCaseNewtonsoftJsonSerializer();
_connectedSocketEvent.Reset();
socket.OnConnected += (_, __) =>
{
Task.Run(async () =>
{
await socket.EmitAsync("auth", AuthKey);
_connectedSocketEvent.Set();
Log("ElectronNET socket {1} connected on port {0}!", BridgeSettings.SocketPort, socket.Id);
});
};
socket.OnReconnectAttempt += (_, __) =>
{
_connectedSocketEvent.Reset();
Log("ElectronNET socket {1} is trying to reconnect on port {0}...", BridgeSettings.SocketPort, socket.Id);
};
socket.OnReconnectError += (_, ex) =>
{
_connectedSocketEvent.Reset();
Log("ElectronNET socket {1} failed to connect {0}", ex, socket.Id);
};
socket.OnReconnectFailed += (_, ex) =>
{
_connectedSocketEvent.Reset();
Log("ElectronNET socket {1} failed to reconnect {0}", ex, socket.Id);
};
socket.OnReconnected += (_, __) =>
{
_connectedSocketEvent.Set();
Log("ElectronNET socket {1} reconnected on port {0}...", BridgeSettings.SocketPort, socket.Id);
};
socket.OnDisconnected += (_, reason) =>
{
_connectedSocketEvent.Reset();
Log("ElectronNET socket {2} disconnected with reason {0}, trying to reconnect on port {1}!", reason, BridgeSettings.SocketPort, socket.Id);
};
socket.OnError += (_, msg) =>
{
//_connectedSocketEvent.Reset();
Log("ElectronNET socket {1} error: {0}...", msg, socket.Id);
};
_socket = socket;
Task.Run(async () =>
{
try
{
await socket.ConnectAsync();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
if (!App.TryRaiseOnSocketConnectFail())
{
Environment.Exit(0xDEAD);
}
}
});
RehookHandlers(socket);
}
else
{
throw new Exception("Missing Socket Port");
}
}
}
}
else
{
throw new Exception("Missing Socket Port");
}
}
}
internal static ILogger<App> Logger { private get; set; }
internal static string AuthKey { get; set; } = null;
private class CamelCaseNewtonsoftJsonSerializer : NewtonsoftJsonSerializer
{
public CamelCaseNewtonsoftJsonSerializer() : base()
{
OptionsProvider = () => new JsonSerializerSettings()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
};
}
}
}
}

View File

@@ -0,0 +1,35 @@
namespace ElectronNET.API
{
/// <summary>
///
/// </summary>
public static class BridgeSettings
{
/// <summary>
/// Gets the socket port.
/// </summary>
/// <value>
/// The socket port.
/// </value>
public static string SocketPort { get; internal set; }
/// <summary>
/// Gets the web port.
/// </summary>
/// <value>
/// The web port.
/// </value>
public static string WebPort { get; internal set; }
/// <summary>
/// Manually set the port values instead of using the UseElectron extension method
/// </summary>
/// <param name="socketPort"></param>
/// <param name="webPort"></param>
public static void InitializePorts(int socketPort, int webPort)
{
SocketPort = socketPort.ToString();
WebPort = webPort.ToString();
}
}
}

View File

@@ -1,22 +1,25 @@
using ElectronNET.API.Entities;
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System.Threading.Tasks;
namespace ElectronNET.API
{
/// <summary>
/// A BrowserView can be used to embed additional web content into a BrowserWindow.
/// It is like a child window, except that it is positioned relative to its owning window.
/// A BrowserView can be used to embed additional web content into a BrowserWindow.
/// It is like a child window, except that it is positioned relative to its owning window.
/// It is meant to be an alternative to the webview tag.
/// </summary>
public class BrowserView : ApiBase
public class BrowserView
{
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.DashesLowerFirst;
protected override SocketTaskMessageNameTypes SocketTaskMessageNameType => SocketTaskMessageNameTypes.DashesLowerFirst;
/// <summary>
/// Gets the identifier.
/// </summary>
public override int Id { get; protected set; }
/// <value>
/// The identifier.
/// </value>
public int Id { get; internal set; }
/// <summary>
/// Render and control web pages.
@@ -25,24 +28,24 @@ namespace ElectronNET.API
/// <summary>
/// Resizes and moves the view to the supplied bounds relative to the window.
///
/// (experimental)
/// </summary>
public Rectangle Bounds
public Task<Rectangle> GetBoundsAsync() => BridgeConnector.OnResult<Rectangle>("browserView-getBounds", "browserView-getBounds-reply" + Id, Id);
/// <summary>
/// Set the bounds of the current view inside the window
/// </summary>
/// <param name="value"></param>
public void SetBounds(Rectangle value)
{
get
{
return Task.Run(() => this.InvokeAsync<Rectangle>()).Result;
}
set
{
BridgeConnector.Socket.Emit("browserView-bounds-set", Id, value);
}
BridgeConnector.Emit("browserView-setBounds", Id, value);
}
/// <summary>
/// BrowserView
/// </summary>
internal BrowserView(int id)
internal BrowserView(int id)
{
Id = id;
@@ -57,17 +60,18 @@ namespace ElectronNET.API
/// <param name="options"></param>
public void SetAutoResize(AutoResizeOptions options)
{
BridgeConnector.Socket.Emit("browserView-setAutoResize", Id, options);
BridgeConnector.Emit("browserView-setAutoResize", Id, options);
}
/// <summary>
/// Color in #aarrggbb or #argb form. The alpha channel is optional.
///
/// (experimental)
/// </summary>
/// <param name="color">Color in #aarrggbb or #argb form. The alpha channel is optional.</param>
public void SetBackgroundColor(string color)
{
BridgeConnector.Socket.Emit("browserView-setBackgroundColor", Id, color);
BridgeConnector.Emit("browserView-setBackgroundColor", Id, color);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,27 +1,22 @@
using ElectronNET.API.Entities;
using ElectronNET.API.Serialization;
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System.Runtime.Versioning;
using System.Text.Json;
using System.Threading.Tasks;
// ReSharper disable InconsistentNaming
using ElectronNET.API.Interfaces;
namespace ElectronNET.API
{
/// <summary>
/// Perform copy and paste operations on the system clipboard.
/// </summary>
public sealed class Clipboard : ApiBase
public sealed class Clipboard : IClipboard
{
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.DashesLowerFirst;
protected override SocketTaskMessageNameTypes SocketTaskMessageNameType => SocketTaskMessageNameTypes.DashesLowerFirst;
private static Clipboard _clipboard;
private static object _syncRoot = new object();
private static readonly object _syncRoot = new();
internal Clipboard()
{
}
internal Clipboard() { }
internal static Clipboard Instance
{
@@ -47,7 +42,7 @@ namespace ElectronNET.API
/// </summary>
/// <param name="type"></param>
/// <returns>The content in the clipboard as plain text.</returns>
public Task<string> ReadTextAsync(string type = "") => this.InvokeAsync<string>(type);
public Task<string> ReadTextAsync(string type = "") => BridgeConnector.OnResult<string>("clipboard-readText", "clipboard-readText-Completed", type);
/// <summary>
/// Writes the text into the clipboard as plain text.
@@ -56,7 +51,7 @@ namespace ElectronNET.API
/// <param name="type"></param>
public void WriteText(string text, string type = "")
{
BridgeConnector.Socket.Emit("clipboard-writeText", text, type);
BridgeConnector.Emit("clipboard-writeText", text, type);
}
/// <summary>
@@ -64,7 +59,7 @@ namespace ElectronNET.API
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public Task<string> ReadHTMLAsync(string type = "") => this.InvokeAsync<string>(type);
public Task<string> ReadHTMLAsync(string type = "") => BridgeConnector.OnResult<string>("clipboard-readHTML", "clipboard-readHTML-Completed", type);
/// <summary>
/// Writes markup to the clipboard.
@@ -73,7 +68,7 @@ namespace ElectronNET.API
/// <param name="type"></param>
public void WriteHTML(string markup, string type = "")
{
BridgeConnector.Socket.Emit("clipboard-writeHTML", markup, type);
BridgeConnector.Emit("clipboard-writeHTML", markup, type);
}
/// <summary>
@@ -81,7 +76,8 @@ namespace ElectronNET.API
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public Task<string> ReadRTFAsync(string type = "") => this.InvokeAsync<string>(type);
public Task<string> ReadRTFAsync(string type = "") => BridgeConnector.OnResult<string>("clipboard-readRTF", "clipboard-readRTF-Completed", type);
/// <summary>
/// Writes the text into the clipboard in RTF.
@@ -90,34 +86,34 @@ namespace ElectronNET.API
/// <param name="type"></param>
public void WriteRTF(string text, string type = "")
{
BridgeConnector.Socket.Emit("clipboard-writeRTF", text, type);
BridgeConnector.Emit("clipboard-writeHTML", text, type);
}
/// <summary>
/// Returns an Object containing title and url keys representing
/// the bookmark in the clipboard. The title and url values will
/// Returns an Object containing title and url keys representing
/// the bookmark in the clipboard. The title and url values will
/// be empty strings when the bookmark is unavailable.
/// </summary>
/// <returns></returns>
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Windows")]
public Task<ReadBookmark> ReadBookmarkAsync() => this.InvokeAsync<ReadBookmark>();
[SupportedOSPlatform("windows")]
[SupportedOSPlatform("macos")]
public Task<ReadBookmark> ReadBookmarkAsync() => BridgeConnector.OnResult<ReadBookmark>("clipboard-readBookmark", "clipboard-readBookmark-Completed");
/// <summary>
/// Writes the title and url into the clipboard as a bookmark.
///
/// Note: Most apps on Windows dont support pasting bookmarks
/// into them so you can use clipboard.write to write both a
/// into them so you can use clipboard.write to write both a
/// bookmark and fallback text to the clipboard.
/// </summary>
/// <param name="title"></param>
/// <param name="url"></param>
/// <param name="type"></param>
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Windows")]
[SupportedOSPlatform("windows")]
[SupportedOSPlatform("macos")]
public void WriteBookmark(string title, string url, string type = "")
{
BridgeConnector.Socket.Emit("clipboard-writeBookmark", title, url, type);
BridgeConnector.Emit("clipboard-writeBookmark", title, url, type);
}
/// <summary>
@@ -126,18 +122,18 @@ namespace ElectronNET.API
/// find pasteboard whenever the application is activated.
/// </summary>
/// <returns></returns>
[SupportedOSPlatform("macOS")]
public Task<string> ReadFindTextAsync() => this.InvokeAsync<string>();
[SupportedOSPlatform("macos")]
public Task<string> ReadFindTextAsync() => BridgeConnector.OnResult<string>("clipboard-readFindText", "clipboard-readFindText-Completed");
/// <summary>
/// macOS: Writes the text into the find pasteboard as plain text. This method uses
/// macOS: Writes the text into the find pasteboard as plain text. This method uses
/// synchronous IPC when called from the renderer process.
/// </summary>
/// <param name="text"></param>
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("macos")]
public void WriteFindText(string text)
{
BridgeConnector.Socket.Emit("clipboard-writeFindText", text);
BridgeConnector.Emit("clipboard-writeFindText", text);
}
/// <summary>
@@ -146,7 +142,7 @@ namespace ElectronNET.API
/// <param name="type"></param>
public void Clear(string type = "")
{
BridgeConnector.Socket.Emit("clipboard-clear", type);
BridgeConnector.Emit("clipboard-clear", type);
}
/// <summary>
@@ -154,7 +150,7 @@ namespace ElectronNET.API
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public Task<string[]> AvailableFormatsAsync(string type = "") => this.InvokeAsync<string[]>(type);
public Task<string[]> AvailableFormatsAsync(string type = "") => BridgeConnector.OnResult<string[]>("clipboard-availableFormats", "clipboard-availableFormats-Completed", type);
/// <summary>
/// Writes data to the clipboard.
@@ -163,7 +159,7 @@ namespace ElectronNET.API
/// <param name="type"></param>
public void Write(Data data, string type = "")
{
BridgeConnector.Socket.Emit("clipboard-write", data, type);
BridgeConnector.Emit("clipboard-write", JObject.FromObject(data, _jsonSerializer), type);
}
/// <summary>
@@ -171,8 +167,8 @@ namespace ElectronNET.API
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public Task<NativeImage> ReadImageAsync(string type = "") => this.InvokeAsync<NativeImage>(type);
public Task<NativeImage> ReadImageAsync(string type = "") => BridgeConnector.OnResult<NativeImage>("clipboard-readImage", "clipboard-readImage-Completed", type);
/// <summary>
/// Writes an image to the clipboard.
/// </summary>
@@ -180,7 +176,14 @@ namespace ElectronNET.API
/// <param name="type"></param>
public void WriteImage(NativeImage image, string type = "")
{
BridgeConnector.Socket.Emit("clipboard-writeImage", JsonSerializer.Serialize(image, ElectronJson.Options), type);
BridgeConnector.Emit("clipboard-writeImage", JsonConvert.SerializeObject(image), type);
}
private static readonly JsonSerializer _jsonSerializer = new()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
}
}

View File

@@ -8,9 +8,7 @@ namespace ElectronNET.API
/// </summary>
public sealed class CommandLine
{
internal CommandLine()
{
}
private CommandLine() { }
internal static CommandLine Instance
{
@@ -33,7 +31,7 @@ namespace ElectronNET.API
private static CommandLine _commandLine;
private static object _syncRoot = new object();
private static readonly object _syncRoot = new();
/// <summary>
/// Append a switch (with optional value) to Chromium's command line.
@@ -45,7 +43,7 @@ namespace ElectronNET.API
/// </remarks>
public void AppendSwitch(string the_switch, string value = "")
{
BridgeConnector.Socket.Emit("appCommandLineAppendSwitch", the_switch, value);
BridgeConnector.Emit("appCommandLineAppendSwitch", the_switch, value);
}
/// <summary>
@@ -59,7 +57,7 @@ namespace ElectronNET.API
/// </remarks>
public void AppendArgument(string value)
{
BridgeConnector.Socket.Emit("appCommandLineAppendArgument", value);
BridgeConnector.Emit("appCommandLineAppendArgument", value);
}
/// <summary>
@@ -68,19 +66,7 @@ namespace ElectronNET.API
/// <param name="switchName">A command-line switch</param>
/// <param name="cancellationToken"></param>
/// <returns>Whether the command-line switch is present.</returns>
public async Task<bool> HasSwitchAsync(string switchName, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
var tcs = new TaskCompletionSource<bool>();
using (cancellationToken.Register(() => tcs.TrySetCanceled()))
{
BridgeConnector.Socket.Once<bool>("appCommandLineHasSwitchCompleted", tcs.SetResult);
BridgeConnector.Socket.Emit("appCommandLineHasSwitch", switchName);
return await tcs.Task.ConfigureAwait(false);
}
}
public Task<bool> HasSwitchAsync(string switchName, CancellationToken cancellationToken = default) => BridgeConnector.OnResult<bool>("appCommandLineHasSwitch", "appCommandLineHasSwitchCompleted", cancellationToken, switchName);
/// <summary>
/// The command-line switch value.
@@ -91,18 +77,6 @@ namespace ElectronNET.API
/// <remarks>
/// Note: When the switch is not present or has no value, it returns empty string.
/// </remarks>
public async Task<string> GetSwitchValueAsync(string switchName, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
var tcs = new TaskCompletionSource<string>();
using (cancellationToken.Register(() => tcs.TrySetCanceled()))
{
BridgeConnector.Socket.Once<string>("appCommandLineGetSwitchValueCompleted", tcs.SetResult);
BridgeConnector.Socket.Emit("appCommandLineGetSwitchValue", switchName);
return await tcs.Task.ConfigureAwait(false);
}
}
public Task<string> GetSwitchValueAsync(string switchName, CancellationToken cancellationToken = default) => BridgeConnector.OnResult<string>("appCommandLineGetSwitchValue", "appCommandLineGetSwitchValueCompleted", cancellationToken, switchName);
}
}
}

150
ElectronNET.API/Cookies.cs Normal file
View File

@@ -0,0 +1,150 @@
using System;
using System.Threading.Tasks;
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
namespace ElectronNET.API
{
/// <summary>
/// Query and modify a session's cookies.
/// </summary>
public class Cookies
{
/// <summary>
/// Gets the identifier.
/// </summary>
/// <value>
/// The identifier.
/// </value>
public int Id { get; private set; }
internal Cookies(int id)
{
Id = id;
}
/// <summary>
/// Emitted when a cookie is changed because it was added, edited, removed, or expired.
/// </summary>
public event Action<Cookie, CookieChangedCause, bool> OnChanged
{
add
{
if (_changed == null)
{
BridgeConnector.On<CookieRemovedResponse>("webContents-session-cookies-changed" + Id, (args) =>
{
_changed(args.cookie, args.cause, args.removed);
});
BridgeConnector.Emit("register-webContents-session-cookies-changed", Id);
}
_changed += value;
}
remove
{
_changed -= value;
if (_changed == null)
BridgeConnector.Off("webContents-session-cookies-changed" + Id);
}
}
private event Action<Cookie, CookieChangedCause, bool> _changed;
/// <summary>
/// Sends a request to get all cookies matching filter, and resolves a callack with the response.
/// </summary>
/// <param name="filter">
/// </param>
/// <returns>A task which resolves an array of cookie objects.</returns>
public Task<Cookie[]> GetAsync(CookieFilter filter)
{
var taskCompletionSource = new TaskCompletionSource<Cookie[]>(TaskCreationOptions.RunContinuationsAsynchronously);
string guid = Guid.NewGuid().ToString();
BridgeConnector.On<Cookie[]>("webContents-session-cookies-get-completed" + guid, (cookies) =>
{
BridgeConnector.Off("webContents-session-cookies-get-completed" + guid);
taskCompletionSource.SetResult(cookies);
});
BridgeConnector.Emit("webContents-session-cookies-get", Id, JObject.FromObject(filter, _jsonSerializer), guid);
return taskCompletionSource.Task;
}
/// <summary>
///
/// </summary>
/// <param name="details"></param>
/// <returns></returns>
public Task SetAsync(CookieDetails details)
{
var taskCompletionSource = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
string guid = Guid.NewGuid().ToString();
BridgeConnector.On("webContents-session-cookies-set-completed" + guid, () =>
{
BridgeConnector.Off("webContents-session-cookies-set-completed" + guid);
taskCompletionSource.SetResult(null);
});
BridgeConnector.Emit("webContents-session-cookies-set", Id, JObject.FromObject(details, _jsonSerializer), guid);
return taskCompletionSource.Task;
}
/// <summary>
/// Removes the cookies matching url and name
/// </summary>
/// <param name="url">The URL associated with the cookie.</param>
/// <param name="name">The name of cookie to remove.</param>
/// <returns>A task which resolves when the cookie has been removed</returns>
public Task RemoveAsync(string url, string name)
{
var taskCompletionSource = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
string guid = Guid.NewGuid().ToString();
BridgeConnector.On("webContents-session-cookies-remove-completed" + guid, () =>
{
BridgeConnector.Off("webContents-session-cookies-remove-completed" + guid);
taskCompletionSource.SetResult(null);
});
BridgeConnector.Emit("webContents-session-cookies-remove", Id, url, name, guid);
return taskCompletionSource.Task;
}
/// <summary>
/// Writes any unwritten cookies data to disk.
/// </summary>
/// <returns>A task which resolves when the cookie store has been flushed</returns>
public Task FlushStoreAsync()
{
var taskCompletionSource = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
string guid = Guid.NewGuid().ToString();
BridgeConnector.On("webContents-session-cookies-flushStore-completed" + guid, () =>
{
BridgeConnector.Off("webContents-session-cookies-flushStore-completed" + guid);
taskCompletionSource.SetResult(null);
});
BridgeConnector.Emit("webContents-session-cookies-flushStore", Id, guid);
return taskCompletionSource.Task;
}
private static readonly JsonSerializer _jsonSerializer = new()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
}
}

View File

@@ -0,0 +1,38 @@
using System.Threading.Tasks;
using ElectronNET.API.Entities;
using Newtonsoft.Json;
namespace ElectronNET.API
{
public sealed class DesktopCapturer
{
private static readonly object _syncRoot = new();
private static DesktopCapturer _desktopCapturer;
internal DesktopCapturer() { }
internal static DesktopCapturer Instance
{
get
{
if (_desktopCapturer == null)
{
lock (_syncRoot)
{
if (_desktopCapturer == null)
{
_desktopCapturer = new DesktopCapturer();
}
}
}
return _desktopCapturer;
}
}
public async Task<DesktopCapturerSource[]> GetSourcesAsync(SourcesOption option)
{
return await BridgeConnector.OnResult<DesktopCapturerSource[]>("desktop-capturer-get-sources", "desktop-capturer-get-sources-result", option);
}
}
}

View File

@@ -1,22 +1,25 @@
using ElectronNET.API.Entities;
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Runtime.Versioning;
using System.Text.Json;
using System.Threading.Tasks;
using System.Web;
using ElectronNET.API.Interfaces;
namespace ElectronNET.API
{
/// <summary>
/// Display native system dialogs for opening and saving files, alerting, etc.
/// </summary>
public sealed class Dialog
public sealed class Dialog : IDialog
{
private static Dialog _dialog;
private static object _syncRoot = new object();
private static readonly object _syncRoot = new();
internal Dialog()
{
}
internal Dialog() { }
internal static Dialog Instance
{
@@ -26,7 +29,7 @@ namespace ElectronNET.API
{
lock (_syncRoot)
{
if (_dialog == null)
if(_dialog == null)
{
_dialog = new Dialog();
}
@@ -38,8 +41,8 @@ namespace ElectronNET.API
}
/// <summary>
/// Note: On Windows and Linux an open dialog can not be both a file selector
/// and a directory selector, so if you set properties to ['openFile', 'openDirectory']
/// Note: On Windows and Linux an open dialog can not be both a file selector
/// and a directory selector, so if you set properties to ['openFile', 'openDirectory']
/// on these platforms, a directory selector will be shown.
/// </summary>
/// <param name="browserWindow">The browserWindow argument allows the dialog to attach itself to a parent window, making it modal.</param>
@@ -47,16 +50,25 @@ namespace ElectronNET.API
/// <returns>An array of file paths chosen by the user</returns>
public Task<string[]> ShowOpenDialogAsync(BrowserWindow browserWindow, OpenDialogOptions options)
{
var tcs = new TaskCompletionSource<string[]>();
var guid = Guid.NewGuid().ToString();
var taskCompletionSource = new TaskCompletionSource<string[]>(TaskCreationOptions.RunContinuationsAsynchronously);
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.Once<string[]>("showOpenDialogComplete" + guid, tcs.SetResult);
BridgeConnector.Socket.Emit("showOpenDialog",
browserWindow,
options,
guid);
BridgeConnector.On<string[]>("showOpenDialogComplete" + guid, (filePaths) =>
{
BridgeConnector.Off("showOpenDialogComplete" + guid);
return tcs.Task;
var list = new List<string>();
foreach (var item in filePaths)
{
list.Add(HttpUtility.UrlDecode(item));
}
taskCompletionSource.SetResult(list.ToArray());
});
BridgeConnector.Emit("showOpenDialog", browserWindow, options, guid);
return taskCompletionSource.Task;
}
/// <summary>
@@ -67,16 +79,19 @@ namespace ElectronNET.API
/// <returns>Returns String, the path of the file chosen by the user, if a callback is provided it returns an empty string.</returns>
public Task<string> ShowSaveDialogAsync(BrowserWindow browserWindow, SaveDialogOptions options)
{
var tcs = new TaskCompletionSource<string>();
var guid = Guid.NewGuid().ToString();
var taskCompletionSource = new TaskCompletionSource<string>(TaskCreationOptions.RunContinuationsAsynchronously);
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.Once<string>("showSaveDialogComplete" + guid, tcs.SetResult);
BridgeConnector.Socket.Emit("showSaveDialog",
browserWindow,
options,
guid);
BridgeConnector.On<string>("showSaveDialogComplete" + guid, (filename) =>
{
BridgeConnector.Off("showSaveDialogComplete" + guid);
return tcs.Task;
taskCompletionSource.SetResult(filename);
});
BridgeConnector.Emit("showSaveDialog", browserWindow, options, guid);
return taskCompletionSource.Task;
}
/// <summary>
@@ -90,7 +105,7 @@ namespace ElectronNET.API
/// <returns>The API call will be asynchronous and the result will be passed via MessageBoxResult.</returns>
public async Task<MessageBoxResult> ShowMessageBoxAsync(string message)
{
return await this.ShowMessageBoxAsync(null, new MessageBoxOptions(message)).ConfigureAwait(false);
return await ShowMessageBoxAsync(null, new MessageBoxOptions(message));
}
/// <summary>
@@ -104,7 +119,7 @@ namespace ElectronNET.API
/// <returns>The API call will be asynchronous and the result will be passed via MessageBoxResult.</returns>
public async Task<MessageBoxResult> ShowMessageBoxAsync(MessageBoxOptions messageBoxOptions)
{
return await this.ShowMessageBoxAsync(null, messageBoxOptions).ConfigureAwait(false);
return await ShowMessageBoxAsync(null, messageBoxOptions);
}
/// <summary>
@@ -117,7 +132,7 @@ namespace ElectronNET.API
/// <returns>The API call will be asynchronous and the result will be passed via MessageBoxResult.</returns>
public async Task<MessageBoxResult> ShowMessageBoxAsync(BrowserWindow browserWindow, string message)
{
return await this.ShowMessageBoxAsync(browserWindow, new MessageBoxOptions(message)).ConfigureAwait(false);
return await ShowMessageBoxAsync(browserWindow, new MessageBoxOptions(message));
}
/// <summary>
@@ -130,65 +145,56 @@ namespace ElectronNET.API
/// <returns>The API call will be asynchronous and the result will be passed via MessageBoxResult.</returns>
public Task<MessageBoxResult> ShowMessageBoxAsync(BrowserWindow browserWindow, MessageBoxOptions messageBoxOptions)
{
var tcs = new TaskCompletionSource<MessageBoxResult>();
var taskCompletionSource = new TaskCompletionSource<MessageBoxResult>(TaskCreationOptions.RunContinuationsAsynchronously);
var guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.Once<JsonElement>("showMessageBoxComplete" + guid, (args) =>
BridgeConnector.On<MessageBoxResponse>("showMessageBoxComplete" + guid, (args) =>
{
// args is [response:int, checkboxChecked:boolean]
var arr = args.EnumerateArray();
var e = arr.GetEnumerator();
e.MoveNext();
var response = e.Current.GetInt32();
e.MoveNext();
var checkbox = e.Current.GetBoolean();
BridgeConnector.Off("showMessageBoxComplete" + guid);
tcs.SetResult(new MessageBoxResult
taskCompletionSource.SetResult(new MessageBoxResult
{
Response = response,
CheckboxChecked = checkbox
Response = args.response,
CheckboxChecked = args.@checked
});
});
if (browserWindow == null)
if (browserWindow is null)
{
BridgeConnector.Socket.Emit("showMessageBox", messageBoxOptions, guid);
}
else
BridgeConnector.Emit("showMessageBox", JObject.FromObject(messageBoxOptions, _jsonSerializer), guid);
} else
{
BridgeConnector.Socket.Emit("showMessageBox",
browserWindow,
messageBoxOptions,
guid);
BridgeConnector.Emit("showMessageBox", JObject.FromObject(messageBoxOptions, _jsonSerializer), JObject.FromObject(messageBoxOptions, _jsonSerializer), guid);
}
return tcs.Task;
return taskCompletionSource.Task;
}
/// <summary>
/// Displays a modal dialog that shows an error message.
///
/// This API can be called safely before the ready event the app module emits,
/// it is usually used to report errors in early stage of startup.If called
/// before the app readyevent on Linux, the message will be emitted to stderr,
/// This API can be called safely before the ready event the app module emits,
/// it is usually used to report errors in early stage of startup.If called
/// before the app readyevent on Linux, the message will be emitted to stderr,
/// and no GUI dialog will appear.
/// </summary>
/// <param name="title">The title to display in the error box.</param>
/// <param name="content">The text content to display in the error box.</param>
public void ShowErrorBox(string title, string content)
{
BridgeConnector.Socket.Emit("showErrorBox", title, content);
BridgeConnector.Emit("showErrorBox", title, content);
}
/// <summary>
/// On macOS, this displays a modal dialog that shows a message and certificate information,
/// and gives the user the option of trusting/importing the certificate. If you provide a
/// and gives the user the option of trusting/importing the certificate. If you provide a
/// browserWindow argument the dialog will be attached to the parent window, making it modal.
/// </summary>
/// <param name="options"></param>
/// <returns></returns>
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Windows")]
[SupportedOSPlatform("windows")]
[SupportedOSPlatform("macos")]
public Task ShowCertificateTrustDialogAsync(CertificateTrustDialogOptions options)
{
return ShowCertificateTrustDialogAsync(null, options);
@@ -196,26 +202,35 @@ namespace ElectronNET.API
/// <summary>
/// On macOS, this displays a modal dialog that shows a message and certificate information,
/// and gives the user the option of trusting/importing the certificate. If you provide a
/// and gives the user the option of trusting/importing the certificate. If you provide a
/// browserWindow argument the dialog will be attached to the parent window, making it modal.
/// </summary>
/// <param name="browserWindow"></param>
/// <param name="options"></param>
/// <returns></returns>
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Windows")]
[SupportedOSPlatform("windows")]
[SupportedOSPlatform("macos")]
public Task ShowCertificateTrustDialogAsync(BrowserWindow browserWindow, CertificateTrustDialogOptions options)
{
var tcs = new TaskCompletionSource();
var taskCompletionSource = new TaskCompletionSource<object>(TaskCreationOptions.RunContinuationsAsynchronously);
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.Once("showCertificateTrustDialogComplete" + guid, () => tcs.SetResult());
BridgeConnector.Socket.Emit("showCertificateTrustDialog",
browserWindow,
options,
guid);
BridgeConnector.On("showCertificateTrustDialogComplete" + guid, () =>
{
BridgeConnector.Off("showCertificateTrustDialogComplete" + guid);
taskCompletionSource.SetResult(null);
});
return tcs.Task;
BridgeConnector.Emit("showCertificateTrustDialog", browserWindow, options, guid);
return taskCompletionSource.Task;
}
private static readonly JsonSerializer _jsonSerializer = new()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
}
}
}

View File

@@ -4,17 +4,21 @@ using System.Threading;
using System.Threading.Tasks;
using ElectronNET.API.Entities;
using ElectronNET.API.Extensions;
using ElectronNET.API.Interfaces;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
namespace ElectronNET.API
{
/// <summary>
/// Control your app in the macOS dock.
/// </summary>
[SupportedOSPlatform("macOS")]
public sealed class Dock
[SupportedOSPlatform("macos")]
public sealed class Dock : IDock
{
private static Dock _dock;
private static object _syncRoot = new object();
private static readonly object _syncRoot = new();
internal Dock()
{
@@ -49,19 +53,11 @@ namespace ElectronNET.API
/// <param name="type">Can be critical or informational. The default is informational.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Return an ID representing the request.</returns>
public async Task<int> BounceAsync(DockBounceType type, CancellationToken cancellationToken = default)
public Task<int> BounceAsync(DockBounceType type, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
var tcs = new TaskCompletionSource<int>();
using (cancellationToken.Register(() => tcs.TrySetCanceled()))
{
BridgeConnector.Socket.Once<int>("dock-bounce-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("dock-bounce", type);
return await tcs.Task
.ConfigureAwait(false);
}
return BridgeConnector.OnResult<int>("dock-bounce", "dock-bounce-completed", cancellationToken, type.GetDescription());
}
/// <summary>
@@ -70,7 +66,7 @@ namespace ElectronNET.API
/// <param name="id">Id of the request.</param>
public void CancelBounce(int id)
{
BridgeConnector.Socket.Emit("dock-cancelBounce", id);
BridgeConnector.Emit("dock-cancelBounce", id);
}
/// <summary>
@@ -79,7 +75,7 @@ namespace ElectronNET.API
/// <param name="filePath"></param>
public void DownloadFinished(string filePath)
{
BridgeConnector.Socket.Emit("dock-downloadFinished", filePath);
BridgeConnector.Emit("dock-downloadFinished", filePath);
}
/// <summary>
@@ -88,7 +84,7 @@ namespace ElectronNET.API
/// <param name="text"></param>
public void SetBadge(string text)
{
BridgeConnector.Socket.Emit("dock-setBadge", text);
BridgeConnector.Emit("dock-setBadge", text);
}
/// <summary>
@@ -96,19 +92,10 @@ namespace ElectronNET.API
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>The badge string of the dock.</returns>
public async Task<string> GetBadgeAsync(CancellationToken cancellationToken = default)
public Task<string> GetBadgeAsync(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
var tcs = new TaskCompletionSource<string>();
using (cancellationToken.Register(() => tcs.TrySetCanceled()))
{
BridgeConnector.Socket.Once<string>("dock-getBadge-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("dock-getBadge");
return await tcs.Task
.ConfigureAwait(false);
}
return BridgeConnector.OnResult<string>("dock-getBadge", "dock-getBadge-completed", cancellationToken);
}
/// <summary>
@@ -116,7 +103,7 @@ namespace ElectronNET.API
/// </summary>
public void Hide()
{
BridgeConnector.Socket.Emit("dock-hide");
BridgeConnector.Emit("dock-hide");
}
/// <summary>
@@ -124,7 +111,7 @@ namespace ElectronNET.API
/// </summary>
public void Show()
{
BridgeConnector.Socket.Emit("dock-show");
BridgeConnector.Emit("dock-show");
}
/// <summary>
@@ -133,19 +120,10 @@ namespace ElectronNET.API
/// </summary>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Whether the dock icon is visible.</returns>
public async Task<bool> IsVisibleAsync(CancellationToken cancellationToken = default)
public Task<bool> IsVisibleAsync(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
var tcs = new TaskCompletionSource<bool>();
using (cancellationToken.Register(() => tcs.TrySetCanceled()))
{
BridgeConnector.Socket.Once<bool>("dock-isVisible-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("dock-isVisible");
return await tcs.Task
.ConfigureAwait(false);
}
return BridgeConnector.OnResult<bool>("dock-isVisible", "dock-isVisible-completed", cancellationToken);
}
/// <summary>
@@ -154,15 +132,8 @@ namespace ElectronNET.API
/// <value>
/// The menu items.
/// </value>
public IReadOnlyCollection<MenuItem> MenuItems
{
get
{
return _items.AsReadOnly();
}
}
private List<MenuItem> _items = new List<MenuItem>();
public IReadOnlyCollection<MenuItem> MenuItems { get { return _items.AsReadOnly(); } }
private readonly List<MenuItem> _items = new();
/// <summary>
/// Sets the application's dock menu.
@@ -170,12 +141,11 @@ namespace ElectronNET.API
public void SetMenu(MenuItem[] menuItems)
{
menuItems.AddMenuItemsId();
BridgeConnector.Socket.Emit("dock-setMenu", new[] { menuItems });
BridgeConnector.Emit("dock-setMenu", JArray.FromObject(menuItems, _jsonSerializer));
_items.AddRange(menuItems);
BridgeConnector.Socket.Off("dockMenuItemClicked");
BridgeConnector.Socket.On<string>("dockMenuItemClicked", (id) =>
{
BridgeConnector.Off("dockMenuItemClicked");
BridgeConnector.On<string>("dockMenuItemClicked", (id) => {
MenuItem menuItem = _items.GetMenuItem(id);
menuItem?.Click();
});
@@ -185,20 +155,7 @@ namespace ElectronNET.API
/// TODO: Menu (macOS) still to be implemented
/// Gets the application's dock menu.
/// </summary>
public async Task<Menu> GetMenu(CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
var tcs = new TaskCompletionSource<Menu>();
using (cancellationToken.Register(() => tcs.TrySetCanceled()))
{
BridgeConnector.Socket.Once<Menu>("dock-getMenu-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("dock-getMenu");
return await tcs.Task
.ConfigureAwait(false);
}
}
public Task<Menu> GetMenu(CancellationToken cancellationToken = default) => BridgeConnector.OnResult<Menu>("dock-getMenu", "dock-getMenu-completed", cancellationToken);
/// <summary>
/// Sets the image associated with this dock icon.
@@ -206,7 +163,13 @@ namespace ElectronNET.API
/// <param name="image"></param>
public void SetIcon(string image)
{
BridgeConnector.Socket.Emit("dock-setIcon", image);
BridgeConnector.Emit("dock-setIcon", image);
}
private static readonly JsonSerializer _jsonSerializer = new()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
}
}

View File

@@ -0,0 +1,144 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Net.Sockets;
using System.Net;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ElectronNET.API
{
public static partial class Electron
{
/// <summary>
/// Experimental code, use with care
/// </summary>
public static class Experimental
{
/// <summary>
/// Starts electron from C#, use during development to avoid having to fully publish / build your app on every compile cycle
/// You will need to run the CLI at least once (and once per update) to bootstrap all required files
/// </summary>
/// <param name="webPort"></param>
/// <param name="projectPath"></param>
/// <param name="extraElectronArguments"></param>
/// <param name="clearCache"></param>
/// <exception cref="DirectoryNotFoundException"></exception>
/// <exception cref="Exception"></exception>
public static async Task<int> StartElectronForDevelopment(int webPort, string projectPath = null, string[] extraElectronArguments = null, bool clearCache = false)
{
string aspCoreProjectPath;
if (!string.IsNullOrEmpty(projectPath))
{
if (Directory.Exists(projectPath))
{
aspCoreProjectPath = projectPath;
}
else
{
throw new DirectoryNotFoundException(projectPath);
}
}
else
{
aspCoreProjectPath = Directory.GetCurrentDirectory();
}
string tempPath = Path.Combine(aspCoreProjectPath, "obj", "Host");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(tempPath);
}
var mainFileJs = Path.Combine(tempPath, "main.js");
if (!File.Exists(mainFileJs))
{
throw new Exception("You need to run once the electronize-h5 start command to bootstrap the necessary files");
}
var nodeModulesDirPath = Path.Combine(tempPath, "node_modules");
bool runNpmInstall = false;
if (!Directory.Exists(nodeModulesDirPath))
{
runNpmInstall = true;
}
var packagesJson = Path.Combine(tempPath, "package.json");
var packagesPrevious = Path.Combine(tempPath, "package.json.previous");
if (!runNpmInstall)
{
if (File.Exists(packagesPrevious))
{
if (File.ReadAllText(packagesPrevious) != File.ReadAllText(packagesJson))
{
runNpmInstall = true;
}
}
else
{
runNpmInstall = true;
}
}
if (runNpmInstall)
{
throw new Exception("You need to run once the electronize-h5 start command to bootstrap the necessary files");
}
string arguments = "";
if (extraElectronArguments is object)
{
arguments = string.Join(' ', extraElectronArguments);
}
if (clearCache)
{
arguments += " --clear-cache=true";
}
BridgeConnector.AuthKey = Guid.NewGuid().ToString().Replace("-", "");
var socketPort = FreeTcpPort();
arguments += $" --development=true --devauth={BridgeConnector.AuthKey} --devport={socketPort}";
string path = Path.Combine(tempPath, "node_modules", ".bin");
bool isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
if (isWindows)
{
ProcessHelper.Execute(@"electron.cmd ""..\..\main.js"" " + arguments, path);
}
else
{
ProcessHelper.Execute(@"./electron ""../../main.js"" " + arguments, path);
}
BridgeSettings.InitializePorts(socketPort, webPort);
await Task.Delay(500);
return socketPort;
}
/// <summary>
/// Return a free local TCP port
/// </summary>
/// <returns></returns>
public static int FreeTcpPort()
{
TcpListener l = new TcpListener(IPAddress.Loopback, 0);
l.Start();
int port = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();
return port;
}
}
}
}

139
ElectronNET.API/Electron.cs Normal file
View File

@@ -0,0 +1,139 @@
using Microsoft.Extensions.Logging;
using System.Runtime.Versioning;
using System;
using System.Collections.Generic;
namespace ElectronNET.API
{
/// <summary>
/// The Electron.NET API
/// </summary>
public static partial class Electron
{
private static ILoggerFactory loggerFactory;
/// <summary>
/// Reads the auth key from the command line. This method must be called first thing.
/// </summary>
/// <exception cref="Exception"></exception>
public static void ReadAuth()
{
if (!string.IsNullOrEmpty(BridgeConnector.AuthKey))
{
throw new Exception($"Don't call ReadAuth twice or from with {nameof(Experimental)}.{nameof(Experimental.StartElectronForDevelopment)}");
}
var line = Console.ReadLine();
if(line.StartsWith("Auth="))
{
BridgeConnector.AuthKey = line.Substring("Auth=".Length);
}
else
{
throw new Exception("The call to Electron.ReadAuth must be the first thing your app entry point does");
}
}
/// <summary>
/// Sets the logger factory to be used by Electron, if any
/// </summary>
public static ILoggerFactory LoggerFactory
{
private get => loggerFactory; set
{
loggerFactory = value;
BridgeConnector.Logger = value.CreateLogger<App>();
}
}
/// <summary>
/// Communicate asynchronously from the main process to renderer processes.
/// </summary>
public static IpcMain IpcMain { get { return IpcMain.Instance; } }
/// <summary>
/// Control your application's event lifecycle.
/// </summary>
public static App App { get { return App.Instance; } }
/// <summary>
/// Enable apps to automatically update themselves. Based on electron-updater.
/// </summary>
public static AutoUpdater AutoUpdater { get { return AutoUpdater.Instance; } }
/// <summary>
/// Control your windows.
/// </summary>
public static WindowManager WindowManager { get { return WindowManager.Instance; } }
/// <summary>
/// Create native application menus and context menus.
/// </summary>
public static Menu Menu { get { return Menu.Instance; } }
/// <summary>
/// Display native system dialogs for opening and saving files, alerting, etc.
/// </summary>
public static Dialog Dialog { get { return Dialog.Instance; } }
/// <summary>
/// Create OS desktop notifications
/// </summary>
public static Notification Notification { get { return Notification.Instance; } }
/// <summary>
/// Add icons and context menus to the systems notification area.
/// </summary>
public static Tray Tray { get { return Tray.Instance; } }
/// <summary>
/// Detect keyboard events when the application does not have keyboard focus.
/// </summary>
public static GlobalShortcut GlobalShortcut { get { return GlobalShortcut.Instance; } }
/// <summary>
/// Manage files and URLs using their default applications.
/// </summary>
public static Shell Shell { get { return Shell.Instance; } }
/// <summary>
/// Retrieve information about screen size, displays, cursor position, etc.
/// </summary>
public static Screen Screen { get { return Screen.Instance; } }
/// <summary>
/// Access information about media sources that can be used to capture audio and video from the desktop using the navigator.mediaDevices.getUserMedia API.
/// </summary>
public static DesktopCapturer DesktopCapturer { get { return DesktopCapturer.Instance; } }
/// <summary>
/// Perform copy and paste operations on the system clipboard.
/// </summary>
public static Clipboard Clipboard { get { return Clipboard.Instance; } }
/// <summary>
/// Allows you to execute native JavaScript/TypeScript code from the host process.
///
/// It is only possible if the Electron.NET CLI has previously added an
/// ElectronHostHook directory:
/// <c>electronize add HostHook</c>
/// </summary>
public static HostHook HostHook { get { return HostHook.Instance; } }
/// <summary>
/// Allows you to execute native Lock and Unlock process.
/// </summary>
public static PowerMonitor PowerMonitor { get { return PowerMonitor.Instance; } }
/// <summary>
/// Read and respond to changes in Chromium's native color theme.
/// </summary>
public static NativeTheme NativeTheme { get { return NativeTheme.Instance; } }
/// <summary>
/// Control your app in the macOS dock.
/// </summary>
[SupportedOSPlatform("macos")]
public static Dock Dock { get { return Dock.Instance; } }
}
}

View File

@@ -0,0 +1,55 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageOutputPath>..\artifacts</PackageOutputPath>
<PackageId>ElectronNET.API</PackageId>
<Authors>Gregor Biswanger, Robert Muehsig</Authors>
<Company />
<Product>Electron.NET</Product>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<PackageProjectUrl>https://github.com/ElectronNET/Electron.NET/</PackageProjectUrl>
<Description>
Building cross platform electron based desktop apps with .NET Core and ASP.NET Core.
This package contains the API to access the "native" electron API.
</Description>
<RepositoryUrl>https://github.com/ElectronNET/Electron.NET/</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<PackageTags>electron aspnetcore</PackageTags>
<PackageReleaseNotes>Changelog: https://github.com/ElectronNET/Electron.NET/blob/master/Changelog.md</PackageReleaseNotes>
<PackageIcon>PackageIcon.png</PackageIcon>
<Version>99.0.0.0</Version>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<TargetFrameworks>net6.0</TargetFrameworks>
</PropertyGroup>
<ItemGroup>
<None Include="PackageIcon.png" Pack="true" PackagePath="\" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(OS)' == 'Windows_NT'">
<Exec Command="$(ProjectDir)devCleanup.cmd" IgnoreExitCode="true" />
</Target>
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(OS)' != 'Windows_NT'">
<Exec Command="$(ProjectDir)devCleanup.sh" IgnoreExitCode="true" />
</Target>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Nito.AsyncEx" Version="5.1.2" />
<PackageReference Include="SocketIOClient" Version="3.0.6" />
<PackageReference Include="System.Collections" Version="4.3.0" />
<PackageReference Include="System.Reactive" Version="5.0.0" />
<PackageReference Include="SixLabors.ImageSharp" Version="1.0.4" />
</ItemGroup>
</Project>

View File

@@ -1,11 +1,8 @@
using System.Runtime.Versioning;
namespace ElectronNET.API.Entities
namespace ElectronNET.API.Entities
{
/// <summary>
/// About panel options.
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class AboutPanelOptions
{
/// <summary>
@@ -24,35 +21,28 @@ namespace ElectronNET.API.Entities
public string Copyright { get; set; }
/// <summary>
/// The app's build version number (macOS).
/// The app's build version number.
/// </summary>
[SupportedOSPlatform("macos")]
public string Version { get; set; }
/// <summary>
/// Credit information (macOS, Windows).
/// Credit information.
/// </summary>
[SupportedOSPlatform("macos")]
[SupportedOSPlatform("windows")]
public string Credits { get; set; }
/// <summary>
/// List of app authors (Linux).
/// List of app authors.
/// </summary>
[SupportedOSPlatform("linux")]
public string[] Authors { get; set; }
/// <summary>
/// The app's website (Linux).
/// The app's website.
/// </summary>
[SupportedOSPlatform("linux")]
public string Website { get; set; }
/// <summary>
/// Path to the app's icon in a JPEG or PNG file format. On Linux, will be shown as 64x64 pixels while retaining aspect ratio. On Windows, a 48x48 PNG will result in the best visual quality.
/// Path to the app's icon. On Linux, will be shown as 64x64 pixels while retaining aspect ratio.
/// </summary>
[SupportedOSPlatform("linux")]
[SupportedOSPlatform("windows")]
public string IconPath { get; set; }
}
}

View File

@@ -0,0 +1,33 @@
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class AddRepresentationOptions
{
/// <summary>
/// Gets or sets the width
/// </summary>
public int? Width { get; set; }
/// <summary>
/// Gets or sets the height
/// </summary>
public int? Height { get; set; }
/// <summary>
/// Gets or sets the scalefactor
/// </summary>
public float ScaleFactor { get; set; } = NativeImage.DefaultScaleFactor;
/// <summary>
/// Gets or sets the buffer
/// </summary>
public byte[] Buffer { get; set; }
/// <summary>
/// Gets or sets the dataURL
/// </summary>
public string DataUrl { get; set; }
}
}

View File

@@ -1,36 +1,32 @@
using System.Runtime.Versioning;
namespace ElectronNET.API.Entities
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
[SupportedOSPlatform("windows")]
public class AppDetailsOptions
{
/// <summary>
/// Window's App User Model ID. It has to be set, otherwise the other options will have no effect.
/// Windows App User Model ID. It has to be set, otherwise the other options will have no effect.
/// </summary>
public string AppId { get; set; }
/// <summary>
/// Window's relaunch icon resource path.
/// Windows Relaunch Icon.
/// </summary>
public string AppIconPath { get; set; }
/// <summary>
/// Index of the icon in <see cref="AppIconPath"/>. Ignored when <see cref="AppIconPath"/> is not set. Default is 0.
/// Index of the icon in appIconPath. Ignored when appIconPath is not set. Default is 0.
/// </summary>
public int AppIconIndex { get; set; }
/// <summary>
/// Window's relaunch command.
/// Windows Relaunch Command.
/// </summary>
public string RelaunchCommand { get; set; }
/// <summary>
/// Window's relaunch display name.
/// Windows Relaunch Display Name.
/// </summary>
public string RelaunchDisplayName { get; set; }
}

View File

@@ -5,7 +5,6 @@ namespace ElectronNET.API.Entities
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class AutoResizeOptions
{
/// <summary>
@@ -36,4 +35,4 @@ namespace ElectronNET.API.Entities
[DefaultValue(false)]
public bool Vertical { get; set; } = false;
}
}
}

View File

@@ -0,0 +1,20 @@
using System;
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
[Obsolete("Use ImageOptions instead.")]
public class BitmapOptions
{
/// <summary>
/// Gets or sets the scale factor
/// </summary>
public float ScaleFactor { get; set; } = NativeImage.DefaultScaleFactor;
/// <summary>
/// Utility conversion for obsolete class
/// </summary>
public static implicit operator ImageOptions(BitmapOptions o) => new() {ScaleFactor = o.ScaleFactor};
}
}

View File

@@ -3,7 +3,6 @@
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class Blob : IPostData
{
/// <summary>

View File

@@ -1,4 +1,8 @@
namespace ElectronNET.API.Entities
using System;
using System.Collections.Generic;
using System.Text;
namespace ElectronNET.API.Entities
{
/// <summary>
///
@@ -28,4 +32,4 @@
/// </summary>
public bool IsAdminRightsRequired { get; set; }
}
}
}

View File

@@ -3,26 +3,23 @@
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class BrowserViewConstructorOptions
{
/// <summary>
/// Gets or sets the web preferences for the view (see WebPreferences).
/// See BrowserWindow.
/// </summary>
public WebPreferences WebPreferences { get; set; }
/// <summary>
/// Gets or sets a proxy to use on creation in the format host:port.
/// A proxy to set on creation in the format host:port.
/// The proxy can be alternatively set using the BrowserView.WebContents.SetProxyAsync function.
/// </summary>
/// <remarks>This is custom shortcut. Not part of the Electron API.</remarks>
public string Proxy { get; set; }
/// <summary>
/// Gets or sets the credentials of the proxy in the format username:password.
/// The credentials of the Proxy in the format username:password.
/// These will only be used if the Proxy field is also set.
/// </summary>
/// <remarks>This is custom shortcut. Not part of the Electron API.</remarks>
public string ProxyCredentials { get; set; }
}
}
}

View File

@@ -1,6 +1,6 @@
using ElectronNET.Converter;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.ComponentModel;
using System.Text.Json.Serialization;
using System.Runtime.Versioning;
namespace ElectronNET.API.Entities
@@ -37,70 +37,62 @@ namespace ElectronNET.API.Entities
/// window's size will include window frame's size and be slightly larger. Default
/// is false.
/// </summary>
public bool UseContentSize { get; set; }
public bool? UseContentSize { get; set; }
/// <summary>
/// Show window in the center of the screen.
/// </summary>
public bool Center { get; set; }
public bool? Center { get; set; }
/// <summary>
/// Window's minimum width. Default is 0.
/// </summary>
public int MinWidth { get; set; }
public int? MinWidth { get; set; }
/// <summary>
/// Window's minimum height. Default is 0.
/// </summary>
public int MinHeight { get; set; }
public int? MinHeight { get; set; }
/// <summary>
/// Window's maximum width. Default is no limit.
/// </summary>
public int MaxWidth { get; set; }
public int? MaxWidth { get; set; }
/// <summary>
/// Window's maximum height. Default is no limit.
/// </summary>
public int MaxHeight { get; set; }
public int? MaxHeight { get; set; }
/// <summary>
/// Whether window is resizable. Default is true.
/// </summary>
[DefaultValue(true)]
public bool Resizable { get; set; } = true;
public bool? Resizable { get; set; } = true;
/// <summary>
/// Whether window is movable. This is not implemented on Linux. Default is true.
/// </summary>
[SupportedOSPlatform("macos")]
[SupportedOSPlatform("windows")]
[DefaultValue(true)]
public bool Movable { get; set; } = true;
public bool? Movable { get; set; } = true;
/// <summary>
/// Whether window is minimizable. This is not implemented on Linux. Default is true.
/// </summary>
[SupportedOSPlatform("macos")]
[SupportedOSPlatform("windows")]
[DefaultValue(true)]
public bool Minimizable { get; set; } = true;
public bool? Minimizable { get; set; } = true;
/// <summary>
/// Whether window is maximizable. This is not implemented on Linux. Default is true.
/// </summary>
[SupportedOSPlatform("macos")]
[SupportedOSPlatform("windows")]
[DefaultValue(true)]
public bool Maximizable { get; set; } = true;
public bool? Maximizable { get; set; } = true;
/// <summary>
/// Whether window is closable. This is not implemented on Linux. Default is true.
/// </summary>
[SupportedOSPlatform("macos")]
[SupportedOSPlatform("windows")]
[DefaultValue(true)]
public bool Closable { get; set; } = true;
public bool? Closable { get; set; } = true;
/// <summary>
/// Whether the window can be focused. Default is true. On Windows setting
@@ -109,43 +101,35 @@ namespace ElectronNET.API.Entities
/// always stay on top in all workspaces.
/// </summary>
[DefaultValue(true)]
public bool Focusable { get; set; } = true;
public bool? Focusable { get; set; } = true;
/// <summary>
/// Whether the window should always stay on top of other windows. Default is false.
/// </summary>
public bool AlwaysOnTop { get; set; }
public bool? AlwaysOnTop { get; set; }
/// <summary>
/// Whether the window should show in fullscreen. When explicitly set to false the
/// fullscreen button will be hidden or disabled on macOS.Default is false.
/// </summary>
public bool Fullscreen { get; set; }
public bool? Fullscreen { get; set; }
/// <summary>
/// Whether the window can be put into fullscreen mode. On macOS, also whether the
/// maximize/zoom button should toggle full screen mode or maximize window. Default
/// is true (Electron default).
/// maximize/zoom button should toggle full screen mode or maximize window.Default
/// is true.
/// </summary>
[DefaultValue(true)]
public bool Fullscreenable { get; set; } = true; // FIX: previously defaulted to false in C#
public bool? Fullscreenable { get; set; }
/// <summary>
/// Whether to show the window in taskbar. Default is false.
/// </summary>
[SupportedOSPlatform("macos")]
[SupportedOSPlatform("windows")]
public bool SkipTaskbar { get; set; }
/// <summary>
/// Determines if Blazor is used. Will disable "module" and "process" globals. Default is false.
/// </summary>
public bool IsRunningBlazor { get; set; }
public bool? SkipTaskbar { get; set; }
/// <summary>
/// The kiosk mode. Default is false.
/// </summary>
public bool Kiosk { get; set; }
public bool? Kiosk { get; set; }
/// <summary>
/// Default window title. Default is "Electron.NET".
@@ -153,7 +137,8 @@ namespace ElectronNET.API.Entities
public string Title { get; set; } = "Electron.NET";
/// <summary>
/// The window icon. Can be a NativeImage or a string path. On Windows it is recommended to use ICO icons; when undefined, the executable's icon will be used.
/// The window icon. On Windows it is recommended to use ICO icons to get best
/// visual effects, you can also leave it undefined so the executable's icon will be used.
/// </summary>
public string Icon { get; set; }
@@ -161,71 +146,63 @@ namespace ElectronNET.API.Entities
/// Whether window should be shown when created. Default is true.
/// </summary>
[DefaultValue(true)]
public bool Show { get; set; } = true;
public bool? Show { get; set; } = true;
/// <summary>
/// Specify false to create a frameless window. Default is true.
/// Specify false to create a . Default is true.
/// </summary>
[DefaultValue(true)]
public bool Frame { get; set; } = true;
public bool? Frame { get; set; } = true;
/// <summary>
/// Whether this is a modal window. This only works when the window is a child
/// window.Default is false.
/// Whether this is a modal window. This only works when <see cref="Parent"/> is
/// also specified. Default is false.
/// </summary>
public bool Modal { get; set; }
public bool? Modal { get; set; }
/// <summary>
/// Whether the web view accepts a single mouse-down event that simultaneously
/// activates the window.Default is false.
/// activates the window. Default is false.
/// </summary>
[SupportedOSPlatform("macos")]
public bool AcceptFirstMouse { get; set; }
public bool? AcceptFirstMouse { get; set; }
/// <summary>
/// Whether to hide cursor when typing. Default is false.
/// </summary>
public bool DisableAutoHideCursor { get; set; }
public bool? DisableAutoHideCursor { get; set; }
/// <summary>
/// Auto hide the menu bar unless the Alt key is pressed. Default is false.
/// </summary>
[SupportedOSPlatform("windows")]
[SupportedOSPlatform("linux")]
public bool AutoHideMenuBar { get; set; }
public bool? AutoHideMenuBar { get; set; }
/// <summary>
/// Enable the window to be resized larger than screen. Default is false.
/// </summary>
[SupportedOSPlatform("macos")]
public bool EnableLargerThanScreen { get; set; }
public bool? EnableLargerThanScreen { get; set; }
/// <summary>
/// The window's background color in Hex, RGB, RGBA, HSL, HSLA or named CSS color format. Alpha in #AARRGGBB format is supported if transparent is set to true. Default is #FFF (white).
/// Window's background color as Hexadecimal value, like #66CD00 or #FFF or
/// #80FFFFFF (alpha is supported). Default is #FFF (white).
/// </summary>
public string BackgroundColor { get; set; }
/// <summary>
/// Initial opacity of the window, between 0.0 (fully transparent) and 1.0 (fully opaque). Only implemented on Windows and macOS.
/// Whether window should have a shadow. This is only implemented on macOS. Default
/// is true.
/// </summary>
[SupportedOSPlatform("windows")]
[SupportedOSPlatform("macos")]
public double? Opacity { get; set; }
public bool? HasShadow { get; set; }
/// <summary>
/// Whether window should have a shadow. Default is true.
/// Forces using dark theme for the window, only works on some GTK+3 desktop
/// environments.Default is false.
/// </summary>
public bool HasShadow { get; set; }
public bool? DarkTheme { get; set; }
/// <summary>
/// Forces using dark theme for the window, only works on some GTK+3 desktop environments. Default is false.
/// Makes the window . Default is false.
/// </summary>
public bool DarkTheme { get; set; }
/// <summary>
/// Makes the window transparent. Default is false.
/// </summary>
public bool Transparent { get; set; }
public bool? Transparent { get; set; }
/// <summary>
/// The type of window, default is normal window.
@@ -236,59 +213,38 @@ namespace ElectronNET.API.Entities
/// The style of window title bar. Default is default. Possible values are:
/// 'default' | 'hidden' | 'hiddenInset' | 'customButtonsOnHover'
/// </summary>
public TitleBarStyle TitleBarStyle { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public TitleBarStyle? TitleBarStyle { get; set; }
/// <summary>
/// Set a custom position for the traffic light buttons in frameless windows (macOS).
/// Shows the title in the tile bar in full screen mode on macOS for all
/// titleBarStyle options.Default is false.
/// </summary>
public bool? FullscreenWindowTitle { get; set; }
/// <summary>
/// Activate the Window Controls Overlay on Windows, when combined with <see cref="TitleBarStyle"/> = <see cref="TitleBarStyle.hidden"/>
/// </summary>
[SupportedOSPlatform("win")]
[SupportedOSPlatform("macos")]
public Point TrafficLightPosition { get; set; }
/// <summary>
/// Configures the window's title bar overlay when using a frameless window.
/// Can be either:
/// - false: No title bar overlay.
/// - true: Enables the default title bar overlay.
/// - An object defining custom overlay options (such as height, color, etc.).
///
/// Default is false.
/// </summary>
[JsonConverter(typeof(TitleBarOverlayConverter))]
public TitleBarOverlay TitleBarOverlay { get; set; }
/// <summary>
/// Shows the title in the title bar in full screen mode on macOS for all titleBarStyle options. Default is false.
/// </summary>
/// <remarks>Not documented by MCP base-window-options / browser-window-options.</remarks>
public bool FullscreenWindowTitle { get; set; }
[DefaultValue(null)]
public TitleBarOverlayConfig TitleBarOverlay { get; set; }
/// <summary>
/// Use WS_THICKFRAME style for frameless windows on Windows, which adds standard
/// window frame.Setting it to false will remove window shadow and window
/// animations. Default is true.
/// </summary>
[SupportedOSPlatform("windows")]
[DefaultValue(true)]
public bool ThickFrame { get; set; } = true;
/// <summary>
/// Whether frameless window should have rounded corners. Default is true. Setting this
/// property to false will prevent the window from being fullscreenable on macOS. On
/// Windows versions older than Windows 11 Build 22000 this property has no effect, and
/// frameless windows will not have rounded corners.
/// </summary>
[SupportedOSPlatform("macos")]
[SupportedOSPlatform("windows")]
[DefaultValue(true)]
public bool RoundedCorners { get; set; } = true;
public bool? ThickFrame { get; set; } = true;
/// <summary>
/// Add a type of vibrancy effect to the window, only on macOS. Can be
/// appearance-based, titlebar, selection, menu, popover, sidebar, header, sheet,
/// window, hud, fullscreen-ui, tooltip, content, under-window, or under-page.
/// appearance-based, light, dark, titlebar, selection, menu, popover, sidebar,
/// medium-light or ultra-dark.
/// </summary>
[SupportedOSPlatform("macos")]
public Vibrancy Vibrancy { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public Vibrancy? Vibrancy { get; set; }
/// <summary>
/// Controls the behavior on macOS when option-clicking the green stoplight button
@@ -297,8 +253,7 @@ namespace ElectronNET.API.Entities
/// it to zoom to the width of the screen.This will also affect the behavior when
/// calling maximize() directly.Default is false.
/// </summary>
[SupportedOSPlatform("macos")]
public bool ZoomToPageWidth { get; set; }
public bool? ZoomToPageWidth { get; set; }
/// <summary>
/// Tab group name, allows opening the window as a native tab on macOS 10.12+.
@@ -306,7 +261,6 @@ namespace ElectronNET.API.Entities
/// adds a native new tab button to your window's tab bar and allows your app and
/// window to receive the new-window-for-tab event.
/// </summary>
[SupportedOSPlatform("macos")]
public string TabbingIdentifier { get; set; }
/// <summary>
@@ -318,39 +272,26 @@ namespace ElectronNET.API.Entities
/// A proxy to set on creation in the format host:port.
/// The proxy can be alternatively set using the BrowserWindow.WebContents.SetProxyAsync function.
/// </summary>
/// <remarks>Not documented by MCP base-window-options / browser-window-options.</remarks>
public string Proxy { get; set; }
/// <summary>
/// The credentials of the Proxy in the format username:password.
/// These will only be used if the Proxy field is also set.
/// </summary>
/// <remarks>Not documented by MCP base-window-options / browser-window-options.</remarks>
public string ProxyCredentials { get; set; }
/// <summary>
/// Gets or sets whether to use pre-Lion fullscreen on macOS. Default is false.
/// The window to use as the created window's parent.
/// </summary>
[SupportedOSPlatform("macos")]
public bool SimpleFullscreen { get; set; }
[DefaultValue(null)]
public BrowserWindow Parent { get; set; }
/// <summary>
/// Gets or sets whether the window should be hidden when the user toggles into mission control (macOS).
/// Set a custom position for the traffic light buttons in frameless windows.
/// </summary>
[SupportedOSPlatform("macos")]
public bool HiddenInMissionControl { get; set; }
/// <summary>
/// Gets or sets how the material appearance should reflect window activity state on macOS. Must be used with the vibrancy property.
/// Possible values: 'followWindow' (default), 'active', 'inactive'.
/// </summary>
[DefaultValue(null)]
[SupportedOSPlatform("macos")]
public string VisualEffectState { get; set; }
/// <summary>
/// Gets or sets the system-drawn background material on Windows. Can be 'auto', 'none', 'mica', 'acrylic' or 'tabbed'.
/// </summary>
[SupportedOSPlatform("windows")]
public string BackgroundMaterial { get; set; }
public Point TrafficLightPosition { get; set; }
}
}
}

View File

@@ -0,0 +1,19 @@
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class CPUUsage
{
/// <summary>
/// Percentage of CPU used since the last call to getCPUUsage. First call returns 0.
/// </summary>
public int PercentCPUUsage { get; set; }
/// <summary>
/// The number of average idle cpu wakeups per second since the last call to
/// getCPUUsage.First call returns 0.
/// </summary>
public int IdleWakeupsPerSecond { get; set; }
}
}

View File

@@ -3,7 +3,6 @@
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class Certificate
{
/// <summary>

View File

@@ -3,7 +3,6 @@
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class CertificatePrincipal
{
/// <summary>

View File

@@ -3,7 +3,6 @@
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class CertificateTrustDialogOptions
{
/// <summary>

View File

@@ -1,9 +1,12 @@
namespace ElectronNET.API.Entities
using System;
using System.Collections.Generic;
using System.Text;
namespace ElectronNET.API.Entities
{
/// <summary>
/// Provide metadata about the current loaded Chrome extension
/// </summary>
/// <yremarks>Project-specific: no matching Electron structure found in MCP docs (electronjs).</yremarks>
public class ChromeExtensionInfo
{
/// <summary>
@@ -27,4 +30,4 @@
/// </summary>
public string Version { get; set; }
}
}
}

View File

@@ -0,0 +1,24 @@
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class ClearStorageDataOptions
{
/// <summary>
/// Should follow window.location.origins representation scheme://host:port.
/// </summary>
public string Origin { get; set; }
/// <summary>
/// The types of storages to clear, can contain: appcache, cookies, filesystem,
/// indexdb, localstorage, shadercache, websql, serviceworkers, cachestorage.
/// </summary>
public string[] Storages { get; set; }
/// <summary>
/// The types of quotas to clear, can contain: temporary, persistent, syncable.
/// </summary>
public string[] Quotas { get; set; }
}
}

View File

@@ -0,0 +1,51 @@
namespace ElectronNET.API.Entities {
/// <summary>
///
/// </summary>
public class Cookie {
/// <summary>
/// The name of the cookie.
/// </summary>
public string Name { get; set;}
/// <summary>
/// The value of the cookie.
/// </summary>
public string Value { get; set; }
/// <summary>
/// (optional) - The domain of the cookie; this will be normalized with a preceding dot so that it's also valid for subdomains.
/// </summary>
public string Domain { get; set; }
/// <summary>
/// (optional) - Whether the cookie is a host-only cookie; this will only be true if no domain was passed.
/// </summary>
public bool HostOnly { get; set; }
/// <summary>
/// (optional) - The path of the cookie.
/// </summary>
public string Path { get; set; }
/// <summary>
/// (optional) - Whether the cookie is marked as secure.
/// </summary>
public bool Secure { get; set; }
/// <summary>
/// (optional) - Whether the cookie is marked as HTTP only.
/// </summary>
public bool HttpOnly { get; set; }
/// <summary>
/// (optional) - Whether the cookie is a session cookie or a persistent cookie with an expiration date.
/// </summary>
public bool Session { get; set; }
/// <summary>
/// (optional) - The expiration date of the cookie as the number of seconds since the UNIX epoch. Not provided for session cookies.
/// </summary>
public long ExpirationDate { get; set; }
}
}

View File

@@ -0,0 +1,40 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace ElectronNET.API.Entities
{
/// <summary>
/// The cause of the change
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public enum CookieChangedCause
{
/// <summary>
///The cookie was changed directly by a consumer's action.
/// </summary>
[JsonProperty("explicit")]
@explicit,
/// <summary>
/// The cookie was automatically removed due to an insert operation that overwrote it.
/// </summary>
overwrite,
/// <summary>
/// The cookie was automatically removed as it expired.
/// </summary>
expired,
/// <summary>
/// The cookie was automatically evicted during garbage collection.
/// </summary>
evicted,
/// <summary>
/// The cookie was overwritten with an already-expired expiration date.
/// </summary>
[JsonProperty("expired_overwrite")]
expiredOverwrite
}
}

View File

@@ -0,0 +1,56 @@
using System.ComponentModel;
namespace ElectronNET.API.Entities {
/// <summary>
///
/// </summary>
public class CookieDetails {
/// <summary>
/// The URL to associate the cookie with. The callback will be rejected if the URL is invalid.
/// </summary>
public string Url { get; set; }
/// <summary>
/// (optional) - The name of the cookie. Empty by default if omitted.
/// </summary>
[DefaultValue("")]
public string Name { get; set; }
/// <summary>
/// (optional) - The value of the cookie. Empty by default if omitted.
/// </summary>
[DefaultValue("")]
public string Value { get; set; }
/// <summary>
/// (optional) - The domain of the cookie; this will be normalized with a preceding dot so that it's also valid for subdomains. Empty by default if omitted.
/// </summary>
[DefaultValue("")]
public string Domain { get; set; }
/// <summary>
/// (optional) - The path of the cookie. Empty by default if omitted.
/// </summary>
[DefaultValue("")]
public string Path { get; set; }
/// <summary>
/// (optional) - Whether the cookie is marked as secure. Defaults to false.
/// </summary>
[DefaultValue(false)]
public bool Secure { get; set; }
/// <summary>
/// (optional) - Whether the cookie is marked as HTTP only. Defaults to false.
/// </summary>
[DefaultValue(false)]
public bool HttpOnly { get; set; }
/// <summary>
/// (optional) - The expiration date of the cookie as the number of seconds since the UNIX epoch.
/// If omitted then the cookie becomes a session cookie and will not be retained between sessions.
/// </summary>
[DefaultValue(0)]
public long ExpirationDate { get; set; }
}
}

View File

@@ -1,13 +1,16 @@
namespace ElectronNET.API.Entities
using System;
using System.Collections.Generic;
using System.Text;
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class CookieFilter
public class CookieFilter
{
/// <summary>
/// (optional) - Retrieves cookies which are associated with url. Empty implies retrieving cookies of all URLs.
/// (optional) - Retrieves cookies which are associated with url.Empty implies retrieving cookies of all URLs.
/// </summary>
public string Url { get; set; }
@@ -36,9 +39,5 @@
/// </summary>
public bool Session { get; set; }
/// <summary>
/// (optional) - Filters cookies by httpOnly.
/// </summary>
public bool HttpOnly { get; set; }
}
}
}

View File

@@ -0,0 +1,10 @@
namespace ElectronNET.API.Entities
{
public class CookieRemovedResponse
{
public Cookie cookie {get;set;}
public CookieChangedCause cause { get; set; }
public bool removed { get; set; }
}
}

View File

@@ -0,0 +1,32 @@
using System;
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
[Obsolete("Use CreateOptions instead")]
public class CreateFromBitmapOptions
{
/// <summary>
/// Gets or sets the width
/// </summary>
public int? Width { get; set; }
/// <summary>
/// Gets or sets the height
/// </summary>
public int? Height { get; set; }
/// <summary>
/// Gets or sets the scalefactor
/// </summary>
public float ScaleFactor { get; set; } = NativeImage.DefaultScaleFactor;
/// <summary>
/// Utility conversion for obsolete class
/// </summary>
public static implicit operator CreateOptions(CreateFromBitmapOptions o) => new()
{Width = o.Width, Height = o.Height, ScaleFactor = o.ScaleFactor};
}
}

View File

@@ -0,0 +1,31 @@
using System;
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
[Obsolete("Use CreateOptions instead")]
public class CreateFromBufferOptions
{
/// <summary>
/// Gets or sets the width
/// </summary>
public int? Width { get; set; }
/// <summary>
/// Gets or sets the height
/// </summary>
public int? Height { get; set; }
/// <summary>
/// Gets or sets the scalefactor
/// </summary>
public float ScaleFactor { get; set; } = NativeImage.DefaultScaleFactor;
/// <summary>
/// Utility conversion for obsolete class
/// </summary>
public static implicit operator CreateOptions(CreateFromBufferOptions o) => new()
{Width = o.Width, Height = o.Height, ScaleFactor = o.ScaleFactor};
}
}

View File

@@ -3,7 +3,6 @@
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class CreateInterruptedDownloadOptions
{
/// <summary>
@@ -17,7 +16,7 @@
public string[] UrlChain { get; set; }
/// <summary>
/// (optional) - MIME type of the download.
///
/// </summary>
public string MimeType { get; set; }
@@ -42,10 +41,9 @@
public string ETag { get; set; }
/// <summary>
/// (optional) - Time when download was started in number of seconds since UNIX epoch.
/// Electron documents this as a Number (Double).
/// Time when download was started in number of seconds since UNIX epoch.
/// </summary>
public double? StartTime { get; set; }
public int StartTime { get; set; }
/// <summary>
///
@@ -66,4 +64,4 @@
ETag = eTag;
}
}
}
}

View File

@@ -0,0 +1,24 @@
namespace ElectronNET.API.Entities
{
/// <summary>
/// Options for creating a new <see cref="NativeImage"/>
/// </summary>
public class CreateOptions
{
/// <summary>
/// Gets or sets the width
/// </summary>
public int? Width { get; set; }
/// <summary>
/// Gets or sets the height
/// </summary>
public int? Height { get; set; }
/// <summary>
/// Gets or sets the scalefactor
/// </summary>
public float ScaleFactor { get; set; } = NativeImage.DefaultScaleFactor;
}
}

View File

@@ -21,12 +21,6 @@
/// </value>
public string Html { get; set; }
/// <summary>
/// Gets or sets the image.
/// Maps to clipboard.write({ image: NativeImage }).
/// </summary>
public NativeImage Image { get; set; }
/// <summary>
/// Gets or sets the RTF.
@@ -40,5 +34,7 @@
/// The title of the url at text.
/// </summary>
public string Bookmark { get; set; }
public NativeImage? Image { get; set; }
}
}
}

View File

@@ -34,10 +34,5 @@
/// Defaults to Impact.
/// </summary>
public string Fantasy { get; set; }
/// <summary>
/// Defaults to Latin Modern Math.
/// </summary>
public string Math { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
using Newtonsoft.Json;
namespace ElectronNET.API.Entities
{
public sealed class DesktopCapturerSource
{
public string Id { get; set; }
public string Name { get; set; }
public NativeImage Thumbnail { get; set; }
[JsonProperty("display_id")]
public string DisplayId { get; set; }
public NativeImage AppIcon { get; set; }
}
}

View File

@@ -1,9 +1,9 @@
namespace ElectronNET.API.Entities
{
/// <summary>
/// Opens the devtools with specified dock state, can be left, right, bottom, undocked,
/// detach. Defaults to last used dock state. In undocked mode it's possible to dock
/// back. In detach mode it's not.
/// Opens the devtools with specified dock state, can be right, bottom, undocked,
/// detach.Defaults to last used dock state.In undocked mode it's possible to dock
/// back.In detach mode it's not.
/// </summary>
public enum DevToolsMode
{
@@ -25,11 +25,6 @@
/// <summary>
/// The detach
/// </summary>
detach,
/// <summary>
/// The left
/// </summary>
left,
detach
}
}

View File

@@ -0,0 +1,65 @@
namespace ElectronNET.API.Entities
{
public class DisplayChanged
{
public Display display { get; set; }
public string[] metrics { get; set; }
}
/// <summary>
///
/// </summary>
public class Display
{
/// <summary>
/// Gets or sets the bounds.
/// </summary>
/// <value>
/// The bounds.
/// </value>
public Rectangle Bounds { get; set; }
/// <summary>
/// Unique identifier associated with the display.
/// </summary>
public string Id { get; set; }
/// <summary>
/// Can be 0, 90, 180, 270, represents screen rotation in clock-wise degrees.
/// </summary>
public float Rotation { get; set; }
/// <summary>
/// Output device's pixel scale factor.
/// </summary>
public float ScaleFactor { get; set; }
/// <summary>
/// Gets or sets the size.
/// </summary>
/// <value>
/// The size.
/// </value>
public Size Size { get; set; }
/// <summary>
/// Can be available, unavailable, unknown.
/// </summary>
public string TouchSupport { get; set; }
/// <summary>
/// Gets or sets the work area.
/// </summary>
/// <value>
/// The work area.
/// </value>
public Rectangle WorkArea { get; set; }
/// <summary>
/// Gets or sets the size of the work area.
/// </summary>
/// <value>
/// The size of the work area.
/// </value>
public Size WorkAreaSize { get; set; }
}
}

View File

@@ -0,0 +1,32 @@
namespace ElectronNET.API
{
/// <summary>
///
/// </summary>
public class DisplayBalloonOptions
{
/// <summary>
/// Gets or sets the icon.
/// </summary>
/// <value>
/// The icon.
/// </value>
public string Icon { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
/// <value>
/// The title.
/// </value>
public string Title { get; set; }
/// <summary>
/// Gets or sets the content.
/// </summary>
/// <value>
/// The content.
/// </value>
public string Content { get; set; }
}
}

View File

@@ -1,13 +1,10 @@
using System.ComponentModel;
using System.Runtime.Versioning;
namespace ElectronNET.API.Entities
{
/// <summary>
/// Defines the DockBounceType enumeration.
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
[SupportedOSPlatform("macOS")]
public enum DockBounceType
{
/// <summary>

View File

@@ -3,7 +3,6 @@
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class EnableNetworkEmulationOptions
{
/// <summary>
@@ -13,20 +12,17 @@
/// <summary>
/// RTT in ms. Defaults to 0 which will disable latency throttling.
/// Electron documents this as a Number (Double).
/// </summary>
public double Latency { get; set; }
public int Latency { get; set; }
/// <summary>
/// Download rate in Bps. Defaults to 0 which will disable download throttling.
/// Electron documents this as a Number (Double).
/// </summary>
public double DownloadThroughput { get; set; }
public int DownloadThroughput { get; set; }
/// <summary>
/// Upload rate in Bps. Defaults to 0 which will disable upload throttling.
/// Electron documents this as a Number (Double).
/// </summary>
public double UploadThroughput { get; set; }
public int UploadThroughput { get; set; }
}
}
}

View File

@@ -1,9 +1,14 @@
namespace ElectronNET.API.Entities
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ElectronNET.API.Entities
{
/// <summary>
/// Docs: https://electronjs.org/docs/api/structures/extension
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class Extension
{
/// <summary>
@@ -36,4 +41,4 @@
/// </summary>
public string Version { get; set; }
}
}
}

View File

@@ -3,7 +3,6 @@
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class FileFilter
{
/// <summary>

View File

@@ -3,13 +3,14 @@
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class FileIconOptions
{
/// <summary>
/// The requested icon size string passed to app.getFileIcon:
/// "small" (16x16), "normal" (32x32), or "large" (48x48 on Linux, 32x32 on Windows; unsupported on macOS).
/// Gets the size.
/// </summary>
/// <value>
/// The size.
/// </value>
public string Size { get; private set; }
/// <summary>

View File

@@ -0,0 +1,23 @@
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public enum FileIconSize
{
/// <summary>
/// The small
/// </summary>
small,
/// <summary>
/// The normal
/// </summary>
normal,
/// <summary>
/// The large
/// </summary>
large
}
}

View File

@@ -1,18 +1,15 @@
using System.Runtime.Versioning;
namespace ElectronNET.API.Entities
namespace ElectronNET.API.Entities
{
/// <summary>
/// Controls the behavior of <see cref="App.Focus(FocusOptions)"/>.
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class FocusOptions
{
/// <summary>
/// Make the receiver the active app even if another app is currently active.
/// You should seek to use the steal option as sparingly as possible.
/// <para/>
/// You should seek to use the <see cref="Steal"/> option as sparingly as possible.
/// </summary>
[SupportedOSPlatform("macOS")]
public bool Steal { get; set; }
}
}

View File

@@ -0,0 +1,85 @@
using Newtonsoft.Json;
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class GPUFeatureStatus
{
/// <summary>
/// Canvas.
/// </summary>
[JsonProperty("2d_canvas")]
public string Canvas { get; set; }
/// <summary>
/// Flash.
/// </summary>
[JsonProperty("flash_3d")]
public string Flash3D { get; set; }
/// <summary>
/// Flash Stage3D.
/// </summary>
[JsonProperty("flash_stage3d")]
public string FlashStage3D { get; set; }
/// <summary>
/// Flash Stage3D Baseline profile.
/// </summary>
[JsonProperty("flash_stage3d_baseline")]
public string FlashStage3dBaseline { get; set; }
/// <summary>
/// Compositing.
/// </summary>
[JsonProperty("gpu_compositing")]
public string GpuCompositing { get; set; }
/// <summary>
/// Multiple Raster Threads.
/// </summary>
[JsonProperty("multiple_raster_threads")]
public string MultipleRasterThreads { get; set; }
/// <summary>
/// Native GpuMemoryBuffers.
/// </summary>
[JsonProperty("native_gpu_memory_buffers")]
public string NativeGpuMemoryBuffers { get; set; }
/// <summary>
/// Rasterization.
/// </summary>
public string Rasterization { get; set; }
/// <summary>
/// Video Decode.
/// </summary>
[JsonProperty("video_decode")]
public string VideoDecode { get; set; }
/// <summary>
/// Video Encode.
/// </summary>
[JsonProperty("video_encode")]
public string VideoEncode { get; set; }
/// <summary>
/// VPx Video Decode.
/// </summary>
[JsonProperty("vpx_decode")]
public string VpxDecode { get; set; }
/// <summary>
/// WebGL.
/// </summary>
public string Webgl { get; set; }
/// <summary>
/// WebGL2.
/// </summary>
public string Webgl2 { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
namespace ElectronNET.API.Entities
{
/// <summary>
/// Interface to use Electrons PostData Object
/// </summary>
public interface IPostData
{
/// <summary>
/// One of the following:
/// rawData - <see cref="UploadRawData"/> The data is available as a Buffer, in the rawData field.
/// file - <see cref="UploadFile"/> The object represents a file. The filePath, offset, length and modificationTime fields will be used to describe the file.
/// blob - <see cref="Blob"/> The object represents a Blob. The blobUUID field will be used to describe the Blob.
/// </summary>
public string Type { get; }
}
}

View File

@@ -0,0 +1,13 @@
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class ImageOptions
{
/// <summary>
/// Gets or sets the scale factor
/// </summary>
public float ScaleFactor { get; set; } = NativeImage.DefaultScaleFactor;
}
}

View File

@@ -1,22 +1,18 @@
using System.Runtime.Versioning;
namespace ElectronNET.API.Entities
namespace ElectronNET.API.Entities
{
/// <summary>
/// Options for app.importCertificate(options) on Linux.
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
[SupportedOSPlatform("linux")]
public class ImportCertificateOptions
{
/// <summary>
/// Path for the pkcs12 file.
/// </summary>
public string Certificate { get; set; }
/// <summary>
/// Passphrase for the certificate.
/// </summary>
public string Password { get; set; }
public string Password {get; set; }
}
}
}

View File

@@ -0,0 +1,27 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class JumpListCategory
{
/// <summary>
/// Must be set if type is custom, otherwise it should be omitted.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Array of objects if type is tasks or custom, otherwise it should be omitted.
/// </summary>
public JumpListItem[] Items { get; set; }
/// <summary>
/// One of the following: "tasks" | "frequent" | "recent" | "custom"
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public JumpListCategoryType Type { get; set; }
}
}

View File

@@ -1,12 +1,8 @@
using System.Runtime.Versioning;
namespace ElectronNET.API.Entities
namespace ElectronNET.API.Entities
{
/// <summary>
/// Jump list category kinds for app.setJumpList (Windows).
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
[SupportedOSPlatform("Windows")]
public enum JumpListCategoryType
{
/// <summary>

View File

@@ -0,0 +1,58 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class JumpListItem
{
/// <summary>
/// The command line arguments when program is executed. Should only be set if type is task.
/// </summary>
public string Args { get; set; }
/// <summary>
/// Description of the task (displayed in a tooltip). Should only be set if type is task.
/// </summary>
public string Description { get; set; }
/// <summary>
/// The index of the icon in the resource file. If a resource file contains multiple
/// icons this value can be used to specify the zero-based index of the icon that
/// should be displayed for this task.If a resource file contains only one icon,
/// this property should be set to zero.
/// </summary>
public int IconIndex { get; set; }
/// <summary>
/// The absolute path to an icon to be displayed in a Jump List, which can be an
/// arbitrary resource file that contains an icon(e.g. .ico, .exe, .dll). You can
/// usually specify process.execPath to show the program icon.
/// </summary>
public string IconPath { get; set; }
/// <summary>
/// Path of the file to open, should only be set if type is file.
/// </summary>
public string Path { get; set; }
/// <summary>
/// Path of the program to execute, usually you should specify process.execPath
/// which opens the current program.Should only be set if type is task.
/// </summary>
public string Program { get; set; }
/// <summary>
/// The text to be displayed for the item in the Jump List. Should only be set if type is task.
/// </summary>
public string Title { get; set; }
/// <summary>
/// One of the following: "task" | "separator" | "file"
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public JumpListItemType Type { get; set; }
}
}

View File

@@ -1,12 +1,8 @@
using System.Runtime.Versioning;
namespace ElectronNET.API.Entities
namespace ElectronNET.API.Entities
{
/// <summary>
/// Jump list item kinds for app.setJumpList (Windows).
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
[SupportedOSPlatform("Windows")]
public enum JumpListItemType
{
/// <summary>

View File

@@ -0,0 +1,20 @@
using System;
namespace ElectronNET.API.Entities
{
public class JumpListSettings
{
/// <summary>
/// The minimum number of items that will be shown in the Jump List (for a more detailed description of this value see the
/// <see href="https://msdn.microsoft.com/en-us/library/windows/desktop/dd378398(v=vs.85).aspx">MSDN</see> docs).
/// </summary>
public int MinItems { get; set; } = 0;
/// <summary>
/// Array of JumpListItem objects that correspond to items that the user has explicitly removed from custom categories
/// in the Jump List. These items must not be re-added to the Jump List in the next call to <see cref="App.SetJumpList"/>, Windows will
/// not display any custom category that contains any of the removed items.
/// </summary>
public JumpListItem[] RemovedItems { get; set; } = Array.Empty<JumpListItem>();
}
}

View File

@@ -1,14 +1,12 @@
namespace ElectronNET.API.Entities
{
/// <summary>
/// Options for BrowserWindow.loadURL(url, options) / webContents.loadURL(url, options).
/// Matches Electron's loadURL options.
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class LoadURLOptions
{
/// <summary>
/// An HTTP Referrer URL. In Electron this may be a string or a Referrer object.
/// A HTTP Referrer url.
/// </summary>
public string HttpReferrer { get; set; }
@@ -18,18 +16,20 @@
public string UserAgent { get; set; }
/// <summary>
/// Base URL (with trailing path separator) for files to be loaded by the data URL.
/// Needed only if the specified URL is a data URL and needs to load other files.
/// Base url (with trailing path separator) for files to be loaded by the data url.
/// This is needed only if the specified url is a data url and needs to load other
/// files.
/// </summary>
public string BaseURLForDataURL { get; set; }
/// <summary>
/// Extra headers separated by "\n".
/// Extra headers for the request.
/// </summary>
public string ExtraHeaders { get; set; }
/// <summary>
/// Post data for the request. Matches Electron's postData: (UploadRawData | UploadFile)[]
/// PostData Object for the request.
/// Can be <see cref="UploadRawData"/>, <see cref="UploadFile"/> or <see cref="Blob"/>
/// </summary>
public IPostData[] PostData { get; set; }
}

View File

@@ -0,0 +1,39 @@
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class LoginItemSettings
{
/// <summary>
/// <see langword="true"/> if the app is set to open at login.
/// </summary>
public bool OpenAtLogin { get; set; }
/// <summary>
/// <see langword="true"/> if the app is set to open as hidden at login. This setting is not available
/// on <see href="https://www.electronjs.org/docs/tutorial/mac-app-store-submission-guide">MAS builds</see>.
/// </summary>
public bool OpenAsHidden { get; set; }
/// <summary>
/// <see langword="true"/> if the app was opened at login automatically. This setting is not available
/// on <see href="https://www.electronjs.org/docs/tutorial/mac-app-store-submission-guide">MAS builds</see>.
/// </summary>
public bool WasOpenedAtLogin { get; set; }
/// <summary>
/// <see langword="true"/> if the app was opened as a hidden login item. This indicates that the app should not
/// open any windows at startup. This setting is not available on
/// <see href="https://www.electronjs.org/docs/tutorial/mac-app-store-submission-guide">MAS builds</see>.
/// </summary>
public bool WasOpenedAsHidden { get; set; }
/// <summary>
/// <see langword="true"/> if the app was opened as a login item that should restore the state from the previous
/// session. This indicates that the app should restore the windows that were open the last time the app was closed.
/// This setting is not available on <see href="https://www.electronjs.org/docs/tutorial/mac-app-store-submission-guide">MAS builds</see>.
/// </summary>
public bool RestoreState { get; set; }
}
}

View File

@@ -0,0 +1,18 @@
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class LoginItemSettingsOptions
{
/// <summary>
/// The executable path to compare against. Defaults to process.execPath.
/// </summary>
public string Path { get; set; }
/// <summary>
/// The command-line arguments to compare against. Defaults to an empty array.
/// </summary>
public string[] Args { get; set; }
}
}

View File

@@ -0,0 +1,32 @@
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class LoginSettings
{
/// <summary>
/// <see langword="true"/> to open the app at login, <see langword="false"/> to remove the app as a login item.
/// Defaults to <see langword="false"/>.
/// </summary>
public bool OpenAtLogin { get; set; }
/// <summary>
/// <see langword="true"/> to open the app as hidden. Defaults to <see langword="false"/>. The user can edit this
/// setting from the System Preferences so app.getLoginItemSettings().wasOpenedAsHidden should be checked when the app is
/// opened to know the current value. This setting is not available on <see href="https://www.electronjs.org/docs/tutorial/mac-app-store-submission-guide">MAS builds</see>.
/// </summary>
public bool OpenAsHidden { get; set; }
/// <summary>
/// The executable to launch at login. Defaults to process.execPath.
/// </summary>
public string Path { get; set; }
/// <summary>
/// The command-line arguments to pass to the executable. Defaults to an empty
/// array.Take care to wrap paths in quotes.
/// </summary>
public string[] Args { get; set; }
}
}

View File

@@ -0,0 +1,24 @@
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class MemoryInfo
{
/// <summary>
/// The amount of memory currently pinned to actual physical RAM.
/// </summary>
public int WorkingSetSize { get; set; }
/// <summary>
/// The maximum amount of memory that has ever been pinned to actual physical RAM.
/// </summary>
public int PeakWorkingSetSize { get; set; }
/// <summary>
/// The amount of memory not shared by other processes, such as JS heap or HTML
/// content.
/// </summary>
public int PrivateBytes { get; set; }
}
}

View File

@@ -0,0 +1,103 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.ComponentModel;
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class MenuItem
{
/// <summary>
/// Will be called with click(menuItem, browserWindow, event) when the menu item is
/// clicked.
/// </summary>
[JsonIgnore]
public Action Click { get; set; }
/// <summary>
/// Define the action of the menu item, when specified the click property will be
/// ignored.
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public MenuRole Role { get; set; }
/// <summary>
/// Can be normal, separator, submenu, checkbox or radio.
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public MenuType Type { get; set; }
/// <summary>
/// Gets or sets the label.
/// </summary>
/// <value>
/// The label.
/// </value>
public string Label { get; set; }
/// <summary>
/// Gets or sets the sublabel.
/// </summary>
/// <value>
/// The sublabel.
/// </value>
public string Sublabel { get; set; }
/// <summary>
/// Gets or sets the accelerator.
/// </summary>
/// <value>
/// The accelerator.
/// </value>
public string Accelerator { get; set; }
/// <summary>
/// Gets or sets the icon.
/// </summary>
/// <value>
/// The icon.
/// </value>
public string Icon { get; set; }
/// <summary>
/// If false, the menu item will be greyed out and unclickable.
/// </summary>
public bool Enabled { get; set; } = true;
/// <summary>
/// If false, the menu item will be entirely hidden.
/// </summary>
public bool Visible { get; set; } = true;
/// <summary>
/// Should only be specified for checkbox or radio type menu items.
/// </summary>
public bool Checked { get; set; }
/// <summary>
/// Should be specified for submenu type menu items. If submenu is specified, the
/// type: 'submenu' can be omitted.If the value is not a Menu then it will be
/// automatically converted to one using Menu.buildFromTemplate.
/// </summary>
public MenuItem[] Submenu { get; set; }
/// <summary>
/// Unique within a single menu. If defined then it can be used as a reference to
/// this item by the position attribute.
/// </summary>
public string Id { get; internal set; }
/// <summary>
/// This field allows fine-grained definition of the specific location within a
/// given menu.
/// </summary>
public string Position { get; set; }
}
}

View File

@@ -31,14 +31,14 @@
paste,
/// <summary>
/// The pasteAndMatchStyle
/// The pasteandmatchstyle
/// </summary>
pasteAndMatchStyle,
pasteandmatchstyle,
/// <summary>
/// The selectAll
/// The selectall
/// </summary>
selectAll,
selectall,
/// <summary>
/// The delete
@@ -68,12 +68,12 @@
/// <summary>
/// Reload the current window ignoring the cache.
/// </summary>
forceReload,
forcereload,
/// <summary>
/// Toggle developer tools in the current window
/// </summary>
toggleDevTools,
toggledevtools,
/// <summary>
/// Toggle full screen mode on the current window
@@ -83,17 +83,17 @@
/// <summary>
/// Reset the focused pages zoom level to the original size
/// </summary>
resetZoom,
resetzoom,
/// <summary>
/// Zoom in the focused page by 10%
/// </summary>
zoomIn,
zoomin,
/// <summary>
/// Zoom out the focused page by 10%
/// </summary>
zoomOut,
zoomout,
/// <summary>
/// Whole default “Edit” menu (Undo, Copy, etc.)
@@ -118,7 +118,7 @@
/// <summary>
/// Only macOS: Map to the hideOtherApplications action
/// </summary>
hideOthers,
hideothers,
/// <summary>
/// Only macOS: Map to the unhideAllApplications action
@@ -128,12 +128,12 @@
/// <summary>
/// Only macOS: Map to the startSpeaking action
/// </summary>
startSpeaking,
startspeaking,
/// <summary>
/// Only macOS: Map to the stopSpeaking action
/// </summary>
stopSpeaking,
stopspeaking,
/// <summary>
/// Only macOS: Map to the arrangeInFront action
@@ -159,107 +159,16 @@
/// Only macOS: The submenu is a “Services” menu
/// </summary>
services,
/// <summary>
/// Toggle built-in spellchecker.
/// Only macOS: the submenue for "Recent Documents"
/// </summary>
toggleSpellChecker,
recentdocuments,
/// <summary>
/// The submenu is a "File" menu.
/// Only macOS: the menu to clear the recent document list
/// </summary>
fileMenu,
/// <summary>
/// The submenu is a "View" menu.
/// </summary>
viewMenu,
/// <summary>
/// The application menu.
/// </summary>
appMenu,
/// <summary>
/// The submenu is a "Share" menu.
/// </summary>
shareMenu,
/// <summary>
/// Displays a list of files recently opened by the app.
/// </summary>
recentDocuments,
/// <summary>
/// Clear the recent documents list.
/// </summary>
clearRecentDocuments,
/// <summary>
/// Toggle the tab bar (macOS).
/// </summary>
toggleTabBar,
/// <summary>
/// Select the next tab (macOS).
/// </summary>
selectNextTab,
/// <summary>
/// Select the previous tab (macOS).
/// </summary>
selectPreviousTab,
/// <summary>
/// Show all tabs (macOS).
/// </summary>
showAllTabs,
/// <summary>
/// Merge all windows (macOS).
/// </summary>
mergeAllWindows,
/// <summary>
/// Move the current tab to a new window (macOS).
/// </summary>
moveTabToNewWindow,
/// <summary>
/// Show substitutions panel (macOS).
/// </summary>
showSubstitutions,
/// <summary>
/// Toggle smart quotes (macOS).
/// </summary>
toggleSmartQuotes,
/// <summary>
/// Toggle smart dashes (macOS).
/// </summary>
toggleSmartDashes,
/// <summary>
/// Toggle text replacement (macOS).
/// </summary>
toggleTextReplacement,
// Backwards-compatibility aliases (old identifiers) to avoid breaking existing code.
// These map to the same enum values as their official values.
pasteandmatchstyle = pasteAndMatchStyle,
selectall = selectAll,
forcereload = forceReload,
toggledevtools = toggleDevTools,
resetzoom = resetZoom,
zoomin = zoomIn,
zoomout = zoomOut,
hideothers = hideOthers,
startspeaking = startSpeaking,
stopspeaking = stopSpeaking,
togglespellchecker = toggleSpellChecker,
togglesmartquotes = toggleSmartQuotes,
togglesmartdashes = toggleSmartDashes,
toggletextreplacement = toggleTextReplacement
clearrecentdocuments,
}
}

View File

@@ -0,0 +1,33 @@
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public enum MenuType
{
/// <summary>
/// The normal
/// </summary>
normal,
/// <summary>
/// The separator
/// </summary>
separator,
/// <summary>
/// The submenu
/// </summary>
submenu,
/// <summary>
/// The checkbox
/// </summary>
checkbox,
/// <summary>
/// The radio
/// </summary>
radio
}
}

View File

@@ -0,0 +1,101 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class MessageBoxOptions
{
/// <summary>
/// Can be "none", "info", "error", "question" or "warning". On Windows, "question"
/// displays the same icon as "info", unless you set an icon using the "icon"
/// option. On macOS, both "warning" and "error" display the same warning icon.
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public MessageBoxType Type { get; set; }
/// <summary>
/// Array of texts for buttons. On Windows, an empty array will result in one button
/// labeled "OK".
/// </summary>
public string[] Buttons { get; set; }
/// <summary>
/// Index of the button in the buttons array which will be selected by default when
/// the message box opens.
/// </summary>
public int DefaultId { get; set; }
/// <summary>
/// Title of the message box, some platforms will not show it.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Content of the message box.
/// </summary>
public string Message { get; set; }
/// <summary>
/// Extra information of the message.
/// </summary>
public string Detail { get; set; }
/// <summary>
/// If provided, the message box will include a checkbox with the given label. The
/// checkbox state can be inspected only when using callback.
/// </summary>
public string CheckboxLabel { get; set; }
/// <summary>
/// Initial checked state of the checkbox. false by default.
/// </summary>
public bool CheckboxChecked { get; set; }
/// <summary>
/// Gets or sets the icon.
/// </summary>
/// <value>
/// The icon.
/// </value>
public string Icon { get; set; }
/// <summary>
/// The index of the button to be used to cancel the dialog, via the Esc key. By
/// default this is assigned to the first button with "cancel" or "no" as the label.
/// If no such labeled buttons exist and this option is not set, 0 will be used as
/// the return value or callback response. This option is ignored on Windows.
/// </summary>
public int CancelId { get; set; }
/// <summary>
/// On Windows Electron will try to figure out which one of the buttons are common
/// buttons(like "Cancel" or "Yes"), and show the others as command links in the
/// dialog.This can make the dialog appear in the style of modern Windows apps. If
/// you don't like this behavior, you can set noLink to true.
/// </summary>
public bool NoLink { get; set; }
/// <summary>
/// Normalize the keyboard access keys across platforms. Default is false. Enabling
/// this assumes AND character is used in the button labels for the placement of the keyboard
/// shortcut access key and labels will be converted so they work correctly on each
/// platform, AND characters are removed on macOS, converted to _ on Linux, and left
/// untouched on Windows.For example, a button label of VieANDw will be converted to
/// Vie_w on Linux and View on macOS and can be selected via Alt-W on Windows and
/// Linux.
/// </summary>
public bool NormalizeAccessKeys { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="MessageBoxOptions"/> class.
/// </summary>
/// <param name="message">The message.</param>
public MessageBoxOptions(string message)
{
Message = message;
}
}
}

View File

@@ -0,0 +1,30 @@
namespace ElectronNET.API.Entities
{
internal class MessageBoxResponse
{
public int response { get; set; }
public bool @checked { get; set; }
}
/// <summary>
///
/// </summary>
public class MessageBoxResult
{
/// <summary>
/// Gets or sets the response.
/// </summary>
/// <value>
/// The response.
/// </value>
public int Response { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [checkbox checked].
/// </summary>
/// <value>
/// <c>true</c> if [checkbox checked]; otherwise, <c>false</c>.
/// </value>
public bool CheckboxChecked { get; set; }
}
}

View File

@@ -1,9 +1,8 @@
namespace ElectronNET.API.Entities
{
/// <summary>
/// Message box type for dialog.showMessageBox/showMessageBoxSync.
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public enum MessageBoxType
{
/// <summary>

View File

@@ -1,13 +1,15 @@
using System;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Processing;
using System.IO;
using System.Linq;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using System.Runtime.Versioning;
using Newtonsoft.Json;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Processing;
namespace ElectronNET.API.Entities
{
@@ -17,14 +19,19 @@ namespace ElectronNET.API.Entities
[JsonConverter(typeof(NativeImageJsonConverter))]
public class NativeImage
{
/// <summary>
///
/// </summary>
public const float DefaultScaleFactor = 1.0f;
private readonly Dictionary<float, Image> _images = new Dictionary<float, Image>();
private bool _isTemplateImage;
private static readonly Dictionary<string, float> ScaleFactorPairs = new Dictionary<string, float>
private static readonly Dictionary<string, float> ScaleFactorPairs = new()
{
{ "@2x", 2.0f }, { "@3x", 3.0f }, { "@1x", 1.0f }, { "@4x", 4.0f },
{ "@5x", 5.0f }, { "@1.25x", 1.25f }, { "@1.33x", 1.33f }, { "@1.4x", 1.4f },
{ "@1.5x", 1.5f }, { "@1.8x", 1.8f }, { "@2.5x", 2.5f }
{"@2x", 2.0f}, {"@3x", 3.0f}, {"@1x", 1.0f}, {"@4x", 4.0f},
{"@5x", 5.0f}, {"@1.25x", 1.25f}, {"@1.33x", 1.33f}, {"@1.4x", 1.4f},
{"@1.5x", 1.5f}, {"@1.8x", 1.8f}, {"@2.5x", 2.5f}
};
private static float? ExtractDpiFromFilePath(string filePath)
@@ -35,11 +42,9 @@ namespace ElectronNET.API.Entities
.Select(p => p.Value)
.FirstOrDefault();
}
private static Image BytesToImage(byte[] bytes)
{
var ms = new MemoryStream(bytes);
return Image.FromStream(ms);
return Image.Load(new MemoryStream(bytes));
}
/// <summary>
@@ -53,30 +58,35 @@ namespace ElectronNET.API.Entities
/// <summary>
///
/// </summary>
public static NativeImage CreateFromBitmap(Bitmap bitmap, CreateFromBitmapOptions options = null)
public static NativeImage CreateFromImage(Image image, CreateFromBitmapOptions options = null)
{
if (options is null)
{
options = new CreateFromBitmapOptions();
}
return new NativeImage(bitmap, options.ScaleFactor);
return new NativeImage(image, options.ScaleFactor);
}
/// <summary>
///
/// </summary>
public static NativeImage CreateFromImage(Image image, CreateOptions options = null)
=> new (image, options?.ScaleFactor ?? DefaultScaleFactor);
/// <summary>
/// Creates a NativeImage from a byte array.
/// </summary>
public static NativeImage CreateFromBuffer(byte[] buffer, CreateFromBufferOptions options = null)
public static NativeImage CreateFromBuffer(byte[] buffer, CreateOptions options = null)
{
if (options is null)
{
options = new CreateFromBufferOptions();
}
var ms = new MemoryStream(buffer);
var image = Image.FromStream(ms);
var image = Image.Load(new MemoryStream(buffer));
return new NativeImage(image, options.ScaleFactor);
return new NativeImage(image, options?.ScaleFactor ?? DefaultScaleFactor);
}
/// <summary>
@@ -85,7 +95,7 @@ namespace ElectronNET.API.Entities
/// <param name="dataUrl">A data URL with a base64 encoded image.</param>
public static NativeImage CreateFromDataURL(string dataUrl)
{
var images = new Dictionary<float, Image>();
var images = new Dictionary<float,Image>();
var parsedDataUrl = Regex.Match(dataUrl, @"data:image/(?<type>.+?),(?<data>.+)");
var actualData = parsedDataUrl.Groups["data"].Value;
var binData = Convert.FromBase64String(actualData);
@@ -103,7 +113,7 @@ namespace ElectronNET.API.Entities
/// <param name="path">The path of the image</param>
public static NativeImage CreateFromPath(string path)
{
var images = new Dictionary<float, Image>();
var images = new Dictionary<float,Image>();
if (Regex.IsMatch(path, "(@.+?x)"))
{
var dpi = ExtractDpiFromFilePath(path);
@@ -112,14 +122,14 @@ namespace ElectronNET.API.Entities
throw new Exception($"Invalid scaling factor for '{path}'.");
}
images[dpi.Value] = Image.FromFile(path);
images[dpi.Value] = Image.Load(path);
}
else
{
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);
var extension = Path.GetExtension(path);
// Load as 1x dpi
images[1.0f] = Image.FromFile(path);
images[1.0f] = Image.Load(path);
foreach (var scale in ScaleFactorPairs)
{
@@ -129,7 +139,7 @@ namespace ElectronNET.API.Entities
var dpi = ExtractDpiFromFilePath(fileName);
if (dpi != null)
{
images[dpi.Value] = Image.FromFile(fileName);
images[dpi.Value] = Image.Load(fileName);
}
}
}
@@ -148,9 +158,9 @@ namespace ElectronNET.API.Entities
/// <summary>
/// Creates a NativeImage from a bitmap and scale factor
/// </summary>
public NativeImage(Image bitmap, float scaleFactor = 1.0f)
public NativeImage(Image image, float scaleFactor = DefaultScaleFactor)
{
_images.Add(scaleFactor, bitmap);
_images.Add(scaleFactor, image);
}
/// <summary>
@@ -198,7 +208,7 @@ namespace ElectronNET.API.Entities
if (options.Buffer.Length > 0)
{
_images[options.ScaleFactor] =
CreateFromBuffer(options.Buffer, new CreateFromBufferOptions { ScaleFactor = options.ScaleFactor })
CreateFromBuffer(options.Buffer, new CreateOptions {ScaleFactor = options.ScaleFactor})
.GetScale(options.ScaleFactor);
}
else if (!string.IsNullOrEmpty(options.DataUrl))
@@ -216,7 +226,7 @@ namespace ElectronNET.API.Entities
var image = GetScale(scaleFactor);
if (image != null)
{
return image.Width / image.Height;
return (float)image.Width / image.Height;
}
return 0f;
@@ -225,9 +235,9 @@ namespace ElectronNET.API.Entities
/// <summary>
/// Returns a byte array that contains the image's raw bitmap pixel data.
/// </summary>
public byte[] GetBitmap(BitmapOptions options)
public byte[] GetBitmap(float scaleFactor)
{
return ToBitmap(new ToBitmapOptions { ScaleFactor = options.ScaleFactor });
return ToBitmap(scaleFactor).ToArray();
}
/// <summary>
@@ -235,26 +245,14 @@ namespace ElectronNET.API.Entities
/// </summary>
public byte[] GetNativeHandle()
{
return ToBitmap(new ToBitmapOptions());
return ToBitmap().ToArray();
}
/// <summary>
/// Gets the size of the specified image based on scale factor
/// </summary>
public Size GetSize(float scaleFactor = 1.0f)
{
if (_images.ContainsKey(scaleFactor))
{
var image = _images[scaleFactor];
return new Size
{
Width = image.Width,
Height = image.Height
};
}
return null;
}
=> _images.TryGetValue(scaleFactor, out var image) ? image.Size() : null;
/// <summary>
/// Checks to see if the NativeImage instance is empty.
@@ -269,12 +267,6 @@ namespace ElectronNET.API.Entities
/// </summary>
public bool IsTemplateImage => _isTemplateImage;
/// <summary>
/// Whether the image is considered a macOS template image.
/// </summary>
[SupportedOSPlatform("macos")]
public bool IsMacTemplateImage => _isTemplateImage;
/// <summary>
/// Deprecated. Marks the image as a template image.
/// </summary>
@@ -286,177 +278,127 @@ namespace ElectronNET.API.Entities
/// <summary>
/// Outputs a bitmap based on the scale factor
/// </summary>
public byte[] ToBitmap(ToBitmapOptions options)
public MemoryStream ToBitmap(float scaleFactor = 1.0f)
{
return ImageToBytes(ImageFormat.Bmp, options.ScaleFactor);
var ms = new MemoryStream();
_images[scaleFactor].SaveAsBmp(ms);
return ms;
}
/// <summary>
/// Outputs a data URL based on the scale factor
/// Outputs a PNG based on the scale factor
/// </summary>
public string ToDataURL(ToDataUrlOptions options)
public string ToDataURL(ImageOptions options)
=> _images.TryGetValue(options.ScaleFactor, out var image)
? $"data:image/png;base64,{image.ToBase64String(PngFormat.Instance)}"
: null;
public MemoryStream ToPng(float scaleFactor = 1.0f)
{
if (!_images.ContainsKey(options.ScaleFactor))
{
return null;
}
var image = _images[options.ScaleFactor];
var mimeType = ImageCodecInfo.GetImageEncoders().FirstOrDefault(x => x.FormatID == image.RawFormat.Guid)?.MimeType;
if (mimeType is null)
{
mimeType = "image/png";
}
var bytes = ImageToBytes(image.RawFormat, options.ScaleFactor);
var base64 = Convert.ToBase64String(bytes);
return $"data:{mimeType};base64,{base64}";
var ms = new MemoryStream();
_images[scaleFactor].SaveAsPng(ms);
return ms;
}
/// <summary>
/// Outputs a JPEG for the default scale factor
/// </summary>
public byte[] ToJPEG(int quality)
public MemoryStream ToJpeg(int quality, float scaleFactor = 1.0f)
{
return ImageToBytes(ImageFormat.Jpeg, 1.0f, quality);
var ms = new MemoryStream();
_images[scaleFactor].SaveAsJpeg(ms, new SixLabors.ImageSharp.Formats.Jpeg.JpegEncoder() { Quality = quality });
return ms;
}
/// <summary>
/// Outputs a PNG for the specified scale factor
/// Outputs a data URL based on the scale factor
/// </summary>
public byte[] ToPNG(ToPNGOptions options)
public string ToDataURL(float scaleFactor = 1.0f)
{
return ImageToBytes(ImageFormat.Png, options.ScaleFactor);
}
private byte[] ImageToBytes(ImageFormat imageFormat = null, float scaleFactor = 1.0f, int quality = 100)
{
using var ms = new MemoryStream();
if (_images.ContainsKey(scaleFactor))
if (!_images.TryGetValue(scaleFactor, out var image))
{
var image = _images[scaleFactor];
var encoderCodecInfo = GetEncoder(imageFormat ?? image.RawFormat);
var encoder = Encoder.Quality;
var encoderParameters = new EncoderParameters(1)
{
Param = new[]
{
new EncoderParameter(encoder, quality)
}
};
image.Save(ms, encoderCodecInfo, encoderParameters);
return ms.ToArray();
throw new KeyNotFoundException($"Missing scaleFactor = {scaleFactor}");
}
return null;
return image.ToBase64String(PngFormat.Instance);
}
private Image Resize(int? width, int? height, float scaleFactor = 1.0f)
{
if (!_images.ContainsKey(scaleFactor) || (width is null && height is null))
if (!_images.TryGetValue(scaleFactor, out var image) || (width is null && height is null))
{
return null;
throw new KeyNotFoundException($"Missing scaleFactor = {scaleFactor}");
}
if (width is null && height is null)
{
throw new ArgumentNullException("Missing width or height");
}
var image = _images[scaleFactor];
using (var g = Graphics.FromImage(image))
var aspect = GetAspectRatio(scaleFactor);
width ??= Convert.ToInt32(image.Width * aspect);
height ??= Convert.ToInt32(image.Height * aspect);
width = Convert.ToInt32(width * scaleFactor);
height = Convert.ToInt32(height * scaleFactor);
return image.Clone(c => c.Resize(new SixLabors.ImageSharp.Processing.ResizeOptions
{
g.CompositingQuality = CompositingQuality.HighQuality;
var aspect = GetAspectRatio(scaleFactor);
width ??= Convert.ToInt32(image.Width * aspect);
height ??= Convert.ToInt32(image.Height * aspect);
width = Convert.ToInt32(width * scaleFactor);
height = Convert.ToInt32(height * scaleFactor);
var bmp = new Bitmap(width.Value, height.Value);
g.DrawImage(bmp,
new System.Drawing.Rectangle(0, 0, image.Width, image.Height),
new System.Drawing.Rectangle(0, 0, bmp.Width, bmp.Height),
GraphicsUnit.Pixel);
return bmp;
}
Size = new(width.Value, height.Value),
Sampler = KnownResamplers.Triangle,
}));
}
private Image Crop(int? x, int? y, int? width, int? height, float scaleFactor = 1.0f)
{
if (!_images.ContainsKey(scaleFactor))
{
return null;
}
var image = _images[scaleFactor];
using (var g = Graphics.FromImage(image))
if (!_images.TryGetValue(scaleFactor, out image))
{
g.CompositingQuality = CompositingQuality.HighQuality;
x ??= 0;
y ??= 0;
x = Convert.ToInt32(x * scaleFactor);
y = Convert.ToInt32(y * scaleFactor);
width ??= image.Width;
height ??= image.Height;
width = Convert.ToInt32(width * scaleFactor);
height = Convert.ToInt32(height * scaleFactor);
var bmp = new Bitmap(width.Value, height.Value);
g.DrawImage(bmp, new System.Drawing.Rectangle(0, 0, image.Width, image.Height), new System.Drawing.Rectangle(x.Value, y.Value, width.Value, height.Value), GraphicsUnit.Pixel);
return bmp;
throw new KeyNotFoundException($"Missing scaleFactor = {scaleFactor}");
}
x ??= 0;
y ??= 0;
x = Convert.ToInt32(x * scaleFactor);
y = Convert.ToInt32(y * scaleFactor);
width ??= image.Width;
height ??= image.Height;
width = Convert.ToInt32(width * scaleFactor);
height = Convert.ToInt32(height * scaleFactor);
return image.Clone(c => c.Crop(new SixLabors.ImageSharp.Rectangle(x.Value, y.Value, width.Value, height.Value)));
}
private ImageCodecInfo GetEncoder(ImageFormat format)
internal Dictionary<float,string> GetAllScaledImages()
{
var codecs = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
return null;
}
internal Dictionary<float, string> GetAllScaledImages()
{
var dict = new Dictionary<float, string>();
var dict = new Dictionary<float,string>();
try
{
foreach (var (scale, image) in _images)
{
dict.Add(scale, Convert.ToBase64String(ImageToBytes(null, scale)));
dict.Add(scale, image.ToBase64String(PngFormat.Instance));
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
BridgeConnector.LogError(ex, "Error getting scaled images");
}
return dict;
}
internal Image GetScale(float scaleFactor)
{
if (_images.ContainsKey(scaleFactor))
if (_images.TryGetValue(scaleFactor, out var image))
{
return _images[scaleFactor];
return image;
}
return null;
}
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Processing;
using System.IO;
using Newtonsoft.Json;
using SixLabors.ImageSharp;
namespace ElectronNET.API.Entities
{
internal class NativeImageJsonConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
if (value is NativeImage nativeImage)
{
var scaledImages = nativeImage.GetAllScaledImages();
serializer.Serialize(writer, scaledImages);
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var dict = serializer.Deserialize<Dictionary<string, string>>(reader);
var newDictionary = new Dictionary<float, Image>();
foreach (var item in dict)
{
if (float.TryParse(item.Key, out var size))
{
var bytes = Convert.FromBase64String(item.Value);
newDictionary.Add(size, Image.Load(new MemoryStream(bytes)));
}
}
return new NativeImage(newDictionary);
}
public override bool CanConvert(Type objectType) => objectType == typeof(NativeImage);
}
}

View File

@@ -5,17 +5,16 @@ namespace ElectronNET.API.Entities
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
[SupportedOSPlatform("macos")]
public class NotificationAction
{
/// <summary>
/// Gets or sets the label for the action.
/// The label for the given action.
/// </summary>
public string Text { get; set; }
/// <summary>
/// Gets or sets the type of action; can be 'button'.
/// The type of action, can be button.
/// </summary>
public string Type { get; set; }
}

View File

@@ -1,91 +1,88 @@
using Newtonsoft.Json;
using System;
using System.Runtime.Versioning;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class NotificationOptions
{
/// <summary>
/// Gets or sets the title for the notification, which will be shown at the top of the notification window when it is shown.
/// A title for the notification, which will be shown at the top of the notification
/// window when it is shown.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Gets or sets the subtitle for the notification, which will be displayed below the title.
/// A subtitle for the notification, which will be displayed below the title.
/// </summary>
[SupportedOSPlatform("macos")]
[JsonPropertyName("subtitle")]
public string Subtitle { get; set; }
public string SubTitle { get; set; }
/// <summary>
/// Gets or sets the body text of the notification, which will be displayed below the title or subtitle.
/// The body text of the notification, which will be displayed below the title or
/// subtitle.
/// </summary>
public string Body { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to suppress the OS notification noise when showing the notification.
/// Whether or not to emit an OS notification noise when showing the notification.
/// </summary>
public bool Silent { get; set; }
/// <summary>
/// Gets or sets an icon to use in the notification. Can be a string path or a NativeImage. If a string is passed, it must be a valid path to a local icon file.
/// An icon to use in the notification.
/// </summary>
public string Icon { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to add an inline reply option to the notification.
/// Whether or not to add an inline reply option to the notification.
/// </summary>
[SupportedOSPlatform("macos")]
[SupportedOSPlatform("macos")]
public bool HasReply { get; set; }
/// <summary>
/// Gets or sets the timeout duration of the notification. Can be 'default' or 'never'.
/// The timeout duration of the notification. Can be 'default' or 'never'.
/// </summary>
[SupportedOSPlatform("linux")]
[SupportedOSPlatform("windows")]
[SupportedOSPlatform("linux")]
public string TimeoutType { get; set; }
/// <summary>
/// Gets or sets the placeholder to write in the inline reply input field.
/// The placeholder to write in the inline reply input field.
/// </summary>
[SupportedOSPlatform("macos")]
[SupportedOSPlatform("macos")]
public string ReplyPlaceholder { get; set; }
/// <summary>
/// Gets or sets the name of the sound file to play when the notification is shown.
/// The name of the sound file to play when the notification is shown.
/// </summary>
[SupportedOSPlatform("macos")]
[SupportedOSPlatform("macos")]
public string Sound { get; set; }
/// <summary>
/// Gets or sets the urgency level of the notification. Can be 'normal', 'critical', or 'low'.
/// The urgency level of the notification. Can be 'normal', 'critical', or 'low'.
/// </summary>
[SupportedOSPlatform("linux")]
[SupportedOSPlatform("linux")]
public string Urgency { get; set; }
/// <summary>
/// Gets or sets the actions to add to the notification. Please read the available actions and limitations in the NotificationAction documentation.
/// Actions to add to the notification. Please read the available actions and
/// limitations in the NotificationAction documentation.
/// </summary>
[SupportedOSPlatform("macos")]
public NotificationAction[] Actions { get; set; }
public NotificationAction Actions { get; set; }
/// <summary>
/// Gets or sets a custom title for the close button of an alert. An empty string will cause the default localized text to be used.
/// A custom title for the close button of an alert. An empty string will cause the
/// default localized text to be used.
/// </summary>
[SupportedOSPlatform("macos")]
[SupportedOSPlatform("macos")]
public string CloseButtonText { get; set; }
/// <summary>
/// Gets or sets a custom description of the Notification on Windows superseding all properties above. Provides full customization of design and behavior of the notification.
/// </summary>
[SupportedOSPlatform("windows")]
public string ToastXml { get; set; }
/// <summary>
/// Emitted when the notification is shown to the user, note this could be fired
/// multiple times as a notification can be shown multiple times through the Show()
@@ -100,7 +97,7 @@ namespace ElectronNET.API.Entities
/// <value>
/// The show identifier.
/// </value>
[JsonInclude]
[JsonProperty]
internal string ShowID { get; set; }
/// <summary>
@@ -115,7 +112,7 @@ namespace ElectronNET.API.Entities
/// <value>
/// The click identifier.
/// </value>
[JsonInclude]
[JsonProperty]
internal string ClickID { get; set; }
/// <summary>
@@ -132,7 +129,7 @@ namespace ElectronNET.API.Entities
/// <value>
/// The close identifier.
/// </value>
[JsonInclude]
[JsonProperty]
internal string CloseID { get; set; }
/// <summary>
@@ -150,15 +147,15 @@ namespace ElectronNET.API.Entities
/// <value>
/// The reply identifier.
/// </value>
[JsonInclude]
[JsonProperty]
internal string ReplyID { get; set; }
/// <summary>
/// macOS only - The index of the action that was activated.
/// macOS only - The index of the action that was activated
/// </summary>
[JsonIgnore]
[SupportedOSPlatform("macos")]
public Action<int> OnAction { get; set; }
public Action<string> OnAction { get; set; }
/// <summary>
/// Gets or sets the action identifier.
@@ -166,17 +163,9 @@ namespace ElectronNET.API.Entities
/// <value>
/// The action identifier.
/// </value>
[JsonInclude]
[JsonProperty]
internal string ActionID { get; set; }
/// <summary>
/// Windows only: Emitted when an error is encountered while creating and showing the native notification.
/// Corresponds to the 'failed' event on Notification.
/// </summary>
[JsonIgnore]
[SupportedOSPlatform("windows")]
public Action<string> OnFailed { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="NotificationOptions"/> class.
/// </summary>

View File

@@ -1,14 +1,10 @@
using System.ComponentModel;
using System.Runtime.Versioning;
namespace ElectronNET.API.Entities
{
/// <summary>
/// String values for the 'level' parameter of BrowserWindow.setAlwaysOnTop.
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
[SupportedOSPlatform("macOS")]
[SupportedOSPlatform("Windows")]
public enum OnTopLevel
{
/// <summary>

View File

@@ -0,0 +1,19 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class OpenDevToolsOptions
{
/// <summary>
/// Opens the devtools with specified dock state, can be right, bottom, undocked,
/// detach.Defaults to last used dock state.In undocked mode it's possible to dock
/// back.In detach mode it's not.
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public DevToolsMode Mode { get; set; }
}
}

View File

@@ -1,13 +1,12 @@
using System.Text.Json.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Runtime.Versioning;
namespace ElectronNET.API.Entities
{
using System.Runtime.Versioning;
/// <summary>
///
/// </summary>
/// <remarks>Up-to-date with Electron API 39.2</remarks>
public class OpenDialogOptions
{
/// <summary>
@@ -32,19 +31,20 @@ namespace ElectronNET.API.Entities
public string ButtonLabel { get; set; }
/// <summary>
/// Gets or sets which features the dialog should use. The following values are supported:
/// Contains which features the dialog should use. The following values are supported:
/// 'openFile' | 'openDirectory' | 'multiSelections' | 'showHiddenFiles' | 'createDirectory' | 'promptToCreate' | 'noResolveAliases' | 'treatPackageAsDirectory'
/// </summary>
[JsonProperty("properties", ItemConverterType = typeof(StringEnumConverter))]
public OpenDialogProperty[] Properties { get; set; }
/// <summary>
/// Gets or sets the message to display above input boxes.
/// Message to display above input boxes.
/// </summary>
[SupportedOSPlatform("macos")]
public string Message { get; set; }
/// <summary>
/// Gets or sets the filters specifying an array of file types that can be displayed or
/// The filters specifies an array of file types that can be displayed or
/// selected when you want to limit the user to a specific type. For example:
/// </summary>
/// <example>
@@ -59,11 +59,5 @@ namespace ElectronNET.API.Entities
/// </code>
/// </example>
public FileFilter[] Filters { get; set; }
/// <summary>
/// Create security scoped bookmarks when packaged for the Mac App Store.
/// </summary>
[SupportedOSPlatform("macos")]
public bool SecurityScopedBookmarks { get; set; }
}
}

View File

@@ -0,0 +1,95 @@
using System.Runtime.Versioning;
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public enum OpenDialogProperty
{
/// <summary>
/// The open file
/// </summary>
openFile,
/// <summary>
/// The open directory
/// </summary>
openDirectory,
/// <summary>
/// The multi selections
/// </summary>
multiSelections,
/// <summary>
/// The show hidden files
/// </summary>
showHiddenFiles,
/// <summary>
/// The create directory
/// </summary>
[SupportedOSPlatform("macos")]
createDirectory,
/// <summary>
/// The prompt to create
/// </summary>
[SupportedOSPlatform("windows")]
promptToCreate,
/// <summary>
/// The no resolve aliases
/// </summary>
[SupportedOSPlatform("macos")]
noResolveAliases,
/// <summary>
/// Treat packages, such as .app folders, as a directory instead of a file.
/// </summary>
[SupportedOSPlatform("macos")]
treatPackageAsDirectory,
/// <summary>
/// Don't add the item being opened to recent documents list
/// </summary>
[SupportedOSPlatform("windows")]
dontAddToRecent
}
/// <summary>
///
/// </summary>
public enum SaveDialogProperty
{
/// <summary>
/// The show hidden files
/// </summary>
showHiddenFiles,
/// <summary>
/// The create directory
/// </summary>
[SupportedOSPlatform("macos")]
createDirectory,
/// <summary>
/// Treat packages, such as .app folders, as a directory instead of a file.
/// </summary>
[SupportedOSPlatform("macos")]
treatPackageAsDirectory,
/// <summary>
/// Sets whether the user will be presented a confirmation dialog if the user types a file name that already exists.
/// </summary>
[SupportedOSPlatform("linux")]
showOverwriteConfirmation,
/// <summary>
/// Don't add the item being opened to recent documents list
/// </summary>
[SupportedOSPlatform("windows")]
dontAddToRecent
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.ComponentModel;
using System.Runtime.Versioning;
namespace ElectronNET.API.Entities
{
/// <summary>
/// Controls the behavior of OpenExternal.
/// </summary>
public class OpenExternalOptions
{
/// <summary>
/// <see langword="true"/> to bring the opened application to the foreground. The default is <see langword="true"/>.
/// </summary>
[DefaultValue(true)]
[SupportedOSPlatform("macos")]
public bool Activate { get; set; } = true;
/// <summary>
/// The working directory.
/// </summary>
[SupportedOSPlatform("windows")]
public string WorkingDirectory { get; set; }
}
}

Some files were not shown because too many files have changed in this diff Show More