Compare commits

...

51 Commits

Author SHA1 Message Date
Florian Rappl
5b0ab76d38 Disable Linux for now 2025-11-14 09:55:30 +01:00
Florian Rappl
349762bd5e Updated changelog 2025-11-14 09:46:01 +01:00
Florian Rappl
0b49467186 Merge pull request #924 from agracio/event-task-rework
ApiEventManager Rework and refactoring of task calls
2025-11-13 14:30:31 +01:00
agracio
6fa65aa149 adding block statements to if 2025-11-12 20:20:13 +00:00
agracio
816e9c0fe9 increasing test timeout times 2025-11-12 15:56:36 +00:00
agracio
c81b0e537f increasing test timeout times 2025-11-12 15:40:04 +00:00
agracio
b89e3caa17 Merge branch 'event-task-rework' of https://github.com/agracio/Electron.NET into event-task-rework 2025-11-12 15:32:33 +00:00
agracio
e8c5de63c9 reverting Linux CI changes, skipping printer test in CI 2025-11-12 15:32:17 +00:00
agracio
d7b9174853 Merge branch 'develop' into event-task-rework 2025-11-12 15:09:44 +00:00
agracio
5ba4ab24d5 adding virtual env instructions for Linux CI 2025-11-12 15:06:14 +00:00
agracio
c6ff957d9a rebase from develop, add timeouts to tests and attempt to skip NativeImageTests on Linux 2025-11-12 14:42:43 +00:00
Florian Rappl
c37f98dcd6 Added the test logger 2025-11-12 14:27:30 +01:00
Florian Rappl
0188051d6c Updated NUKE and integrated tests in CI/CD 2025-11-12 14:21:11 +01:00
Florian Rappl
3eb8507985 Updated to target .NET 10 as well 2025-11-12 13:48:03 +01:00
agracio
546668a2c0 refactoring events API, replacing task code with calls to ApiBase. 2025-11-12 10:43:32 +00:00
Florian Rappl
68feffba02 Merge pull request #922 from softworkz/submit_fix_ipc_params
Fix sendToIpcRenderer parameter handling
2025-11-12 01:30:35 +01:00
softworkz
12d2fcb484 Fix sendToIpcRenderer parameter handling 2025-11-11 23:46:56 +01:00
Florian Rappl
979cf72d4c Merge pull request #920 from Denny09310/feature/using-once
feat: Add "Once" socket listener registration for one-time handlers
2025-11-10 22:29:01 +01:00
Florian Rappl
14bf7fdcd8 Merge pull request #921 from softworkz/submit_missing_locks
SocketIOFacade: Add missing locking on .Off calls
2025-11-10 22:27:02 +01:00
softworkz
f89f2e7591 SocketIOFacade: Add missing locking on .Off calls 2025-11-10 21:29:16 +01:00
Denny09310
9a0a494bc5 fix: missing "Once" changes, rollback to "On" on Notification 2025-11-10 11:27:32 +01:00
Florian Rappl
41a2b075c9 Merge pull request #917 from Denny09310/feature/system-text-json
refactor: Migrating from Newtonsoft.Json to System.Text.Json
2025-11-10 11:03:19 +01:00
Denny09310
adc1e81743 fix: simplified add/remove of socket listener through usage of "Once" 2025-11-10 10:40:51 +01:00
Denny09310
d8062aae00 fix: scale factor can be a double 2025-11-10 10:40:19 +01:00
Denny09310
0522bc425b fix: using correct deserialization type instead JsonElement for everyting except mixed arrays 2025-11-09 15:46:33 +01:00
Denny09310
168eceac8c fix: removed unused JsonPropertyName as ElectronJson.Options as by default camel case 2025-11-09 15:17:42 +01:00
Denny09310
4736bc640c fix: added usings, simplified imports, using JsonElement.Deserialize directly instead of JsonSerializer.Deserialize(JsonElement), removed some unused attributes 2025-11-09 15:15:52 +01:00
Denny09310
18b1317fc5 fix: ignore writing when value is null 2025-11-09 14:53:44 +01:00
Denny09310
dfe04f14d0 fix: menuItems splattering due to "params" keyword 2025-11-09 14:40:55 +01:00
Denny09310
9d6861ffcd fix: including internal properties in json 2025-11-09 14:40:55 +01:00
Denny09310
d8b0d0443d fix: removed useless attribute 2025-11-09 14:40:55 +01:00
Denny09310
71ced8db56 refactor: Migrated from Newtonsoft.Json to System.Text.Json, missing one test passing 2025-11-09 14:40:51 +01:00
Florian Rappl
fc69598b09 Merge pull request #913 from softworkz/submit_tests_fixes
Add 77 IntegrationTests and lots of fixes
2025-11-09 14:05:41 +01:00
softworkz
60a278c41f Cookie: Fix formatting 2025-11-09 12:47:56 +01:00
softworkz
9d25795b7a SocketBridgeService: Fix state transition error 2025-11-09 12:45:01 +01:00
softworkz
5b597cc12c StartupManager: Add support for running under testhost 2025-11-09 12:45:01 +01:00
softworkz
707c0f5a7b BrowserView.cs: Fix cast exception in Bounds property getter 2025-11-09 12:45:01 +01:00
softworkz
bb59bc8365 App.cs: Fix UserAgentFallbackAsync 2025-11-09 12:45:01 +01:00
softworkz
423ea57af7 ipc.ts: Add helper method for tests 2025-11-09 12:45:01 +01:00
softworkz
8dcc3721eb browserWindows.ts: Fix SetThumbarButtons 2025-11-09 12:45:01 +01:00
softworkz
dc27511aa5 browserWindows.ts: Add catch for Set/GetRepresentedFilename
It's not supported on all platforms
2025-11-09 12:45:01 +01:00
softworkz
dd465baebf notification.ts: Fix notificationIsSupported
It's a method, was used like a property
2025-11-09 12:45:01 +01:00
softworkz
04210955a3 webContents.ts: Fix clearAuthCache invocation
The options were no propagated for the overload
with RemovePassword options
2025-11-09 12:45:01 +01:00
softworkz
4129cc17a6 main.js: Load api/process import (was missing) 2025-11-09 12:45:01 +01:00
softworkz
bc0f601dd8 ProcessMetric: Fix deserialization error for CreationTime 2025-11-09 12:45:01 +01:00
softworkz
95fd7aa665 ApiBase: fix event names for App 2025-11-09 12:45:01 +01:00
softworkz
402147b8ef BrowserWindow: Disable SetPosition 'workaround'
It doesn't make sense to do this adjustment for
set only but not for get.
Neither is this done for SetBounds, so it should
be either fully consistent or left up to the
application to deal with it.
2025-11-09 12:45:01 +01:00
softworkz
ed7cc434ea browserWindowSetParentWindow: Support null parameter 2025-11-09 12:44:20 +01:00
softworkz
c5fb5f62d9 Add IntegrationTests project 2025-11-09 12:44:20 +01:00
Florian Rappl
84989cda25 Merge pull request #914 from softworkz/submit_whitespace
Fix and normalize whitespace
2025-11-09 12:25:49 +01:00
softworkz
84b3c59353 Fix and normalize whitespace 2025-11-09 03:50:24 +01:00
155 changed files with 3623 additions and 2577 deletions

View File

@@ -7,24 +7,27 @@ env:
NUGET_API_KEY: ${{ secrets.NUGET_API_KEY }}
jobs:
linux:
runs-on: ubuntu-latest
# linux:
# runs-on: ubuntu-latest
# timeout-minutes: 10
steps:
- uses: actions/checkout@v4
# steps:
# - uses: actions/checkout@v4
- name: Setup dotnet
uses: actions/setup-dotnet@v4
with:
dotnet-version: |
6.0.x
8.0.x
# - name: Setup dotnet
# uses: actions/setup-dotnet@v4
# with:
# dotnet-version: |
# 6.0.x
# 8.0.x
# 10.0.x
- name: Build
run: ./build.sh
# - name: Build
# run: ./build.sh
windows:
runs-on: windows-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
@@ -35,6 +38,7 @@ jobs:
dotnet-version: |
6.0.x
8.0.x
10.0.x
- name: Build
run: |

View File

@@ -1,23 +1,54 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$ref": "#/definitions/build",
"title": "Build Schema",
"definitions": {
"build": {
"type": "object",
"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": {
"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"
]
},
"Continue": {
"type": "boolean",
"description": "Indicates to continue a previously failed build attempt"
@@ -27,25 +58,8 @@
"description": "Shows the help text for this build assembly"
},
"Host": {
"type": "string",
"description": "Host for execution. Default is 'automatic'",
"enum": [
"AppVeyor",
"AzurePipelines",
"Bamboo",
"Bitbucket",
"Bitrise",
"GitHubActions",
"GitLab",
"Jenkins",
"Rider",
"SpaceAutomation",
"TeamCity",
"Terminal",
"TravisCI",
"VisualStudio",
"VSCode"
]
"$ref": "#/definitions/Host"
},
"NoLogo": {
"type": "boolean",
@@ -66,10 +80,6 @@
"type": "string"
}
},
"ReleaseNotesFilePath": {
"type": "string",
"description": "ReleaseNotesFilePath - To determine the lates changelog version"
},
"Root": {
"type": "string",
"description": "Root directory during build execution"
@@ -78,59 +88,50 @@
"type": "array",
"description": "List of targets to be skipped. Empty list skips all dependencies",
"items": {
"type": "string",
"enum": [
"Clean",
"Compile",
"CreatePackages",
"Default",
"Package",
"PrePublish",
"Publish",
"PublishPackages",
"PublishPreRelease",
"PublishRelease",
"Restore",
"RunUnitTests"
]
"$ref": "#/definitions/ExecutableTarget"
}
},
"Solution": {
"type": "string",
"description": "Path to a solution file that is automatically loaded"
},
"Target": {
"type": "array",
"description": "List of targets to be invoked. Default is '{default_target}'",
"items": {
"type": "string",
"enum": [
"Clean",
"Compile",
"CreatePackages",
"Default",
"Package",
"PrePublish",
"Publish",
"PublishPackages",
"PublishPreRelease",
"PublishRelease",
"Restore",
"RunUnitTests"
]
"$ref": "#/definitions/ExecutableTarget"
}
},
"Verbosity": {
"type": "string",
"description": "Logging verbosity during build execution. Default is 'Normal'",
"enum": [
"Minimal",
"Normal",
"Quiet",
"Verbose"
]
"$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

@@ -5,13 +5,20 @@
- 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
# 0.0.18

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2017-2024 Gregor Biswanger, Robert Mühsig
Copyright (c) 2017-2025 Gregor Biswanger, Robert Mühsig, Florian Rappl
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@@ -49,12 +49,12 @@ Add the Electron.NET configuration to your `.csproj` file:
```xml
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ElectronNET.Core" Version="1.0.0" />
<PackageReference Include="ElectronNET.Core" Version="0.1.0" />
</ItemGroup>
```

View File

@@ -28,7 +28,7 @@ Add publish profiles to `Properties/PublishProfiles/`:
<Platform>Any CPU</Platform>
<PublishDir>publish\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishSingleFile>false</PublishSingleFile>
@@ -48,7 +48,7 @@ Add publish profiles to `Properties/PublishProfiles/`:
<Platform>Any CPU</Platform>
<PublishDir>publish\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishSingleFile>false</PublishSingleFile>
@@ -68,7 +68,7 @@ Add publish profiles to `Properties/PublishProfiles/`:
<Platform>Any CPU</Platform>
<PublishDir>publish\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>false</SelfContained>
<PublishSingleFile>false</PublishSingleFile>
@@ -89,7 +89,7 @@ Add publish profiles to `Properties/PublishProfiles/`:
<Platform>Any CPU</Platform>
<PublishDir>publish\$(Configuration)\$(TargetFramework)\$(RuntimeIdentifier)\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<RuntimeIdentifier>linux-x64</RuntimeIdentifier>
<SelfContained>false</SelfContained>
<PublishSingleFile>false</PublishSingleFile>

View File

@@ -1,6 +1,6 @@
{
"sdk": {
"version": "8.0.305",
"version": "10.0.100",
"rollForward": "feature",
"allowPrerelease": false
}

View File

@@ -3,6 +3,7 @@ using Nuke.Common;
using Nuke.Common.CI.GitHubActions;
using Nuke.Common.IO;
using Nuke.Common.ProjectModel;
using Nuke.Common.Tooling;
using Nuke.Common.Tools.DotNet;
using Nuke.Common.Tools.GitHub;
using Nuke.Common.Tools.NuGet;
@@ -15,7 +16,6 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using static Nuke.Common.IO.FileSystemTasks;
using static Nuke.Common.IO.PathConstruction;
using static Nuke.Common.Tools.DotNet.DotNetTasks;
// ReSharper disable ArrangeThisQualifier
@@ -116,7 +116,7 @@ class Build : NukeBuild
Target Restore => _ => _
.Executes(() =>
{
DotNetRestore(s => s.SetProjectFile(Solution.Path));
DotNetRestore(s => s.SetProjectFile(Solution));
});
Target Compile => _ => _
@@ -124,7 +124,7 @@ class Build : NukeBuild
.Executes(() =>
{
DotNetBuild(s => s
.SetProjectFile(Solution.Path)
.SetProjectFile(Solution)
.SetConfiguration(Configuration)
.SetProperty("GeneratePackageOnBuild", "True")
.SetProperty("VersionPostFix", VersionPostFix ?? string.Empty));
@@ -134,18 +134,17 @@ class Build : NukeBuild
.DependsOn(Compile)
.Executes(() =>
{
// There aren't any yet
});
var TestProject = SourceDirectory / "ElectronNET.IntegrationTests" / "ElectronNET.IntegrationTests.csproj";
Target CreatePackages => _ => _
.DependsOn(Compile)
.Executes(() =>
{
// Packages are created on build
DotNetTest(s => s
.SetProjectFile(TestProject)
.SetConfiguration(Configuration)
.When(_ => GitHubActions.Instance is not null, x => x.SetLoggers("GitHubActions"))
);
});
Target PublishPackages => _ => _
.DependsOn(CreatePackages)
.DependsOn(Compile)
.DependsOn(RunUnitTests)
.Executes(() =>
{
@@ -240,7 +239,7 @@ class Build : NukeBuild
Target Package => _ => _
.DependsOn(RunUnitTests)
.DependsOn(CreatePackages);
.DependsOn(Compile);
Target Default => _ => _
.DependsOn(Package);

View File

@@ -11,11 +11,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Nuke.Common" Version="8.0.0" />
<PackageReference Include="Nuke.Common" Version="9.0.4" />
</ItemGroup>
<ItemGroup>
<PackageDownload Include="NuGet.CommandLine" Version="[6.3.1]" />
<PackageDownload Include="NuGet.CommandLine" Version="[6.12.2]" />
</ItemGroup>
</Project>

View File

@@ -1,29 +1,49 @@
namespace ElectronNET.API
// ReSharper disable InconsistentNaming
namespace ElectronNET.API
{
using Common;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using ElectronNET.Common;
public abstract class ApiBase
{
internal const int PropertyTimeout = 1000;
protected enum SocketTaskEventNameTypes
{
DashesLowerFirst,
NoDashUpperFirst
}
protected enum SocketTaskMessageNameTypes
{
DashesLowerFirst,
NoDashUpperFirst
}
protected enum SocketEventNameTypes
{
DashedLower,
CamelCase,
}
private const int PropertyTimeout = 1000;
private readonly string objectName;
private readonly ConcurrentDictionary<string, PropertyGetter> propertyGetters = new ConcurrentDictionary<string, PropertyGetter>();
private readonly ConcurrentDictionary<string, string> propertyEventNames = new ConcurrentDictionary<string, string>();
private readonly ConcurrentDictionary<string, string> propertyMessageNames = new ConcurrentDictionary<string, string>();
private readonly ConcurrentDictionary<string, string> methodMessageNames = new ConcurrentDictionary<string, string>();
private readonly ConcurrentDictionary<string, PropertyGetter> propertyGetters;
private readonly ConcurrentDictionary<string, string> propertyEventNames = new();
private readonly ConcurrentDictionary<string, string> propertyMessageNames = new();
private readonly ConcurrentDictionary<string, string> methodMessageNames = new();
private static readonly ConcurrentDictionary<string, EventContainer> eventContainers = new();
private static readonly ConcurrentDictionary<string, ConcurrentDictionary<string, PropertyGetter>> AllPropertyGetters = new();
private readonly object objLock = new object();
public virtual int Id
{
get
{
return -1;
}
get => -1;
// ReSharper disable once ValueParameterNotUsed
protected set
@@ -31,11 +51,14 @@
}
}
protected abstract string SocketEventCompleteSuffix { get; }
protected abstract SocketTaskEventNameTypes SocketTaskEventNameType { get; }
protected virtual SocketTaskMessageNameTypes SocketTaskMessageNameType => SocketTaskMessageNameTypes.NoDashUpperFirst;
protected virtual SocketEventNameTypes SocketEventNameType => SocketEventNameTypes.DashedLower;
protected ApiBase()
{
this.objectName = this.GetType().Name.LowerFirst();
propertyGetters = AllPropertyGetters.GetOrAdd(objectName, _ => new ConcurrentDictionary<string, PropertyGetter>());
}
protected void CallMethod0([CallerMemberName] string callerName = null)
@@ -90,7 +113,7 @@
}
}
protected Task<T> GetPropertyAsync<T>([CallerMemberName] string callerName = null)
protected Task<T> GetPropertyAsync<T>(object arg = null, [CallerMemberName] string callerName = null)
{
Debug.Assert(callerName != null, nameof(callerName) + " != null");
@@ -98,7 +121,7 @@
{
return this.propertyGetters.GetOrAdd(callerName, _ =>
{
var getter = new PropertyGetter<T>(this, callerName, PropertyTimeout);
var getter = new PropertyGetter<T>(this, callerName, PropertyTimeout, arg);
getter.Task<T>().ContinueWith(_ =>
{
@@ -112,6 +135,98 @@
}).Task<T>();
}
}
protected void AddEvent(Action value, int? id = null, [CallerMemberName] string callerName = null)
{
Debug.Assert(callerName != null, nameof(callerName) + " != null");
var eventName = EventName(callerName);
var eventKey = EventKey(eventName, id);
lock (objLock)
{
var container = eventContainers.GetOrAdd(eventKey, _ =>
{
var container = new EventContainer();
BridgeConnector.Socket.On(eventKey, container.OnEventAction);
BridgeConnector.Socket.Emit($"register-{eventName}", id);
return container;
});
container.Register(value);
}
}
protected void RemoveEvent(Action value, int? id = null, [CallerMemberName] string callerName = null)
{
Debug.Assert(callerName != null, nameof(callerName) + " != null");
var eventName = EventName(callerName);
var eventKey = EventKey(eventName, id);
lock (objLock)
{
if (eventContainers.TryGetValue(eventKey, out var container) && !container.Unregister(value))
{
BridgeConnector.Socket.Off(eventKey);
eventContainers.TryRemove(eventKey, out _);
}
}
}
protected void AddEvent<T>(Action<T> value, int? id = null, [CallerMemberName] string callerName = null)
{
Debug.Assert(callerName != null, nameof(callerName) + " != null");
var eventName = EventName(callerName);
var eventKey = EventKey(eventName, id);
lock (objLock)
{
var container = eventContainers.GetOrAdd(eventKey, _ =>
{
var container = new EventContainer();
BridgeConnector.Socket.On<T>(eventKey, container.OnEventActionT);
BridgeConnector.Socket.Emit($"register-{eventName}", id);
return container;
});
container.Register(value);
}
}
protected void RemoveEvent<T>(Action<T> value, int? id = null, [CallerMemberName] string callerName = null)
{
Debug.Assert(callerName != null, nameof(callerName) + " != null");
var eventName = EventName(callerName);
var eventKey = EventKey(eventName, id);
lock (objLock)
{
if (eventContainers.TryGetValue(eventKey, out var container) && !container.Unregister(value))
{
BridgeConnector.Socket.Off(eventKey);
eventContainers.TryRemove(eventKey, out _);
}
}
}
private string EventName(string callerName)
{
switch (SocketEventNameType)
{
case SocketEventNameTypes.DashedLower:
return $"{objectName}-{callerName.ToDashedEventName()}";
case SocketEventNameTypes.CamelCase:
return $"{objectName}-{callerName.ToCamelCaseEventName()}";
default:
throw new ArgumentOutOfRangeException();
}
}
private string EventKey(string eventName, int? id)
{
return string.Format(CultureInfo.InvariantCulture, "{0}{1:D}", eventName, id);
}
internal abstract class PropertyGetter
{
@@ -123,35 +238,68 @@
private readonly Task<T> tcsTask;
private TaskCompletionSource<T> tcs;
public PropertyGetter(ApiBase apiBase, string callerName, int timeoutMs)
public PropertyGetter(ApiBase apiBase, string callerName, int timeoutMs, object arg = null)
{
this.tcs = new TaskCompletionSource<T>(TaskCreationOptions.RunContinuationsAsynchronously);
this.tcsTask = this.tcs.Task;
var eventName = apiBase.propertyEventNames.GetOrAdd(callerName, s => $"{apiBase.objectName}-{s.StripAsync().LowerFirst()}{apiBase.SocketEventCompleteSuffix}");
var messageName = apiBase.propertyMessageNames.GetOrAdd(callerName, s => apiBase.objectName + s.StripAsync());
string eventName;
string messageName;
BridgeConnector.Socket.On<T>(eventName, (result) =>
switch (apiBase.SocketTaskEventNameType)
{
BridgeConnector.Socket.Off(eventName);
case SocketTaskEventNameTypes.DashesLowerFirst:
eventName = apiBase.propertyEventNames.GetOrAdd(callerName, s => $"{apiBase.objectName}-{s.StripAsync().LowerFirst()}-completed");
break;
case SocketTaskEventNameTypes.NoDashUpperFirst:
eventName = apiBase.propertyEventNames.GetOrAdd(callerName, s => $"{apiBase.objectName}{s.StripAsync()}Completed");
break;
default:
throw new ArgumentOutOfRangeException();
}
switch (apiBase.SocketTaskMessageNameType)
{
case SocketTaskMessageNameTypes.DashesLowerFirst:
messageName = apiBase.propertyMessageNames.GetOrAdd(callerName, s => $"{apiBase.objectName}-{s.StripAsync().LowerFirst()}");
break;
case SocketTaskMessageNameTypes.NoDashUpperFirst:
messageName = apiBase.propertyMessageNames.GetOrAdd(callerName, s => apiBase.objectName + s.StripAsync());
break;
default:
throw new ArgumentOutOfRangeException();
}
BridgeConnector.Socket.Once<T>(eventName, (result) =>
{
lock (this)
{
this.tcs?.SetResult(result);
this.tcs = null;
try
{
var value = result;
this.tcs?.SetResult(value);
}
catch (Exception ex)
{
this.tcs?.TrySetException(ex);
}
finally
{
this.tcs = null;
}
}
});
if (apiBase.Id >= 0)
if (arg != null)
{
BridgeConnector.Socket.Emit(messageName, apiBase.Id);
_ = apiBase.Id >= 0 ? BridgeConnector.Socket.Emit(messageName, apiBase.Id, arg) : BridgeConnector.Socket.Emit(messageName, arg);
}
else
{
BridgeConnector.Socket.Emit(messageName);
_ = apiBase.Id >= 0 ? BridgeConnector.Socket.Emit(messageName, apiBase.Id) : BridgeConnector.Socket.Emit(messageName);
}
System.Threading.Tasks.Task.Delay(ApiBase.PropertyTimeout).ContinueWith(_ =>
System.Threading.Tasks.Task.Delay(PropertyTimeout).ContinueWith(_ =>
{
if (this.tcs != null)
{
@@ -173,5 +321,53 @@
return this.tcsTask as Task<T1>;
}
}
[SuppressMessage("ReSharper", "InconsistentlySynchronizedField")]
private class EventContainer
{
private Action eventAction;
private Delegate eventActionT;
private Action<T> GetEventActionT<T>()
{
return (Action<T>)eventActionT;
}
private void SetEventActionT<T>(Action<T> actionT)
{
eventActionT = actionT;
}
public void OnEventAction() => eventAction?.Invoke();
public void OnEventActionT<T>(T p) => GetEventActionT<T>()?.Invoke(p);
public void Register(Action receiver)
{
eventAction += receiver;
}
public void Register<T>(Action<T> receiver)
{
var actionT = GetEventActionT<T>();
actionT += receiver;
SetEventActionT(actionT);
}
public bool Unregister(Action receiver)
{
eventAction -= receiver;
return this.eventAction != null;
}
public bool Unregister<T>(Action<T> receiver)
{
var actionT = GetEventActionT<T>();
actionT -= receiver;
SetEventActionT(actionT);
return actionT != null;
}
}
}
}

View File

@@ -1,13 +1,10 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ElectronNET.API.Entities;
using ElectronNET.API.Extensions;
using System;
using System.Runtime.InteropServices;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using ElectronNET.API.Extensions;
using ElectronNET.Common;
// ReSharper disable InconsistentNaming
@@ -18,7 +15,8 @@ namespace ElectronNET.API
/// </summary>
public sealed class App : ApiBase
{
protected override string SocketEventCompleteSuffix => "Completed";
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.NoDashUpperFirst;
protected override SocketEventNameTypes SocketEventNameType => SocketEventNameTypes.DashedLower;
/// <summary>
/// Emitted when all windows have been closed.
@@ -45,13 +43,14 @@ namespace ElectronNET.API
BridgeConnector.Socket.Emit("register-app-window-all-closed", GetHashCode());
}
_windowAllClosed += value;
}
remove
{
_windowAllClosed -= value;
if(_windowAllClosed == null)
if (_windowAllClosed == null)
BridgeConnector.Socket.Off("app-window-all-closed" + GetHashCode());
}
}
@@ -117,6 +116,7 @@ namespace ElectronNET.API
BridgeConnector.Socket.Emit("register-app-before-quit", GetHashCode());
}
_beforeQuit += value;
}
remove
@@ -168,6 +168,7 @@ namespace ElectronNET.API
BridgeConnector.Socket.Emit("register-app-will-quit", GetHashCode());
}
_willQuit += value;
}
remove
@@ -194,7 +195,7 @@ namespace ElectronNET.API
{
BridgeConnector.Socket.On("app-will-quit" + GetHashCode() + "quitting", async () =>
{
if(_willQuit == null)
if (_willQuit == null)
{
await this._quitting().ConfigureAwait(false);
Exit();
@@ -203,6 +204,7 @@ namespace ElectronNET.API
BridgeConnector.Socket.Emit("register-app-will-quit", GetHashCode() + "quitting");
}
_quitting += value;
}
remove
@@ -221,45 +223,37 @@ namespace ElectronNET.API
/// </summary>
public event Action BrowserWindowBlur
{
add => ApiEventManager.AddEvent("app-browser-window-blur", GetHashCode(), _browserWindowBlur, value);
remove => ApiEventManager.RemoveEvent("app-browser-window-blur", GetHashCode(), _browserWindowBlur, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action _browserWindowBlur;
/// <summary>
/// Emitted when a <see cref="BrowserWindow"/> gets focused.
/// </summary>
public event Action BrowserWindowFocus
{
add => ApiEventManager.AddEvent("app-browser-window-focus", GetHashCode(), _browserWindowFocus, value);
remove => ApiEventManager.RemoveEvent("app-browser-window-focus", GetHashCode(), _browserWindowFocus, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action _browserWindowFocus;
/// <summary>
/// Emitted when a new <see cref="BrowserWindow"/> is created.
/// </summary>
public event Action BrowserWindowCreated
{
add => ApiEventManager.AddEvent("app-browser-window-created", GetHashCode(), _browserWindowCreated, value);
remove => ApiEventManager.RemoveEvent("app-browser-window-created", GetHashCode(), _browserWindowCreated, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action _browserWindowCreated;
/// <summary>
/// Emitted when a new <see cref="WebContents"/> is created.
/// </summary>
public event Action WebContentsCreated
{
add => ApiEventManager.AddEvent("app-web-contents-created", GetHashCode(), _webContentsCreated, value);
remove => ApiEventManager.RemoveEvent("app-web-contents-created", GetHashCode(), _webContentsCreated, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action _webContentsCreated;
/// <summary>
/// Emitted when Chromes accessibility support changes. This event fires when assistive technologies, such as
/// screen readers, are enabled or disabled. See https://www.chromium.org/developers/design-documents/accessibility for more details.
@@ -267,20 +261,18 @@ namespace ElectronNET.API
/// <returns><see langword="true"/> when Chrome's accessibility support is enabled, <see langword="false"/> otherwise.</returns>
public event Action<bool> AccessibilitySupportChanged
{
add => ApiEventManager.AddEvent("app-accessibility-support-changed", GetHashCode(), _accessibilitySupportChanged, value, (args) => (bool)args);
remove => ApiEventManager.RemoveEvent("app-accessibility-support-changed", GetHashCode(), _accessibilitySupportChanged, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action<bool> _accessibilitySupportChanged;
/// <summary>
/// Emitted when the application has finished basic startup.
/// </summary>
public event Action Ready
public event Action Ready
{
add
{
if(IsReady)
if (IsReady)
{
value();
}
@@ -298,19 +290,23 @@ namespace ElectronNET.API
/// <summary>
/// Application host fully started.
/// </summary>
public bool IsReady
{
get { return _isReady; }
public bool IsReady
{
get
{
return _isReady;
}
internal set
{
_isReady = value;
if(value)
if (value)
{
_ready?.Invoke();
}
}
}
private bool _isReady = false;
/// <summary>
@@ -322,12 +318,10 @@ namespace ElectronNET.API
/// </summary>
public event Action<string> OpenFile
{
add => ApiEventManager.AddEvent("app-open-file", GetHashCode(), _openFile, value, (args) => args.ToString());
remove => ApiEventManager.RemoveEvent("app-open-file", GetHashCode(), _openFile, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action<string> _openFile;
/// <summary>
/// Emitted when a MacOS user wants to open a URL with the application. Your application's Info.plist file must
@@ -335,12 +329,10 @@ namespace ElectronNET.API
/// </summary>
public event Action<string> OpenUrl
{
add => ApiEventManager.AddEvent("app-open-url", GetHashCode(), _openUrl, value, (args) => args.ToString());
remove => ApiEventManager.RemoveEvent("app-open-url", GetHashCode(), _openUrl, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action<string> _openUrl;
/// <summary>
/// A <see cref="string"/> property that indicates the current application's name, which is the name in the
/// application's package.json file.
@@ -379,7 +371,7 @@ namespace ElectronNET.API
}
internal App()
internal App()
{
CommandLine = new CommandLine();
}
@@ -392,7 +384,7 @@ namespace ElectronNET.API
{
lock (_syncRoot)
{
if(_app == null)
if (_app == null)
{
_app = new App();
}
@@ -406,10 +398,7 @@ namespace ElectronNET.API
private static App _app;
private static object _syncRoot = new object();
private readonly JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
/// <summary>
/// Try to close all windows. The <see cref="BeforeQuit"/> event will be emitted first. If all windows are successfully
@@ -467,7 +456,7 @@ namespace ElectronNET.API
/// <param name="relaunchOptions">Options for the relaunch.</param>
public void Relaunch(RelaunchOptions relaunchOptions)
{
this.CallMethod1(JObject.FromObject(relaunchOptions, _jsonSerializer));
this.CallMethod1(relaunchOptions);
}
/// <summary>
@@ -487,7 +476,7 @@ namespace ElectronNET.API
/// </summary>
public void Focus(FocusOptions focusOptions)
{
this.CallMethod1(JObject.FromObject(focusOptions, _jsonSerializer));
this.CallMethod1(focusOptions);
}
/// <summary>
@@ -541,20 +530,14 @@ namespace ElectronNET.API
cancellationToken.ThrowIfCancellationRequested();
var taskCompletionSource = new TaskCompletionSource<string>();
using(cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
{
BridgeConnector.Socket.On("appGetPathCompleted", (path) =>
{
BridgeConnector.Socket.Off("appGetPathCompleted");
taskCompletionSource.SetResult(path.ToString());
});
BridgeConnector.Socket.Once<string>("appGetPathCompleted", taskCompletionSource.SetResult);
BridgeConnector.Socket.Emit("appGetPath", pathName.GetDescription());
return await taskCompletionSource.Task
.ConfigureAwait(false);
}
}
}
/// <summary>
@@ -712,12 +695,7 @@ namespace ElectronNET.API
var taskCompletionSource = new TaskCompletionSource<bool>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
{
BridgeConnector.Socket.On("appSetAsDefaultProtocolClientCompleted", (success) =>
{
BridgeConnector.Socket.Off("appSetAsDefaultProtocolClientCompleted");
taskCompletionSource.SetResult((bool) success);
});
BridgeConnector.Socket.Once<bool>("appSetAsDefaultProtocolClientCompleted", taskCompletionSource.SetResult);
BridgeConnector.Socket.Emit("appSetAsDefaultProtocolClient", protocol, path, args);
return await taskCompletionSource.Task
@@ -760,18 +738,13 @@ namespace ElectronNET.API
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Whether the call succeeded.</returns>
public async Task<bool> RemoveAsDefaultProtocolClientAsync(string protocol, string path, string[] args, CancellationToken cancellationToken = default)
{
{
cancellationToken.ThrowIfCancellationRequested();
var taskCompletionSource = new TaskCompletionSource<bool>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
{
BridgeConnector.Socket.On("appRemoveAsDefaultProtocolClientCompleted", (success) =>
{
BridgeConnector.Socket.Off("appRemoveAsDefaultProtocolClientCompleted");
taskCompletionSource.SetResult((bool) success);
});
BridgeConnector.Socket.Once<bool>("appRemoveAsDefaultProtocolClientCompleted", taskCompletionSource.SetResult);
BridgeConnector.Socket.Emit("appRemoveAsDefaultProtocolClient", protocol, path, args);
return await taskCompletionSource.Task
@@ -838,12 +811,7 @@ namespace ElectronNET.API
var taskCompletionSource = new TaskCompletionSource<bool>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
{
BridgeConnector.Socket.On("appIsDefaultProtocolClientCompleted", (success) =>
{
BridgeConnector.Socket.Off("appIsDefaultProtocolClientCompleted");
taskCompletionSource.SetResult((bool) success);
});
BridgeConnector.Socket.Once<bool>("appIsDefaultProtocolClientCompleted", taskCompletionSource.SetResult);
BridgeConnector.Socket.Emit("appIsDefaultProtocolClient", protocol, path, args);
return await taskCompletionSource.Task
@@ -866,13 +834,8 @@ namespace ElectronNET.API
var taskCompletionSource = new TaskCompletionSource<bool>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
{
BridgeConnector.Socket.On("appSetUserTasksCompleted", (success) =>
{
BridgeConnector.Socket.Off("appSetUserTasksCompleted");
taskCompletionSource.SetResult((bool) success);
});
BridgeConnector.Socket.Emit("appSetUserTasks", JArray.FromObject(userTasks, _jsonSerializer));
BridgeConnector.Socket.Once<bool>("appSetUserTasksCompleted", taskCompletionSource.SetResult);
BridgeConnector.Socket.Emit("appSetUserTasks", userTasks);
return await taskCompletionSource.Task
.ConfigureAwait(false);
@@ -908,7 +871,7 @@ namespace ElectronNET.API
/// <param name="categories">Array of <see cref="JumpListCategory"/> objects.</param>
public void SetJumpList(JumpListCategory[] categories)
{
this.CallMethod1(JArray.FromObject(categories, _jsonSerializer));
this.CallMethod1(categories);
}
/// <summary>
@@ -939,19 +902,17 @@ namespace ElectronNET.API
var taskCompletionSource = new TaskCompletionSource<bool>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
{
BridgeConnector.Socket.On("appRequestSingleInstanceLockCompleted", (success) =>
{
BridgeConnector.Socket.Off("appRequestSingleInstanceLockCompleted");
taskCompletionSource.SetResult((bool)success);
});
BridgeConnector.Socket.Once<bool>("appRequestSingleInstanceLockCompleted", taskCompletionSource.SetResult);
BridgeConnector.Socket.Off("secondInstance");
BridgeConnector.Socket.On("secondInstance", (result) =>
BridgeConnector.Socket.On<JsonElement>("secondInstance", (result) =>
{
JArray results = (JArray)result;
string[] args = results.First.ToObject<string[]>();
string workingDirectory = results.Last.ToObject<string>();
var arr = result.EnumerateArray();
var e = arr.GetEnumerator();
e.MoveNext();
var args = e.Current.Deserialize<string[]>(JsonSerializerOptions.Default);
e.MoveNext();
var workingDirectory = e.Current.GetString();
newInstanceOpened(args, workingDirectory);
});
@@ -1063,13 +1024,8 @@ namespace ElectronNET.API
var taskCompletionSource = new TaskCompletionSource<int>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
{
BridgeConnector.Socket.On("appImportCertificateCompleted", (result) =>
{
BridgeConnector.Socket.Off("appImportCertificateCompleted");
taskCompletionSource.SetResult((int) result);
});
BridgeConnector.Socket.Emit("appImportCertificate", JObject.FromObject(options, _jsonSerializer));
BridgeConnector.Socket.Once<int>("appImportCertificateCompleted", taskCompletionSource.SetResult);
BridgeConnector.Socket.Emit("appImportCertificate", options);
return await taskCompletionSource.Task
.ConfigureAwait(false);
@@ -1119,12 +1075,7 @@ namespace ElectronNET.API
var taskCompletionSource = new TaskCompletionSource<bool>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
{
BridgeConnector.Socket.On("appSetBadgeCountCompleted", (success) =>
{
BridgeConnector.Socket.Off("appSetBadgeCountCompleted");
taskCompletionSource.SetResult((bool) success);
});
BridgeConnector.Socket.Once<bool>("appSetBadgeCountCompleted", taskCompletionSource.SetResult);
BridgeConnector.Socket.Emit("appSetBadgeCount", count);
return await taskCompletionSource.Task
@@ -1179,14 +1130,7 @@ namespace ElectronNET.API
var taskCompletionSource = new TaskCompletionSource<LoginItemSettings>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
{
BridgeConnector.Socket.On("appGetLoginItemSettingsCompleted", (loginItemSettings) =>
{
BridgeConnector.Socket.Off("appGetLoginItemSettingsCompleted");
var result = ((JObject) loginItemSettings).ToObject<LoginItemSettings>();
taskCompletionSource.SetResult(result);
});
BridgeConnector.Socket.Once<LoginItemSettings>("appGetLoginItemSettingsCompleted", taskCompletionSource.SetResult);
if (options == null)
{
@@ -1194,7 +1138,7 @@ namespace ElectronNET.API
}
else
{
BridgeConnector.Socket.Emit("appGetLoginItemSettings", JObject.FromObject(options, _jsonSerializer));
BridgeConnector.Socket.Emit("appGetLoginItemSettings", options);
}
return await taskCompletionSource.Task
@@ -1210,7 +1154,7 @@ namespace ElectronNET.API
/// <param name="loginSettings"></param>
public void SetLoginItemSettings(LoginSettings loginSettings)
{
this.CallMethod1(JObject.FromObject(loginSettings, _jsonSerializer));
this.CallMethod1(loginSettings);
}
/// <summary>
@@ -1262,7 +1206,7 @@ namespace ElectronNET.API
/// <param name="options">About panel options.</param>
public void SetAboutPanelOptions(AboutPanelOptions options)
{
this.CallMethod1(JObject.FromObject(options, _jsonSerializer));
this.CallMethod1(options);
}
/// <summary>
@@ -1298,7 +1242,15 @@ namespace ElectronNET.API
{
get
{
return this.GetPropertyAsync<string>();
return Task.Run(() =>
{
var taskCompletionSource = new TaskCompletionSource<string>();
BridgeConnector.Socket.Once<string>("appGetUserAgentFallbackCompleted", taskCompletionSource.SetResult);
BridgeConnector.Socket.Emit("appGetUserAgentFallback");
return taskCompletionSource.Task;
});
}
}
@@ -1310,6 +1262,7 @@ namespace ElectronNET.API
private bool _preventQuit = false;
private const string ModuleName = "app";
/// <summary>
/// Subscribe to an unmapped event on the <see cref="App"/> module.
/// </summary>
@@ -1317,6 +1270,7 @@ namespace ElectronNET.API
/// <param name="action">The handler</param>
public void On(string eventName, Action action)
=> Events.Instance.On(ModuleName, eventName, action);
/// <summary>
/// Subscribe to an unmapped event on the <see cref="App"/> module.
/// </summary>
@@ -1324,6 +1278,7 @@ namespace ElectronNET.API
/// <param name="action">The handler</param>
public async Task On(string eventName, Action<object> action)
=> await Events.Instance.On(ModuleName, eventName, action).ConfigureAwait(false);
/// <summary>
/// Subscribe to an unmapped event on the <see cref="App"/> module once.
/// </summary>
@@ -1331,6 +1286,7 @@ namespace ElectronNET.API
/// <param name="action">The handler</param>
public void Once(string eventName, Action action)
=> Events.Instance.Once(ModuleName, eventName, action);
/// <summary>
/// Subscribe to an unmapped event on the <see cref="App"/> module once.
/// </summary>

View File

@@ -1,11 +1,8 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ElectronNET.API.Entities;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using ElectronNET.Common;
// ReSharper disable InconsistentNaming
namespace ElectronNET.API
@@ -13,8 +10,12 @@ namespace ElectronNET.API
/// <summary>
/// Enable apps to automatically update themselves. Based on electron-updater.
/// </summary>
public sealed class AutoUpdater
public sealed class AutoUpdater: ApiBase
{
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.DashesLowerFirst;
protected override SocketTaskMessageNameTypes SocketTaskMessageNameType => SocketTaskMessageNameTypes.DashesLowerFirst;
protected override SocketEventNameTypes SocketEventNameType => SocketEventNameTypes.DashedLower;
/// <summary>
/// Whether to automatically download an update when it is found. (Default is true)
/// </summary>
@@ -22,20 +23,7 @@ namespace ElectronNET.API
{
get
{
return Task.Run<bool>(() =>
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("autoUpdater-autoDownload-get-reply", (result) =>
{
BridgeConnector.Socket.Off("autoUpdater-autoDownload-get-reply");
taskCompletionSource.SetResult((bool)result);
});
BridgeConnector.Socket.Emit("autoUpdater-autoDownload-get");
return taskCompletionSource.Task;
}).Result;
return Task.Run(() => GetPropertyAsync<bool>()).Result;
}
set
{
@@ -52,20 +40,7 @@ namespace ElectronNET.API
{
get
{
return Task.Run<bool>(() =>
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("autoUpdater-autoInstallOnAppQuit-get-reply", (result) =>
{
BridgeConnector.Socket.Off("autoUpdater-autoInstallOnAppQuit-get-reply");
taskCompletionSource.SetResult((bool)result);
});
BridgeConnector.Socket.Emit("autoUpdater-autoInstallOnAppQuit-get");
return taskCompletionSource.Task;
}).Result;
return Task.Run(() => GetPropertyAsync<bool>()).Result;
}
set
{
@@ -83,20 +58,7 @@ namespace ElectronNET.API
{
get
{
return Task.Run<bool>(() =>
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("autoUpdater-allowPrerelease-get-reply", (result) =>
{
BridgeConnector.Socket.Off("autoUpdater-allowPrerelease-get-reply");
taskCompletionSource.SetResult((bool)result);
});
BridgeConnector.Socket.Emit("autoUpdater-allowPrerelease-get");
return taskCompletionSource.Task;
}).Result;
return Task.Run(() => GetPropertyAsync<bool>()).Result;
}
set
{
@@ -112,20 +74,7 @@ namespace ElectronNET.API
{
get
{
return Task.Run<bool>(() =>
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("autoUpdater-fullChangelog-get-reply", (result) =>
{
BridgeConnector.Socket.Off("autoUpdater-fullChangelog-get-reply");
taskCompletionSource.SetResult((bool)result);
});
BridgeConnector.Socket.Emit("autoUpdater-fullChangelog-get");
return taskCompletionSource.Task;
}).Result;
return Task.Run(() => GetPropertyAsync<bool>()).Result;
}
set
{
@@ -142,20 +91,7 @@ namespace ElectronNET.API
{
get
{
return Task.Run<bool>(() =>
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("autoUpdater-allowDowngrade-get-reply", (result) =>
{
BridgeConnector.Socket.Off("autoUpdater-allowDowngrade-get-reply");
taskCompletionSource.SetResult((bool)result);
});
BridgeConnector.Socket.Emit("autoUpdater-allowDowngrade-get");
return taskCompletionSource.Task;
}).Result;
return Task.Run(() => GetPropertyAsync<bool>()).Result;
}
set
{
@@ -170,20 +106,7 @@ namespace ElectronNET.API
{
get
{
return Task.Run<string>(() =>
{
var taskCompletionSource = new TaskCompletionSource<string>();
BridgeConnector.Socket.On("autoUpdater-updateConfigPath-get-reply", (result) =>
{
BridgeConnector.Socket.Off("autoUpdater-updateConfigPath-get-reply");
taskCompletionSource.SetResult(result.ToString());
});
BridgeConnector.Socket.Emit("autoUpdater-updateConfigPath-get");
return taskCompletionSource.Task;
}).Result;
return Task.Run(() => GetPropertyAsync<string>()).Result;
}
}
@@ -194,20 +117,7 @@ namespace ElectronNET.API
{
get
{
return Task.Run<SemVer>(() =>
{
var taskCompletionSource = new TaskCompletionSource<SemVer>();
BridgeConnector.Socket.On("autoUpdater-currentVersion-get-reply", (result) =>
{
BridgeConnector.Socket.Off("autoUpdater-currentVersion-get-reply");
SemVer version = ((JObject)result).ToObject<SemVer>();
taskCompletionSource.SetResult(version);
});
BridgeConnector.Socket.Emit("autoUpdater-currentVersion-get");
return taskCompletionSource.Task;
});
return Task.Run(() => GetPropertyAsync<SemVer>());
}
}
@@ -232,22 +142,20 @@ namespace ElectronNET.API
{
get
{
return Task.Run<string>(() =>
{
var taskCompletionSource = new TaskCompletionSource<string>();
BridgeConnector.Socket.On("autoUpdater-channel-get-reply", (result) =>
{
BridgeConnector.Socket.Off("autoUpdater-channel-get-reply");
taskCompletionSource.SetResult(result.ToString());
});
BridgeConnector.Socket.Emit("autoUpdater-channel-get");
return taskCompletionSource.Task;
});
return Task.Run(() => GetPropertyAsync<string>());
}
}
/// <summary>
/// Set the update channel. Not applicable for GitHub.
/// </summary>
public string SetChannel
{
set
{
BridgeConnector.Socket.Emit("autoUpdater-channel-set", value);
}
}
/// <summary>
@@ -257,18 +165,7 @@ namespace ElectronNET.API
{
get
{
return Task.Run(() =>
{
var taskCompletionSource = new TaskCompletionSource<Dictionary<string, string>>();
BridgeConnector.Socket.On("autoUpdater-requestHeaders-get-reply", (headers) =>
{
BridgeConnector.Socket.Off("autoUpdater-requestHeaders-get-reply");
Dictionary<string, string> result = ((JObject)headers).ToObject<Dictionary<string, string>>();
taskCompletionSource.SetResult(result);
});
BridgeConnector.Socket.Emit("autoUpdater-requestHeaders-get");
return taskCompletionSource.Task;
});
return Task.Run(() => GetPropertyAsync<Dictionary<string, string>>());
}
}
@@ -279,7 +176,7 @@ namespace ElectronNET.API
{
set
{
BridgeConnector.Socket.Emit("autoUpdater-requestHeaders-set", JObject.FromObject(value, _jsonSerializer));
BridgeConnector.Socket.Emit("autoUpdater-requestHeaders-set", value);
}
}
@@ -288,72 +185,62 @@ namespace ElectronNET.API
/// </summary>
public event Action<string> OnError
{
add => ApiEventManager.AddEvent("autoUpdater-error", GetHashCode(), _error, value, (args) => args.ToString());
remove => ApiEventManager.RemoveEvent("autoUpdater-error", GetHashCode(), _error, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action<string> _error;
/// <summary>
/// Emitted when checking if an update has started.
/// </summary>
public event Action OnCheckingForUpdate
{
add => ApiEventManager.AddEvent("autoUpdater-checking-for-update", GetHashCode(), _checkingForUpdate, value);
remove => ApiEventManager.RemoveEvent("autoUpdater-checking-for-update", GetHashCode(), _checkingForUpdate, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, 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 => ApiEventManager.AddEvent("autoUpdater-update-available", GetHashCode(), _updateAvailable, value, (args) => JObject.Parse(args.ToString()).ToObject<UpdateInfo>());
remove => ApiEventManager.RemoveEvent("autoUpdater-update-available", GetHashCode(), _updateAvailable, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action<UpdateInfo> _updateAvailable;
/// <summary>
/// Emitted when there is no available update.
/// </summary>
public event Action<UpdateInfo> OnUpdateNotAvailable
{
add => ApiEventManager.AddEvent("autoUpdater-update-not-available", GetHashCode(), _updateNotAvailable, value, (args) => JObject.Parse(args.ToString()).ToObject<UpdateInfo>());
remove => ApiEventManager.RemoveEvent("autoUpdater-update-not-available", GetHashCode(), _updateNotAvailable, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action<UpdateInfo> _updateNotAvailable;
/// <summary>
/// Emitted on download progress.
/// </summary>
public event Action<ProgressInfo> OnDownloadProgress
{
add => ApiEventManager.AddEvent("autoUpdater-download-progress", GetHashCode(), _downloadProgress, value, (args) => JObject.Parse(args.ToString()).ToObject<ProgressInfo>());
remove => ApiEventManager.RemoveEvent("autoUpdater-download-progress", GetHashCode(), _downloadProgress, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action<ProgressInfo> _downloadProgress;
/// <summary>
/// Emitted on download complete.
/// </summary>
public event Action<UpdateInfo> OnUpdateDownloaded
{
add => ApiEventManager.AddEvent("autoUpdater-update-downloaded", GetHashCode(), _updateDownloaded, value, (args) => JObject.Parse(args.ToString()).ToObject<UpdateInfo>());
remove => ApiEventManager.RemoveEvent("autoUpdater-update-downloaded", GetHashCode(), _updateDownloaded, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action<UpdateInfo> _updateDownloaded;
private static AutoUpdater _autoUpdater;
private static object _syncRoot = new object();
internal AutoUpdater() { }
internal AutoUpdater()
{
}
internal static AutoUpdater Instance
{
@@ -383,30 +270,27 @@ namespace ElectronNET.API
var taskCompletionSource = new TaskCompletionSource<UpdateCheckResult>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("autoUpdaterCheckForUpdatesComplete" + guid, (updateCheckResult) =>
BridgeConnector.Socket.Once<UpdateCheckResult>("autoUpdater-checkForUpdates-completed" + guid, (result) =>
{
try
{
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesComplete" + guid);
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesError" + guid);
taskCompletionSource.SetResult(JObject.Parse(updateCheckResult.ToString()).ToObject<UpdateCheckResult>());
BridgeConnector.Socket.Off("autoUpdater-checkForUpdatesError" + guid);
taskCompletionSource.SetResult(result);
}
catch (Exception ex)
{
taskCompletionSource.SetException(ex);
}
});
BridgeConnector.Socket.On("autoUpdaterCheckForUpdatesError" + guid, (error) =>
BridgeConnector.Socket.Once<string>("autoUpdater-checkForUpdatesError" + guid, (result) =>
{
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesComplete" + guid);
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesError" + guid);
BridgeConnector.Socket.Off("autoUpdater-checkForUpdates-completed" + guid);
string message = "An error occurred in CheckForUpdatesAsync";
if (error != null && !string.IsNullOrEmpty(error.ToString()))
message = JsonConvert.SerializeObject(error);
if (!string.IsNullOrEmpty(result)) message = result;
taskCompletionSource.SetException(new Exception(message));
});
BridgeConnector.Socket.Emit("autoUpdaterCheckForUpdates", guid);
BridgeConnector.Socket.Emit("autoUpdater-checkForUpdates", guid);
return taskCompletionSource.Task;
}
@@ -422,33 +306,27 @@ namespace ElectronNET.API
var taskCompletionSource = new TaskCompletionSource<UpdateCheckResult>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("autoUpdaterCheckForUpdatesAndNotifyComplete" + guid, (updateCheckResult) =>
BridgeConnector.Socket.Once<UpdateCheckResult>("autoUpdater-checkForUpdatesAndNotify-completed" + guid, (result) =>
{
try
{
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesAndNotifyComplete" + guid);
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesAndNotifyError" + guid);
if (updateCheckResult == null)
taskCompletionSource.SetResult(null);
else
taskCompletionSource.SetResult(JObject.Parse(updateCheckResult.ToString()).ToObject<UpdateCheckResult>());
BridgeConnector.Socket.Off("autoUpdater-checkForUpdatesAndNotifyError" + guid);
taskCompletionSource.SetResult(result);
}
catch (Exception ex)
{
taskCompletionSource.SetException(ex);
}
});
BridgeConnector.Socket.On("autoUpdaterCheckForUpdatesAndNotifyError" + guid, (error) =>
BridgeConnector.Socket.Once<string>("autoUpdater-checkForUpdatesAndNotifyError" + guid, (result) =>
{
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesAndNotifyComplete" + guid);
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesAndNotifyError" + guid);
string message = "An error occurred in autoUpdaterCheckForUpdatesAndNotify";
if (error != null)
message = JsonConvert.SerializeObject(error);
BridgeConnector.Socket.Off("autoUpdater-checkForUpdatesAndNotify-completed" + guid);
string message = "An error occurred in CheckForUpdatesAndNotifyAsync";
if (!string.IsNullOrEmpty(result)) message = result;
taskCompletionSource.SetException(new Exception(message));
});
BridgeConnector.Socket.Emit("autoUpdaterCheckForUpdatesAndNotify", guid);
BridgeConnector.Socket.Emit("autoUpdater-checkForUpdatesAndNotify", guid);
return taskCompletionSource.Task;
}
@@ -464,7 +342,7 @@ namespace ElectronNET.API
/// <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.Socket.Emit("autoUpdaterQuitAndInstall", isSilent, isForceRunAfter);
BridgeConnector.Socket.Emit("autoUpdater-quitAndInstall", isSilent, isForceRunAfter);
}
/// <summary>
@@ -473,18 +351,13 @@ namespace ElectronNET.API
/// <returns>Path to downloaded file.</returns>
public Task<string> DownloadUpdateAsync()
{
var taskCompletionSource = new TaskCompletionSource<string>();
var tcs = new TaskCompletionSource<string>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("autoUpdaterDownloadUpdateComplete" + guid, (downloadedPath) =>
{
BridgeConnector.Socket.Off("autoUpdaterDownloadUpdateComplete" + guid);
taskCompletionSource.SetResult(downloadedPath.ToString());
});
BridgeConnector.Socket.Once<string>("autoUpdater-downloadUpdate-completed" + guid, tcs.SetResult);
BridgeConnector.Socket.Emit("autoUpdater-downloadUpdate", guid);
BridgeConnector.Socket.Emit("autoUpdaterDownloadUpdate", guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -493,23 +366,17 @@ namespace ElectronNET.API
/// <returns>Feed URL.</returns>
public Task<string> GetFeedURLAsync()
{
var taskCompletionSource = new TaskCompletionSource<string>();
var tcs = new TaskCompletionSource<string>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("autoUpdaterGetFeedURLComplete" + guid, (downloadedPath) =>
{
BridgeConnector.Socket.Off("autoUpdaterGetFeedURLComplete" + guid);
taskCompletionSource.SetResult(downloadedPath.ToString());
});
BridgeConnector.Socket.Once<string>("autoUpdater-getFeedURL-completed" + guid, tcs.SetResult);
BridgeConnector.Socket.Emit("autoUpdater-getFeedURL", guid);
BridgeConnector.Socket.Emit("autoUpdaterGetFeedURL", guid);
return taskCompletionSource.Task;
return tcs.Task;
}
private readonly JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
}
}

View File

@@ -1,25 +1,21 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ElectronNET.API.Entities;
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
public class BrowserView: ApiBase
{
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.DashesLowerFirst;
protected override SocketTaskMessageNameTypes SocketTaskMessageNameType => SocketTaskMessageNameTypes.DashesLowerFirst;
/// <summary>
/// Gets the identifier.
/// </summary>
/// <value>
/// The identifier.
/// </value>
public int Id { get; internal set; }
public override int Id { get; protected set; }
/// <summary>
/// Render and control web pages.
@@ -28,38 +24,24 @@ namespace ElectronNET.API
/// <summary>
/// Resizes and moves the view to the supplied bounds relative to the window.
///
/// (experimental)
/// </summary>
public Rectangle Bounds
{
get
{
return Task.Run<Rectangle>(() =>
{
var taskCompletionSource = new TaskCompletionSource<Rectangle>();
BridgeConnector.Socket.On("browserView-getBounds-reply", (result) =>
{
BridgeConnector.Socket.Off("browserView-getBounds-reply");
taskCompletionSource.SetResult((Rectangle)result);
});
BridgeConnector.Socket.Emit("browserView-getBounds", Id);
return taskCompletionSource.Task;
}).Result;
return Task.Run(() => GetPropertyAsync<Rectangle>()).Result;
}
set
{
BridgeConnector.Socket.Emit("browserView-setBounds", Id, JObject.FromObject(value, _jsonSerializer));
BridgeConnector.Socket.Emit("browserView-bounds-set", Id, value);
}
}
/// <summary>
/// BrowserView
/// </summary>
internal BrowserView(int id)
internal BrowserView(int id)
{
Id = id;
@@ -74,12 +56,11 @@ namespace ElectronNET.API
/// <param name="options"></param>
public void SetAutoResize(AutoResizeOptions options)
{
BridgeConnector.Socket.Emit("browserView-setAutoResize", Id, JObject.FromObject(options, _jsonSerializer));
BridgeConnector.Socket.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>
@@ -87,11 +68,6 @@ namespace ElectronNET.API
{
BridgeConnector.Socket.Emit("browserView-setBackgroundColor", Id, color);
}
private JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
}
}

View File

@@ -1,29 +1,22 @@
using ElectronNET.API.Entities;
using ElectronNET.API.Entities;
using ElectronNET.API.Extensions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using ElectronNET.Common;
// ReSharper disable InconsistentNaming
namespace ElectronNET.API;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using ElectronNET.Common;
/// <summary>
/// Create and control browser windows.
/// </summary>
public class BrowserWindow : ApiBase
{
protected override string SocketEventCompleteSuffix => "-completed";
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.DashesLowerFirst;
protected override SocketEventNameTypes SocketEventNameType => SocketEventNameTypes.DashedLower;
/// <summary>
/// Gets the identifier.
@@ -39,34 +32,28 @@ public class BrowserWindow : ApiBase
/// </summary>
public event Action OnReadyToShow
{
add => ApiEventManager.AddEvent("browserWindow-ready-to-show", Id, _readyToShow, value);
remove => ApiEventManager.RemoveEvent("browserWindow-ready-to-show", Id, _readyToShow, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _readyToShow;
/// <summary>
/// Emitted when the document changed its title.
/// </summary>
public event Action<string> OnPageTitleUpdated
{
add => ApiEventManager.AddEvent("browserWindow-page-title-updated", Id, _pageTitleUpdated, value, (args) => args.ToString());
remove => ApiEventManager.RemoveEvent("browserWindow-page-title-updated", Id, _pageTitleUpdated, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action<string> _pageTitleUpdated;
/// <summary>
/// Emitted when the window is going to be closed.
/// </summary>
public event Action OnClose
{
add => ApiEventManager.AddEvent("browserWindow-close", Id, _close, value);
remove => ApiEventManager.RemoveEvent("browserWindow-close", Id, _close, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _close;
/// <summary>
/// Emitted when the window is closed.
/// After you have received this event you should remove the
@@ -74,144 +61,118 @@ public class BrowserWindow : ApiBase
/// </summary>
public event Action OnClosed
{
add => ApiEventManager.AddEvent("browserWindow-closed", Id, _closed, value);
remove => ApiEventManager.RemoveEvent("browserWindow-closed", Id, _closed, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _closed;
/// <summary>
/// Emitted when window session is going to end due to force shutdown or machine restart or session log off.
/// </summary>
public event Action OnSessionEnd
{
add => ApiEventManager.AddEvent("browserWindow-session-end", Id, _sessionEnd, value);
remove => ApiEventManager.RemoveEvent("browserWindow-session-end", Id, _sessionEnd, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _sessionEnd;
/// <summary>
/// Emitted when the web page becomes unresponsive.
/// </summary>
public event Action OnUnresponsive
{
add => ApiEventManager.AddEvent("browserWindow-unresponsive", Id, _unresponsive, value);
remove => ApiEventManager.RemoveEvent("browserWindow-unresponsive", Id, _unresponsive, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _unresponsive;
/// <summary>
/// Emitted when the unresponsive web page becomes responsive again.
/// </summary>
public event Action OnResponsive
{
add => ApiEventManager.AddEvent("browserWindow-responsive", Id, _responsive, value);
remove => ApiEventManager.RemoveEvent("browserWindow-responsive", Id, _responsive, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _responsive;
/// <summary>
/// Emitted when the window loses focus.
/// </summary>
public event Action OnBlur
{
add => ApiEventManager.AddEvent("browserWindow-blur", Id, _blur, value);
remove => ApiEventManager.RemoveEvent("browserWindow-blur", Id, _blur, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _blur;
/// <summary>
/// Emitted when the window gains focus.
/// </summary>
public event Action OnFocus
{
add => ApiEventManager.AddEvent("browserWindow-focus", Id, _focus, value);
remove => ApiEventManager.RemoveEvent("browserWindow-focus", Id, _focus, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _focus;
/// <summary>
/// Emitted when the window is shown.
/// </summary>
public event Action OnShow
{
add => ApiEventManager.AddEvent("browserWindow-show", Id, _show, value);
remove => ApiEventManager.RemoveEvent("browserWindow-show", Id, _show, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _show;
/// <summary>
/// Emitted when the window is hidden.
/// </summary>
public event Action OnHide
{
add => ApiEventManager.AddEvent("browserWindow-hide", Id, _hide, value);
remove => ApiEventManager.RemoveEvent("browserWindow-hide", Id, _hide, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _hide;
/// <summary>
/// Emitted when window is maximized.
/// </summary>
public event Action OnMaximize
{
add => ApiEventManager.AddEvent("browserWindow-maximize", Id, _maximize, value);
remove => ApiEventManager.RemoveEvent("browserWindow-maximize", Id, _maximize, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _maximize;
/// <summary>
/// Emitted when the window exits from a maximized state.
/// </summary>
public event Action OnUnmaximize
{
add => ApiEventManager.AddEvent("browserWindow-unmaximize", Id, _unmaximize, value);
remove => ApiEventManager.RemoveEvent("browserWindow-unmaximize", Id, _unmaximize, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _unmaximize;
/// <summary>
/// Emitted when the window is minimized.
/// </summary>
public event Action OnMinimize
{
add => ApiEventManager.AddEvent("browserWindow-minimize", Id, _minimize, value);
remove => ApiEventManager.RemoveEvent("browserWindow-minimize", Id, _minimize, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _minimize;
/// <summary>
/// Emitted when the window is restored from a minimized state.
/// </summary>
public event Action OnRestore
{
add => ApiEventManager.AddEvent("browserWindow-restore", Id, _restore, value);
remove => ApiEventManager.RemoveEvent("browserWindow-restore", Id, _restore, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _restore;
/// <summary>
/// Emitted when the window is being resized.
/// </summary>
public event Action OnResize
{
add => ApiEventManager.AddEvent("browserWindow-resize", Id, _resize, value);
remove => ApiEventManager.RemoveEvent("browserWindow-resize", Id, _resize, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _resize;
/// <summary>
/// Emitted when the window is being moved to a new position.
///
@@ -219,67 +180,55 @@ public class BrowserWindow : ApiBase
/// </summary>
public event Action OnMove
{
add => ApiEventManager.AddEvent("browserWindow-move", Id, _move, value);
remove => ApiEventManager.RemoveEvent("browserWindow-move", Id, _move, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _move;
/// <summary>
/// macOS: Emitted once when the window is moved to a new position.
/// </summary>
public event Action OnMoved
{
add => ApiEventManager.AddEvent("browserWindow-moved", Id, _moved, value);
remove => ApiEventManager.RemoveEvent("browserWindow-moved", Id, _moved, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _moved;
/// <summary>
/// Emitted when the window enters a full-screen state.
/// </summary>
public event Action OnEnterFullScreen
{
add => ApiEventManager.AddEvent("browserWindow-enter-full-screen", Id, _enterFullScreen, value);
remove => ApiEventManager.RemoveEvent("browserWindow-enter-full-screen", Id, _enterFullScreen, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _enterFullScreen;
/// <summary>
/// Emitted when the window leaves a full-screen state.
/// </summary>
public event Action OnLeaveFullScreen
{
add => ApiEventManager.AddEvent("browserWindow-leave-full-screen", Id, _leaveFullScreen, value);
remove => ApiEventManager.RemoveEvent("browserWindow-leave-full-screen", Id, _leaveFullScreen, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _leaveFullScreen;
/// <summary>
/// Emitted when the window enters a full-screen state triggered by HTML API.
/// </summary>
public event Action OnEnterHtmlFullScreen
{
add => ApiEventManager.AddEvent("browserWindow-enter-html-full-screen", Id, _enterHtmlFullScreen, value);
remove => ApiEventManager.RemoveEvent("browserWindow-enter-html-full-screen", Id, _enterHtmlFullScreen, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _enterHtmlFullScreen;
/// <summary>
/// Emitted when the window leaves a full-screen state triggered by HTML API.
/// </summary>
public event Action OnLeaveHtmlFullScreen
{
add => ApiEventManager.AddEvent("browserWindow-leave-html-full-screen", Id, _leaveHtmlFullScreen, value);
remove => ApiEventManager.RemoveEvent("browserWindow-leave-html-full-screen", Id, _leaveHtmlFullScreen, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _leaveHtmlFullScreen;
/// <summary>
/// Emitted when an App Command is invoked. These are typically related to
/// keyboard media keys or browser commands, as well as the “Back” button
@@ -291,56 +240,46 @@ public class BrowserWindow : ApiBase
/// </summary>
public event Action<string> OnAppCommand
{
add => ApiEventManager.AddEvent("browserWindow-app-command", Id, _appCommand, value, (args) => args.ToString());
remove => ApiEventManager.RemoveEvent("browserWindow-app-command", Id, _appCommand, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action<string> _appCommand;
/// <summary>
/// Emitted on 3-finger swipe. Possible directions are up, right, down, left.
/// </summary>
public event Action<string> OnSwipe
{
add => ApiEventManager.AddEvent("browserWindow-swipe", Id, _swipe, value, (args) => args.ToString());
remove => ApiEventManager.RemoveEvent("browserWindow-swipe", Id, _swipe, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action<string> _swipe;
/// <summary>
/// Emitted when the window opens a sheet.
/// </summary>
public event Action OnSheetBegin
{
add => ApiEventManager.AddEvent("browserWindow-sheet-begin", Id, _sheetBegin, value);
remove => ApiEventManager.RemoveEvent("browserWindow-sheet-begin", Id, _sheetBegin, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _sheetBegin;
/// <summary>
/// Emitted when the window has closed a sheet.
/// </summary>
public event Action OnSheetEnd
{
add => ApiEventManager.AddEvent("browserWindow-sheet-end", Id, _sheetEnd, value);
remove => ApiEventManager.RemoveEvent("browserWindow-sheet-end", Id, _sheetEnd, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _sheetEnd;
/// <summary>
/// Emitted when the native new tab button is clicked.
/// </summary>
public event Action OnNewWindowForTab
{
add => ApiEventManager.AddEvent("browserWindow-new-window-for-tab", Id, _newWindowForTab, value);
remove => ApiEventManager.RemoveEvent("browserWindow-new-window-for-tab", Id, _newWindowForTab, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _newWindowForTab;
internal BrowserWindow(int id)
{
Id = id;
@@ -468,7 +407,7 @@ public class BrowserWindow : ApiBase
/// <param name="aspectRatio">The aspect ratio to maintain for some portion of the content view.</param>
/// <param name="extraSize">The extra size not to be included while maintaining the aspect ratio.</param>
public void SetAspectRatio(double aspectRatio, Size extraSize) =>
this.CallMethod2(aspectRatio, JObject.FromObject(extraSize, _jsonSerializer));
this.CallMethod2(aspectRatio, extraSize);
/// <summary>
/// This will make a window maintain an aspect ratio. The extra size allows a developer to have space,
@@ -485,7 +424,7 @@ public class BrowserWindow : ApiBase
/// <param name="aspectRatio">The aspect ratio to maintain for some portion of the content view.</param>
/// <param name="extraSize">The extra size not to be included while maintaining the aspect ratio.</param>
public void SetAspectRatio(int aspectRatio, Size extraSize) =>
this.CallMethod2(aspectRatio, JObject.FromObject(extraSize, _jsonSerializer));
this.CallMethod2(aspectRatio, extraSize);
/// <summary>
/// Uses Quick Look to preview a file at a given path.
@@ -514,14 +453,14 @@ public class BrowserWindow : ApiBase
/// Resizes and moves the window to the supplied bounds
/// </summary>
/// <param name="bounds"></param>
public void SetBounds(Rectangle bounds) => this.CallMethod1(JObject.FromObject(bounds, _jsonSerializer));
public void SetBounds(Rectangle bounds) => this.CallMethod1(bounds);
/// <summary>
/// Resizes and moves the window to the supplied bounds
/// </summary>
/// <param name="bounds"></param>
/// <param name="animate"></param>
public void SetBounds(Rectangle bounds, bool animate) => this.CallMethod2(JObject.FromObject(bounds, _jsonSerializer), animate);
public void SetBounds(Rectangle bounds, bool animate) => this.CallMethod2(bounds, animate);
/// <summary>
/// Gets the bounds asynchronous.
@@ -533,14 +472,14 @@ public class BrowserWindow : ApiBase
/// Resizes and moves the windows client area (e.g. the web page) to the supplied bounds.
/// </summary>
/// <param name="bounds"></param>
public void SetContentBounds(Rectangle bounds) => this.CallMethod1(JObject.FromObject(bounds, _jsonSerializer));
public void SetContentBounds(Rectangle bounds) => this.CallMethod1(bounds);
/// <summary>
/// Resizes and moves the windows client area (e.g. the web page) to the supplied bounds.
/// </summary>
/// <param name="bounds"></param>
/// <param name="animate"></param>
public void SetContentBounds(Rectangle bounds, bool animate) => this.CallMethod2(JObject.FromObject(bounds, _jsonSerializer), animate);
public void SetContentBounds(Rectangle bounds, bool animate) => this.CallMethod2(bounds, animate);
/// <summary>
/// Gets the content bounds asynchronous.
@@ -748,10 +687,10 @@ public class BrowserWindow : ApiBase
{
// Workaround Windows 10 / Electron Bug
// https://github.com/electron/electron/issues/4045
if (isWindows10())
{
x = x - 7;
}
//if (isWindows10())
//{
// x = x - 7;
//}
this.CallMethod2(x, y);
}
@@ -765,10 +704,11 @@ public class BrowserWindow : ApiBase
{
// Workaround Windows 10 / Electron Bug
// https://github.com/electron/electron/issues/4045
if (isWindows10())
{
x = x - 7;
}
//if (isWindows10())
//{
// x = x - 7;
//}
this.CallMethod3(x, y, animate);
}
@@ -893,7 +833,7 @@ public class BrowserWindow : ApiBase
/// </summary>
/// <param name="url"></param>
/// <param name="options"></param>
public void LoadURL(string url, LoadURLOptions options) => this.CallMethod2(url, JObject.FromObject(options, _jsonSerializer));
public void LoadURL(string url, LoadURLOptions options) => this.CallMethod2(url, options);
/// <summary>
/// Same as webContents.reload.
@@ -906,7 +846,14 @@ public class BrowserWindow : ApiBase
/// <value>
/// The menu items.
/// </value>
public IReadOnlyCollection<MenuItem> MenuItems { get { return _items.AsReadOnly(); } }
public IReadOnlyCollection<MenuItem> MenuItems
{
get
{
return _items.AsReadOnly();
}
}
private List<MenuItem> _items = new List<MenuItem>();
/// <summary>
@@ -917,13 +864,13 @@ public class BrowserWindow : ApiBase
public void SetMenu(MenuItem[] menuItems)
{
menuItems.AddMenuItemsId();
this.CallMethod1(JArray.FromObject(menuItems, _jsonSerializer));
this.CallMethod1(menuItems);
_items.AddRange(menuItems);
BridgeConnector.Socket.Off("windowMenuItemClicked");
BridgeConnector.Socket.On("windowMenuItemClicked", (id) =>
BridgeConnector.Socket.On<string>("windowMenuItemClicked", (id) =>
{
MenuItem menuItem = _items.GetMenuItem(id.ToString());
MenuItem menuItem = _items.GetMenuItem(id);
menuItem?.Click();
});
}
@@ -959,7 +906,7 @@ public class BrowserWindow : ApiBase
/// <param name="progress"></param>
/// <param name="progressBarOptions"></param>
public void SetProgressBar(double progress, ProgressBarOptions progressBarOptions) =>
this.CallMethod2(progress, JObject.FromObject(progressBarOptions, _jsonSerializer));
this.CallMethod2(progress, progressBarOptions);
/// <summary>
/// Sets whether the window should have a shadow. On Windows and Linux does nothing.
@@ -981,7 +928,14 @@ public class BrowserWindow : ApiBase
/// <value>
/// The thumbar buttons.
/// </value>
public IReadOnlyCollection<ThumbarButton> ThumbarButtons { get { return _thumbarButtons.AsReadOnly(); } }
public IReadOnlyCollection<ThumbarButton> ThumbarButtons
{
get
{
return _thumbarButtons.AsReadOnly();
}
}
private List<ThumbarButton> _thumbarButtons = new List<ThumbarButton>();
/// <summary>
@@ -998,28 +952,23 @@ public class BrowserWindow : ApiBase
/// <returns>Whether the buttons were added successfully.</returns>
public Task<bool> SetThumbarButtonsAsync(ThumbarButton[] thumbarButtons)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
var tcs = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("browserWindowSetThumbarButtons-completed", (success) =>
{
BridgeConnector.Socket.Off("browserWindowSetThumbarButtons-completed");
taskCompletionSource.SetResult((bool)success);
});
BridgeConnector.Socket.Once<bool>("browserWindowSetThumbarButtons-completed", tcs.SetResult);
thumbarButtons.AddThumbarButtonsId();
BridgeConnector.Socket.Emit("browserWindowSetThumbarButtons", Id, JArray.FromObject(thumbarButtons, _jsonSerializer));
BridgeConnector.Socket.Emit("browserWindowSetThumbarButtons", Id, thumbarButtons);
_thumbarButtons.Clear();
_thumbarButtons.AddRange(thumbarButtons);
BridgeConnector.Socket.Off("thumbarButtonClicked");
BridgeConnector.Socket.On("thumbarButtonClicked", (id) =>
BridgeConnector.Socket.On<string>("thumbarButtonClicked", (id) =>
{
ThumbarButton thumbarButton = _thumbarButtons.GetThumbarButton(id.ToString());
ThumbarButton thumbarButton = _thumbarButtons.GetThumbarButton(id);
thumbarButton?.Click();
});
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -1043,7 +992,7 @@ public class BrowserWindow : ApiBase
/// If one of those properties is not set, then neither will be used.
/// </summary>
/// <param name="options"></param>
public void SetAppDetails(AppDetailsOptions options) => this.CallMethod1(JObject.FromObject(options, _jsonSerializer));
public void SetAppDetails(AppDetailsOptions options) => this.CallMethod1(options);
/// <summary>
/// Same as webContents.showDefinitionForSelection().
@@ -1123,7 +1072,17 @@ public class BrowserWindow : ApiBase
/// passing null will turn current window into a top-level window.
/// </summary>
/// <param name="parent"></param>
public void SetParentWindow(BrowserWindow parent) => this.CallMethod1(JObject.FromObject(parent, _jsonSerializer));
public void SetParentWindow(BrowserWindow parent)
{
if (parent == null)
{
BridgeConnector.Socket.Emit("browserWindowSetParentWindow", Id, null);
}
else
{
BridgeConnector.Socket.Emit("browserWindowSetParentWindow", Id, parent);
}
}
/// <summary>
/// The parent window.
@@ -1185,10 +1144,4 @@ public class BrowserWindow : ApiBase
// This message name does not match the default ApiBase naming convention.
BridgeConnector.Socket.Emit("browserWindow-setBrowserView", Id, browserView.Id);
}
private readonly JsonSerializer _jsonSerializer = new()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
}

View File

@@ -1,20 +1,25 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ElectronNET.API.Entities;
using ElectronNET.API.Serialization;
using System.Text.Json;
using System.Threading.Tasks;
// ReSharper disable InconsistentNaming
namespace ElectronNET.API
{
/// <summary>
/// Perform copy and paste operations on the system clipboard.
/// </summary>
public sealed class Clipboard
public sealed class Clipboard: ApiBase
{
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.DashesLowerFirst;
protected override SocketTaskMessageNameTypes SocketTaskMessageNameType => SocketTaskMessageNameTypes.DashesLowerFirst;
private static Clipboard _clipboard;
private static object _syncRoot = new object();
internal Clipboard() { }
internal Clipboard()
{
}
internal static Clipboard Instance
{
@@ -40,21 +45,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 = "")
{
var taskCompletionSource = new TaskCompletionSource<string>();
BridgeConnector.Socket.On("clipboard-readText-Completed", (text) =>
{
BridgeConnector.Socket.Off("clipboard-readText-Completed");
taskCompletionSource.SetResult(text.ToString());
});
BridgeConnector.Socket.Emit("clipboard-readText", type);
return taskCompletionSource.Task;
}
public Task<string> ReadTextAsync(string type = "") => GetPropertyAsync<string>(type);
/// <summary>
/// Writes the text into the clipboard as plain text.
@@ -71,21 +62,7 @@ namespace ElectronNET.API
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public Task<string> ReadHTMLAsync(string type = "")
{
var taskCompletionSource = new TaskCompletionSource<string>();
BridgeConnector.Socket.On("clipboard-readHTML-Completed", (text) =>
{
BridgeConnector.Socket.Off("clipboard-readHTML-Completed");
taskCompletionSource.SetResult(text.ToString());
});
BridgeConnector.Socket.Emit("clipboard-readHTML", type);
return taskCompletionSource.Task;
}
public Task<string> ReadHTMLAsync(string type = "") => GetPropertyAsync<string>(type);
/// <summary>
/// Writes markup to the clipboard.
@@ -102,21 +79,7 @@ namespace ElectronNET.API
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public Task<string> ReadRTFAsync(string type = "")
{
var taskCompletionSource = new TaskCompletionSource<string>();
BridgeConnector.Socket.On("clipboard-readRTF-Completed", (text) =>
{
BridgeConnector.Socket.Off("clipboard-readRTF-Completed");
taskCompletionSource.SetResult(text.ToString());
});
BridgeConnector.Socket.Emit("clipboard-readRTF", type);
return taskCompletionSource.Task;
}
public Task<string> ReadRTFAsync(string type = "") => GetPropertyAsync<string>(type);
/// <summary>
/// Writes the text into the clipboard in RTF.
@@ -125,7 +88,7 @@ namespace ElectronNET.API
/// <param name="type"></param>
public void WriteRTF(string text, string type = "")
{
BridgeConnector.Socket.Emit("clipboard-writeHTML", text, type);
BridgeConnector.Socket.Emit("clipboard-writeRTF", text, type);
}
/// <summary>
@@ -134,21 +97,7 @@ namespace ElectronNET.API
/// be empty strings when the bookmark is unavailable.
/// </summary>
/// <returns></returns>
public Task<ReadBookmark> ReadBookmarkAsync()
{
var taskCompletionSource = new TaskCompletionSource<ReadBookmark>();
BridgeConnector.Socket.On("clipboard-readBookmark-Completed", (bookmark) =>
{
BridgeConnector.Socket.Off("clipboard-readBookmark-Completed");
taskCompletionSource.SetResult(((JObject)bookmark).ToObject<ReadBookmark>());
});
BridgeConnector.Socket.Emit("clipboard-readBookmark");
return taskCompletionSource.Task;
}
public Task<ReadBookmark> ReadBookmarkAsync() => GetPropertyAsync<ReadBookmark>();
/// <summary>
/// Writes the title and url into the clipboard as a bookmark.
@@ -171,21 +120,7 @@ namespace ElectronNET.API
/// find pasteboard whenever the application is activated.
/// </summary>
/// <returns></returns>
public Task<string> ReadFindTextAsync()
{
var taskCompletionSource = new TaskCompletionSource<string>();
BridgeConnector.Socket.On("clipboard-readFindText-Completed", (text) =>
{
BridgeConnector.Socket.Off("clipboard-readFindText-Completed");
taskCompletionSource.SetResult(text.ToString());
});
BridgeConnector.Socket.Emit("clipboard-readFindText");
return taskCompletionSource.Task;
}
public Task<string> ReadFindTextAsync() => GetPropertyAsync<string>();
/// <summary>
/// macOS: Writes the text into the find pasteboard as plain text. This method uses
@@ -211,21 +146,7 @@ namespace ElectronNET.API
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public Task<string[]> AvailableFormatsAsync(string type = "")
{
var taskCompletionSource = new TaskCompletionSource<string[]>();
BridgeConnector.Socket.On("clipboard-availableFormats-Completed", (formats) =>
{
BridgeConnector.Socket.Off("clipboard-availableFormats-Completed");
taskCompletionSource.SetResult(((JArray)formats).ToObject<string[]>());
});
BridgeConnector.Socket.Emit("clipboard-availableFormats", type);
return taskCompletionSource.Task;
}
public Task<string[]> AvailableFormatsAsync(string type = "") => GetPropertyAsync<string[]>(type);
/// <summary>
/// Writes data to the clipboard.
@@ -234,7 +155,7 @@ namespace ElectronNET.API
/// <param name="type"></param>
public void Write(Data data, string type = "")
{
BridgeConnector.Socket.Emit("clipboard-write", JObject.FromObject(data, _jsonSerializer), type);
BridgeConnector.Socket.Emit("clipboard-write", data, type);
}
/// <summary>
@@ -242,25 +163,8 @@ namespace ElectronNET.API
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public Task<NativeImage> ReadImageAsync(string type = "")
{
var taskCompletionSource = new TaskCompletionSource<NativeImage>();
public Task<NativeImage> ReadImageAsync(string type = "") => GetPropertyAsync<NativeImage>(type);
BridgeConnector.Socket.On("clipboard-readImage-Completed", (image) =>
{
BridgeConnector.Socket.Off("clipboard-readImage-Completed");
var nativeImage = ((JObject)image).ToObject<NativeImage>();
taskCompletionSource.SetResult(nativeImage);
});
BridgeConnector.Socket.Emit("clipboard-readImage", type);
return taskCompletionSource.Task;
}
/// <summary>
/// Writes an image to the clipboard.
/// </summary>
@@ -268,14 +172,7 @@ namespace ElectronNET.API
/// <param name="type"></param>
public void WriteImage(NativeImage image, string type = "")
{
BridgeConnector.Socket.Emit("clipboard-writeImage", JsonConvert.SerializeObject(image), type);
BridgeConnector.Socket.Emit("clipboard-writeImage", JsonSerializer.Serialize(image, ElectronJson.Options), type);
}
private JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
}
}
}

View File

@@ -8,7 +8,9 @@ namespace ElectronNET.API
/// </summary>
public sealed class CommandLine
{
internal CommandLine() { }
internal CommandLine()
{
}
internal static CommandLine Instance
{
@@ -66,22 +68,17 @@ 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))
public async Task<bool> HasSwitchAsync(string switchName, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
var taskCompletionSource = new TaskCompletionSource<bool>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
var tcs = new TaskCompletionSource<bool>();
using (cancellationToken.Register(() => tcs.TrySetCanceled()))
{
BridgeConnector.Socket.On("appCommandLineHasSwitchCompleted", (result) =>
{
BridgeConnector.Socket.Off("appCommandLineHasSwitchCompleted");
taskCompletionSource.SetResult((bool)result);
});
BridgeConnector.Socket.Once<bool>("appCommandLineHasSwitchCompleted", tcs.SetResult);
BridgeConnector.Socket.Emit("appCommandLineHasSwitch", switchName);
return await taskCompletionSource.Task.ConfigureAwait(false);
return await tcs.Task.ConfigureAwait(false);
}
}
@@ -94,23 +91,18 @@ 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))
public async Task<string> GetSwitchValueAsync(string switchName, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
var taskCompletionSource = new TaskCompletionSource<string>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
var tcs = new TaskCompletionSource<string>();
using (cancellationToken.Register(() => tcs.TrySetCanceled()))
{
BridgeConnector.Socket.On("appCommandLineGetSwitchValueCompleted", (result) =>
{
BridgeConnector.Socket.Off("appCommandLineGetSwitchValueCompleted");
taskCompletionSource.SetResult((string)result);
});
BridgeConnector.Socket.Once<string>("appCommandLineGetSwitchValueCompleted", tcs.SetResult);
BridgeConnector.Socket.Emit("appCommandLineGetSwitchValue", switchName);
return await taskCompletionSource.Task.ConfigureAwait(false);
return await tcs.Task.ConfigureAwait(false);
}
}
}
}
}

View File

@@ -1,9 +1,7 @@
using System;
using System.Threading.Tasks;
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ElectronNET.API.Serialization;
using System;
using System.Text.Json;
namespace ElectronNET.API
{
@@ -34,16 +32,21 @@ namespace ElectronNET.API
{
if (_changed == null)
{
BridgeConnector.Socket.On("webContents-session-cookies-changed" + Id, (args) =>
BridgeConnector.Socket.On<JsonElement>("webContents-session-cookies-changed" + Id, (args) =>
{
Cookie cookie = ((JArray)args)[0].ToObject<Cookie>();
CookieChangedCause cause = ((JArray)args)[1].ToObject<CookieChangedCause>();
bool removed = ((JArray)args)[2].ToObject<bool>();
var e = args.EnumerateArray().GetEnumerator();
e.MoveNext();
var cookie = e.Current.Deserialize<Cookie>(ElectronJson.Options);
e.MoveNext();
var cause = e.Current.Deserialize<CookieChangedCause>(ElectronJson.Options);
e.MoveNext();
var removed = e.Current.GetBoolean();
_changed(cookie, cause, removed);
});
BridgeConnector.Socket.Emit("register-webContents-session-cookies-changed", Id);
}
_changed += value;
}
remove
@@ -57,11 +60,6 @@ namespace ElectronNET.API
private event Action<Cookie, CookieChangedCause, bool> _changed;
private JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
}
}
}

View File

@@ -1,9 +1,6 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ElectronNET.API.Entities;
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
namespace ElectronNET.API
@@ -16,7 +13,9 @@ namespace ElectronNET.API
private static Dialog _dialog;
private static object _syncRoot = new object();
internal Dialog() { }
internal Dialog()
{
}
internal static Dialog Instance
{
@@ -26,7 +25,7 @@ namespace ElectronNET.API
{
lock (_syncRoot)
{
if(_dialog == null)
if (_dialog == null)
{
_dialog = new Dialog();
}
@@ -47,23 +46,16 @@ namespace ElectronNET.API
/// <returns>An array of file paths chosen by the user</returns>
public Task<string[]> ShowOpenDialogAsync(BrowserWindow browserWindow, OpenDialogOptions options)
{
var taskCompletionSource = new TaskCompletionSource<string[]>();
var tcs = new TaskCompletionSource<string[]>();
var guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("showOpenDialogComplete" + guid, (filePaths) =>
{
BridgeConnector.Socket.Off("showOpenDialogComplete" + guid);
BridgeConnector.Socket.Once<string[]>("showOpenDialogComplete" + guid, tcs.SetResult);
BridgeConnector.Socket.Emit("showOpenDialog",
browserWindow,
options,
guid);
var result = ((JArray)filePaths).ToObject<string[]>();
taskCompletionSource.SetResult(result);
});
BridgeConnector.Socket.Emit("showOpenDialog",
JObject.FromObject(browserWindow, _jsonSerializer),
JObject.FromObject(options, _jsonSerializer), guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -74,22 +66,16 @@ 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 taskCompletionSource = new TaskCompletionSource<string>();
var tcs = new TaskCompletionSource<string>();
var guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("showSaveDialogComplete" + guid, (filename) =>
{
BridgeConnector.Socket.Off("showSaveDialogComplete" + guid);
taskCompletionSource.SetResult(filename.ToString());
});
BridgeConnector.Socket.Once<string>("showSaveDialogComplete" + guid, tcs.SetResult);
BridgeConnector.Socket.Emit("showSaveDialog",
JObject.FromObject(browserWindow, _jsonSerializer),
JObject.FromObject(options, _jsonSerializer),
guid);
browserWindow,
options,
guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -143,35 +129,39 @@ 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 taskCompletionSource = new TaskCompletionSource<MessageBoxResult>();
var tcs = new TaskCompletionSource<MessageBoxResult>();
var guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("showMessageBoxComplete" + guid, (args) =>
BridgeConnector.Socket.Once<JsonElement>("showMessageBoxComplete" + guid, (args) =>
{
BridgeConnector.Socket.Off("showMessageBoxComplete" + guid);
// 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();
var result = ((JArray)args);
taskCompletionSource.SetResult(new MessageBoxResult
tcs.SetResult(new MessageBoxResult
{
Response = (int)result.First,
CheckboxChecked = (bool)result.Last
Response = response,
CheckboxChecked = checkbox
});
});
if (browserWindow == null)
{
BridgeConnector.Socket.Emit("showMessageBox", JObject.FromObject(messageBoxOptions, _jsonSerializer), guid);
} else
BridgeConnector.Socket.Emit("showMessageBox", messageBoxOptions, guid);
}
else
{
BridgeConnector.Socket.Emit("showMessageBox",
JObject.FromObject(browserWindow, _jsonSerializer),
JObject.FromObject(messageBoxOptions, _jsonSerializer),
BridgeConnector.Socket.Emit("showMessageBox",
browserWindow,
messageBoxOptions,
guid);
}
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -211,28 +201,18 @@ namespace ElectronNET.API
/// <returns></returns>
public Task ShowCertificateTrustDialogAsync(BrowserWindow browserWindow, CertificateTrustDialogOptions options)
{
var taskCompletionSource = new TaskCompletionSource<object>();
var tcs = new TaskCompletionSource<object>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("showCertificateTrustDialogComplete" + guid, () =>
{
BridgeConnector.Socket.Off("showCertificateTrustDialogComplete" + guid);
taskCompletionSource.SetResult(null);
});
BridgeConnector.Socket.Once("showCertificateTrustDialogComplete" + guid, () => tcs.SetResult(null));
BridgeConnector.Socket.Emit("showCertificateTrustDialog",
JObject.FromObject(browserWindow, _jsonSerializer),
JObject.FromObject(options, _jsonSerializer),
browserWindow,
options,
guid);
return taskCompletionSource.Task;
return tcs.Task;
}
private JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
}
}

View File

@@ -1,11 +1,10 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using ElectronNET.API.Entities;
using ElectronNET.API.Extensions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ElectronNET.API.Serialization;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace ElectronNET.API
{
@@ -54,18 +53,13 @@ namespace ElectronNET.API
{
cancellationToken.ThrowIfCancellationRequested();
var taskCompletionSource = new TaskCompletionSource<int>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
var tcs = new TaskCompletionSource<int>();
using (cancellationToken.Register(() => tcs.TrySetCanceled()))
{
BridgeConnector.Socket.On("dock-bounce-completed", (id) =>
{
BridgeConnector.Socket.Off("dock-bounce-completed");
taskCompletionSource.SetResult((int) id);
});
BridgeConnector.Socket.Once<int>("dock-bounce-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("dock-bounce", type.GetDescription());
return await taskCompletionSource.Task
return await tcs.Task
.ConfigureAwait(false);
}
}
@@ -106,18 +100,13 @@ namespace ElectronNET.API
{
cancellationToken.ThrowIfCancellationRequested();
var taskCompletionSource = new TaskCompletionSource<string>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
var tcs = new TaskCompletionSource<string>();
using (cancellationToken.Register(() => tcs.TrySetCanceled()))
{
BridgeConnector.Socket.On("dock-getBadge-completed", (text) =>
{
BridgeConnector.Socket.Off("dock-getBadge-completed");
taskCompletionSource.SetResult((string) text);
});
BridgeConnector.Socket.Once<string>("dock-getBadge-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("dock-getBadge");
return await taskCompletionSource.Task
return await tcs.Task
.ConfigureAwait(false);
}
}
@@ -148,18 +137,13 @@ namespace ElectronNET.API
{
cancellationToken.ThrowIfCancellationRequested();
var taskCompletionSource = new TaskCompletionSource<bool>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
var tcs = new TaskCompletionSource<bool>();
using (cancellationToken.Register(() => tcs.TrySetCanceled()))
{
BridgeConnector.Socket.On("dock-isVisible-completed", (isVisible) =>
{
BridgeConnector.Socket.Off("dock-isVisible-completed");
taskCompletionSource.SetResult((bool) isVisible);
});
BridgeConnector.Socket.Once<bool>("dock-isVisible-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("dock-isVisible");
return await taskCompletionSource.Task
return await tcs.Task
.ConfigureAwait(false);
}
}
@@ -170,7 +154,14 @@ namespace ElectronNET.API
/// <value>
/// The menu items.
/// </value>
public IReadOnlyCollection<MenuItem> MenuItems { get { return _items.AsReadOnly(); } }
public IReadOnlyCollection<MenuItem> MenuItems
{
get
{
return _items.AsReadOnly();
}
}
private List<MenuItem> _items = new List<MenuItem>();
/// <summary>
@@ -179,15 +170,15 @@ namespace ElectronNET.API
public void SetMenu(MenuItem[] menuItems)
{
menuItems.AddMenuItemsId();
BridgeConnector.Socket.Emit("dock-setMenu", JArray.FromObject(menuItems, _jsonSerializer));
BridgeConnector.Socket.Emit("dock-setMenu", new[] { menuItems });
_items.AddRange(menuItems);
BridgeConnector.Socket.Off("dockMenuItemClicked");
BridgeConnector.Socket.On("dockMenuItemClicked", (id) => {
MenuItem menuItem = _items.GetMenuItem(id.ToString());
BridgeConnector.Socket.On<string>("dockMenuItemClicked", (id) =>
{
MenuItem menuItem = _items.GetMenuItem(id);
menuItem?.Click();
});
}
/// <summary>
@@ -198,18 +189,13 @@ namespace ElectronNET.API
{
cancellationToken.ThrowIfCancellationRequested();
var taskCompletionSource = new TaskCompletionSource<Menu>();
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
var tcs = new TaskCompletionSource<Menu>();
using (cancellationToken.Register(() => tcs.TrySetCanceled()))
{
BridgeConnector.Socket.On("dock-getMenu-completed", (menu) =>
{
BridgeConnector.Socket.Off("dock-getMenu-completed");
taskCompletionSource.SetResult(((JObject)menu).ToObject<Menu>());
});
BridgeConnector.Socket.Once<Menu>("dock-getMenu-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("dock-getMenu");
return await taskCompletionSource.Task
return await tcs.Task
.ConfigureAwait(false);
}
}
@@ -223,10 +209,6 @@ namespace ElectronNET.API
BridgeConnector.Socket.Emit("dock-setIcon", image);
}
private JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
}
}
}

View File

@@ -8,62 +8,134 @@
/// <summary>
/// Communicate asynchronously from the main process to renderer processes.
/// </summary>
public static IpcMain IpcMain { get { return IpcMain.Instance; } }
public static IpcMain IpcMain
{
get
{
return IpcMain.Instance;
}
}
/// <summary>
/// Control your application's event lifecycle.
/// </summary>
public static App App { get { return App.Instance; } }
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; } }
public static AutoUpdater AutoUpdater
{
get
{
return AutoUpdater.Instance;
}
}
/// <summary>
/// Control your windows.
/// </summary>
public static WindowManager WindowManager { get { return WindowManager.Instance; } }
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; } }
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; } }
public static Dialog Dialog
{
get
{
return Dialog.Instance;
}
}
/// <summary>
/// Create OS desktop notifications
/// </summary>
public static Notification Notification { get { return Notification.Instance; } }
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; } }
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; } }
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; } }
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; } }
public static Screen Screen
{
get
{
return Screen.Instance;
}
}
/// <summary>
/// Perform copy and paste operations on the system clipboard.
/// </summary>
public static Clipboard Clipboard { get { return Clipboard.Instance; } }
public static Clipboard Clipboard
{
get
{
return Clipboard.Instance;
}
}
/// <summary>
/// Allows you to execute native JavaScript/TypeScript code from the host process.
@@ -72,26 +144,56 @@
/// ElectronHostHook directory:
/// <c>electronize add HostHook</c>
/// </summary>
public static HostHook HostHook { get { return HostHook.Instance; } }
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; } }
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; } }
public static NativeTheme NativeTheme
{
get
{
return NativeTheme.Instance;
}
}
/// <summary>
/// Control your app in the macOS dock.
/// </summary>
public static Dock Dock { get { return Dock.Instance; } }
public static Dock Dock
{
get
{
return Dock.Instance;
}
}
/// <summary>
/// Electeon extensions to the Nodejs process object.
/// </summary>
public static Process Process { get { return Process.Instance; } }
public static Process Process
{
get
{
return Process.Instance;
}
}
}
}

View File

@@ -28,6 +28,6 @@ namespace ElectronNET.API.Entities
/// <summary>
/// Gets or sets the dataURL
/// </summary>
public string DataUrl { get; set; }
public string DataUrl { get; set; }
}
}

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ElectronNET.API.Entities
namespace ElectronNET.API.Entities
{
/// <summary>
///

View File

@@ -1,7 +1,7 @@
using ElectronNET.Converter;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using ElectronNET.Converter;
using System.ComponentModel;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
@@ -213,7 +213,6 @@ namespace ElectronNET.API.Entities
/// The style of window title bar. Default is default. Possible values are:
/// 'default' | 'hidden' | 'hiddenInset' | 'customButtonsOnHover'
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public TitleBarStyle TitleBarStyle { get; set; }
/// <summary>
@@ -256,7 +255,6 @@ namespace ElectronNET.API.Entities
/// appearance-based, light, dark, titlebar, selection, menu, popover, sidebar,
/// medium-light or ultra-dark.
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public Vibrancy Vibrancy { get; set; }
/// <summary>
@@ -294,3 +292,7 @@ namespace ElectronNET.API.Entities
public string ProxyCredentials { get; set; }
}
}

View File

@@ -8,7 +8,7 @@
/// <summary>
/// Percentage of CPU used since the last call to getCPUUsage. First call returns 0.
/// </summary>
public int PercentCPUUsage { get; set; }
public double PercentCPUUsage { get; set; }
/// <summary>
/// The number of average idle cpu wakeups per second since the last call to

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ElectronNET.API.Entities
namespace ElectronNET.API.Entities
{
/// <summary>
/// Provide metadata about the current loaded Chrome extension

View File

@@ -1,12 +1,14 @@
namespace ElectronNET.API.Entities {
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class Cookie {
public class Cookie
{
/// <summary>
/// The name of the cookie.
/// </summary>
public string Name { get; set;}
public string Name { get; set; }
/// <summary>
/// The value of the cookie.
@@ -26,7 +28,7 @@
/// <summary>
/// (optional) - The path of the cookie.
/// </summary>
public string Path { get; set; }
public string Path { get; set; }
/// <summary>
/// (optional) - Whether the cookie is marked as secure.
@@ -36,7 +38,7 @@
/// <summary>
/// (optional) - Whether the cookie is marked as HTTP only.
/// </summary>
public bool HttpOnly { get; set; }
public bool HttpOnly { get; set; }
/// <summary>
/// (optional) - Whether the cookie is a session cookie or a persistent cookie with an expiration date.
@@ -48,4 +50,4 @@
/// </summary>
public long ExpirationDate { get; set; }
}
}
}

View File

@@ -1,17 +1,17 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace ElectronNET.API.Entities {
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
/// <summary>
/// The cause of the change
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public enum CookieChangedCause
public enum CookieChangedCause
{
/// <summary>
///The cookie was changed directly by a consumer's action.
/// </summary>
[JsonProperty("explicit")]
[JsonPropertyName("explicit")]
@explicit,
/// <summary>
@@ -32,7 +32,7 @@ namespace ElectronNET.API.Entities {
/// <summary>
/// The cookie was overwritten with an already-expired expiration date.
/// </summary>
[JsonProperty("expired_overwrite")]
[JsonPropertyName("expired_overwrite")]
expiredOverwrite
}
}
}

View File

@@ -1,10 +1,12 @@
using System.ComponentModel;
namespace ElectronNET.API.Entities {
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class CookieDetails {
public class CookieDetails
{
/// <summary>
/// The URL to associate the cookie with. The callback will be rejected if the URL is invalid.
/// </summary>
@@ -19,7 +21,7 @@ namespace ElectronNET.API.Entities {
/// <summary>
/// (optional) - The value of the cookie. Empty by default if omitted.
/// </summary>
[DefaultValue("")]
[DefaultValue("")]
public string Value { get; set; }
/// <summary>
@@ -31,13 +33,13 @@ namespace ElectronNET.API.Entities {
/// <summary>
/// (optional) - The path of the cookie. Empty by default if omitted.
/// </summary>
[DefaultValue("")]
[DefaultValue("")]
public string Path { get; set; }
/// <summary>
/// (optional) - Whether the cookie is marked as secure. Defaults to false.
/// </summary>
[DefaultValue(false)]
[DefaultValue(false)]
public bool Secure { get; set; }
/// <summary>
@@ -53,4 +55,4 @@ namespace ElectronNET.API.Entities {
[DefaultValue(0)]
public long ExpirationDate { get; set; }
}
}
}

View File

@@ -1,13 +1,9 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ElectronNET.API.Entities
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// </summary>
public class CookieFilter
public class CookieFilter
{
/// <summary>
/// (optional) - Retrieves cookies which are associated with url.Empty implies retrieving cookies of all URLs.
@@ -38,6 +34,5 @@ namespace ElectronNET.API.Entities
/// (optional) - Filters out session or persistent cookies.
/// </summary>
public bool Session { get; set; }
}
}
}

View File

@@ -41,7 +41,7 @@
/// <summary>
/// Unique identifier associated with the display.
/// </summary>
public string Id { get; set; }
public long Id { get; set; }
/// <summary>
/// true for an internal display and false for an external display.
@@ -61,7 +61,7 @@
/// <summary>
/// Output device's pixel scale factor.
/// </summary>
public int ScaleFactor { get; set; }
public double ScaleFactor { get; set; }
/// <summary>
/// Can be available, unavailable, unknown.

View File

@@ -1,10 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ElectronNET.API.Entities
namespace ElectronNET.API.Entities
{
/// <summary>
/// Docs: https://electronjs.org/docs/api/structures/extension

View File

@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
@@ -10,43 +11,43 @@ namespace ElectronNET.API.Entities
/// <summary>
/// Canvas.
/// </summary>
[JsonProperty("2d_canvas")]
[JsonPropertyName("2d_canvas")]
public string Canvas { get; set; }
/// <summary>
/// Flash.
/// </summary>
[JsonProperty("flash_3d")]
[JsonPropertyName("flash_3d")]
public string Flash3D { get; set; }
/// <summary>
/// Flash Stage3D.
/// </summary>
[JsonProperty("flash_stage3d")]
[JsonPropertyName("flash_stage3d")]
public string FlashStage3D { get; set; }
/// <summary>
/// Flash Stage3D Baseline profile.
/// </summary>
[JsonProperty("flash_stage3d_baseline")]
[JsonPropertyName("flash_stage3d_baseline")]
public string FlashStage3dBaseline { get; set; }
/// <summary>
/// Compositing.
/// </summary>
[JsonProperty("gpu_compositing")]
[JsonPropertyName("gpu_compositing")]
public string GpuCompositing { get; set; }
/// <summary>
/// Multiple Raster Threads.
/// </summary>
[JsonProperty("multiple_raster_threads")]
[JsonPropertyName("multiple_raster_threads")]
public string MultipleRasterThreads { get; set; }
/// <summary>
/// Native GpuMemoryBuffers.
/// </summary>
[JsonProperty("native_gpu_memory_buffers")]
[JsonPropertyName("native_gpu_memory_buffers")]
public string NativeGpuMemoryBuffers { get; set; }
/// <summary>
@@ -57,19 +58,19 @@ namespace ElectronNET.API.Entities
/// <summary>
/// Video Decode.
/// </summary>
[JsonProperty("video_decode")]
[JsonPropertyName("video_decode")]
public string VideoDecode { get; set; }
/// <summary>
/// Video Encode.
/// </summary>
[JsonProperty("video_encode")]
[JsonPropertyName("video_encode")]
public string VideoEncode { get; set; }
/// <summary>
/// VPx Video Decode.
/// </summary>
[JsonProperty("vpx_decode")]
[JsonPropertyName("vpx_decode")]
public string VpxDecode { get; set; }
/// <summary>

View File

@@ -9,10 +9,10 @@
/// 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

@@ -1,10 +1,9 @@
using Newtonsoft.Json.Converters;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace ElectronNET.API.Entities
{
using ElectronNET.Converter;
using System.Text.Json.Serialization;
/// <summary>
///
@@ -76,7 +75,8 @@ namespace ElectronNET.API.Entities
/// `touchScrollStarted`, `pointerDown`, `pointerUp`, `pointerMove`,
/// `pointerRawUpdate`, `pointerCancel` or `pointerCausedUaAction`.
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public InputEventType Type { get; set; }
}
}

View File

@@ -9,26 +9,32 @@ public enum InputEventType
///
/// </summary>
undefined,
/// <summary>
///
/// </summary>
mouseDown,
/// <summary>
///
/// </summary>
mouseUp,
/// <summary>
///
/// </summary>
mouseMove,
/// <summary>
///
/// </summary>
mouseEnter,
/// <summary>
///
/// </summary>
mouseLeave,
/// <summary>
///
/// </summary>

View File

@@ -1,5 +1,5 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
@@ -21,7 +21,7 @@ namespace ElectronNET.API.Entities
/// <summary>
/// One of the following: "tasks" | "frequent" | "recent" | "custom"
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public JumpListCategoryType Type { get; set; }
}
}
}

View File

@@ -1,5 +1,5 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
@@ -52,7 +52,8 @@ namespace ElectronNET.API.Entities
/// <summary>
/// One of the following: "task" | "separator" | "file"
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public JumpListItemType Type { get; set; }
}
}

View File

@@ -1,7 +1,5 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.ComponentModel;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
@@ -21,13 +19,11 @@ namespace ElectronNET.API.Entities
/// 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; }
@@ -101,3 +97,5 @@ namespace ElectronNET.API.Entities
public string Position { get; set; }
}
}

View File

@@ -1,5 +1,5 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
@@ -13,7 +13,6 @@ namespace ElectronNET.API.Entities
/// 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>
@@ -99,3 +98,5 @@ namespace ElectronNET.API.Entities
}
}
}

View File

@@ -1,12 +1,12 @@
using System;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
namespace ElectronNET.API.Entities
{
@@ -21,9 +21,9 @@ namespace ElectronNET.API.Entities
private static readonly Dictionary<string, float> ScaleFactorPairs = new Dictionary<string, float>
{
{"@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)
@@ -34,6 +34,7 @@ namespace ElectronNET.API.Entities
.Select(p => p.Value)
.FirstOrDefault();
}
private static Image BytesToImage(byte[] bytes)
{
var ms = new MemoryStream(bytes);
@@ -83,7 +84,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);
@@ -101,7 +102,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);
@@ -164,7 +165,7 @@ namespace ElectronNET.API.Entities
/// </summary>
public NativeImage Crop(Rectangle rect)
{
var images = new Dictionary<float,Image>();
var images = new Dictionary<float, Image>();
foreach (var image in _images)
{
images.Add(image.Key, Crop(rect.X, rect.Y, rect.Width, rect.Height, image.Key));
@@ -196,7 +197,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 CreateFromBufferOptions { ScaleFactor = options.ScaleFactor })
.GetScale(options.ScaleFactor);
}
else if (!string.IsNullOrEmpty(options.DataUrl))
@@ -225,7 +226,7 @@ namespace ElectronNET.API.Entities
/// </summary>
public byte[] GetBitmap(BitmapOptions options)
{
return ToBitmap(new ToBitmapOptions{ ScaleFactor = options.ScaleFactor });
return ToBitmap(new ToBitmapOptions { ScaleFactor = options.ScaleFactor });
}
/// <summary>
@@ -419,12 +420,13 @@ namespace ElectronNET.API.Entities
return codec;
}
}
return null;
}
internal Dictionary<float,string> GetAllScaledImages()
internal Dictionary<float, string> GetAllScaledImages()
{
var dict = new Dictionary<float,string>();
var dict = new Dictionary<float, string>();
try
{
foreach (var (scale, image) in _images)
@@ -436,7 +438,7 @@ namespace ElectronNET.API.Entities
{
Console.WriteLine(ex);
}
return dict;
}
@@ -450,4 +452,4 @@ namespace ElectronNET.API.Entities
return null;
}
}
}
}

View File

@@ -1,34 +1,39 @@
using System;
using ElectronNET.API.Serialization;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using Newtonsoft.Json;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
internal class NativeImageJsonConverter : JsonConverter
internal class NativeImageJsonConverter : JsonConverter<NativeImage>
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
public override void Write(Utf8JsonWriter writer, NativeImage value, JsonSerializerOptions options)
{
if (value is NativeImage nativeImage)
if (value is null)
{
var scaledImages = nativeImage.GetAllScaledImages();
serializer.Serialize(writer, scaledImages);
writer.WriteNullValue();
return;
}
var scaledImages = value.GetAllScaledImages();
JsonSerializer.Serialize(writer, scaledImages, ElectronJson.Options);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
public override NativeImage Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var dict = serializer.Deserialize<Dictionary<float, string>>(reader);
var dict = JsonSerializer.Deserialize<Dictionary<float, string>>(ref reader, ElectronJson.Options);
var newDictionary = new Dictionary<float, Image>();
foreach (var item in dict)
{
var bytes = Convert.FromBase64String(item.Value);
newDictionary.Add(item.Key, Image.FromStream(new MemoryStream(bytes)));
}
return new NativeImage(newDictionary);
}
public override bool CanConvert(Type objectType) => objectType == typeof(NativeImage);
}
}

View File

@@ -1,5 +1,5 @@
using Newtonsoft.Json;
using System;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
@@ -86,7 +86,7 @@ namespace ElectronNET.API.Entities
/// <value>
/// The show identifier.
/// </value>
[JsonProperty]
[JsonInclude]
internal string ShowID { get; set; }
/// <summary>
@@ -101,7 +101,7 @@ namespace ElectronNET.API.Entities
/// <value>
/// The click identifier.
/// </value>
[JsonProperty]
[JsonInclude]
internal string ClickID { get; set; }
/// <summary>
@@ -118,7 +118,7 @@ namespace ElectronNET.API.Entities
/// <value>
/// The close identifier.
/// </value>
[JsonProperty]
[JsonInclude]
internal string CloseID { get; set; }
/// <summary>
@@ -135,7 +135,7 @@ namespace ElectronNET.API.Entities
/// <value>
/// The reply identifier.
/// </value>
[JsonProperty]
[JsonInclude]
internal string ReplyID { get; set; }
/// <summary>
@@ -150,7 +150,7 @@ namespace ElectronNET.API.Entities
/// <value>
/// The action identifier.
/// </value>
[JsonProperty]
[JsonInclude]
internal string ActionID { get; set; }
/// <summary>

View File

@@ -1,5 +1,5 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
@@ -13,7 +13,7 @@ namespace ElectronNET.API.Entities
/// 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,5 +1,5 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
@@ -33,7 +33,6 @@ namespace ElectronNET.API.Entities
/// 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>
@@ -58,4 +57,5 @@ namespace ElectronNET.API.Entities
/// </example>
public FileFilter[] Filters { get; set; }
}
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.ComponentModel;
using System.ComponentModel;
namespace ElectronNET.API.Entities
{

View File

@@ -67,7 +67,7 @@ namespace ElectronNET.API.Entities
/// true for landscape, false for portrait.
/// </summary>
public bool Landscape { get; set; }
/// <summary>
/// The scale factor of the web page
/// </summary>
@@ -102,6 +102,5 @@ namespace ElectronNET.API.Entities
/// Dpi
/// </summary>
public PrintDpi Dpi { get; set; }
}
}

View File

@@ -1,5 +1,5 @@
using ElectronNET.Converter;
using Newtonsoft.Json;
using ElectronNET.Converter;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities;

View File

@@ -14,7 +14,7 @@ namespace ElectronNET.API.Entities
/// Name
/// </summary>
public string Description { get; set; }
/// <summary>
/// Status
/// </summary>
@@ -24,6 +24,5 @@ namespace ElectronNET.API.Entities
/// Is default
/// </summary>
public bool IsDefault { get; set; }
}
}

View File

@@ -1,7 +1,7 @@
namespace ElectronNET.API.Entities
{
/// <summary>
///
/// Process metrics information.
/// </summary>
public class ProcessMetric
{
@@ -21,11 +21,9 @@
public CPUUsage Cpu { get; set; }
/// <summary>
/// Creation time for this process. The time is represented as number of milliseconds since epoch.
/// Since the <see cref="PId"/> can be reused after a process dies, it is useful to use both the <see cref="PId"/>
/// and the <see cref="CreationTime"/> to uniquely identify a process.
/// Creation time for this process in milliseconds since Unix epoch. Can exceed Int32 range and may contain fractional milliseconds.
/// </summary>
public int CreationTime { get; set; }
public double CreationTime { get; set; }
/// <summary>
/// Memory information for the process.

View File

@@ -1,5 +1,5 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
@@ -11,7 +11,7 @@ namespace ElectronNET.API.Entities
/// <summary>
/// Mode for the progress bar. Can be 'none' | 'normal' | 'indeterminate' | 'error' | 'paused'.
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public ProgressBarMode Mode { get; set; }
}
}
}

View File

@@ -1,8 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ElectronNET.API.Entities
namespace ElectronNET.API.Entities
{
/// <summary>
///

View File

@@ -1,5 +1,5 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
@@ -28,7 +28,6 @@ namespace ElectronNET.API.Entities
/// Scheme of the authentication. Can be basic, digest, ntlm, negotiate.
/// Must be provided if removing by origin.
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public Scheme Scheme { get; set; }
/// <summary>
@@ -51,3 +50,5 @@ namespace ElectronNET.API.Entities
}
}
}

View File

@@ -8,35 +8,43 @@
/// <summary>
///
/// </summary>
public string Raw { get; set; }
public string Raw { get; set; }
/// <summary>
///
/// </summary>
public bool Loose { get; set; }
/// <summary>
///
/// </summary>
public SemVerOptions Options { get; set; }
/// <summary>
///
/// </summary>
public int Major { get; set; }
/// <summary>
///
/// </summary>
public int Minor { get; set; }
/// <summary>
///
/// </summary>
public int Patch { get; set; }
/// <summary>
///
/// </summary>
public string Version { get; set; }
/// <summary>
///
/// </summary>
public string[] Build { get; set; }
/// <summary>
///
/// </summary>
@@ -46,14 +54,16 @@
/// <summary>
///
/// </summary>
public class SemVerOptions {
public class SemVerOptions
{
/// <summary>
///
/// </summary>
public bool? Loose { get; set; }
/// <summary>
///
/// </summary>
public bool? IncludePrerelease { get; set; }
}
}
}

View File

@@ -1,6 +1,5 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
@@ -36,7 +35,6 @@ namespace ElectronNET.API.Entities
/// hidden - The button is not shown to the user.
/// noninteractive - The button is enabled but not interactive; no pressed button state is drawn.This value is intended for instances where the button is used in a notification.
/// </summary>
[JsonProperty("flags", ItemConverterType = typeof(StringEnumConverter))]
public ThumbarButtonFlag[] Flags { get; set; }
/// <summary>
@@ -58,4 +56,5 @@ namespace ElectronNET.API.Entities
Icon = icon;
}
}
}
}

View File

@@ -1,4 +1,5 @@
using Newtonsoft.Json;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Entities
{
@@ -10,7 +11,7 @@ namespace ElectronNET.API.Entities
/// <summary>
/// The default style
/// </summary>
[JsonProperty("default")]
[JsonPropertyName("default")]
defaultStyle,
/// <summary>

View File

@@ -15,7 +15,6 @@
/// </summary>
public void Cancel()
{
}
/// <summary>
@@ -23,7 +22,6 @@
/// </summary>
public void Dispose()
{
}
}
}
}

View File

@@ -9,7 +9,7 @@
/// The data is available as a Buffer, in the rawData field.
/// </summary>
public string Type { get; } = "rawData";
/// <summary>
/// The raw bytes of the post data in a Buffer.
/// </summary>

View File

@@ -27,8 +27,9 @@ namespace ElectronNET.API.Extensions
return ((DescriptionAttribute)attrs[0]).Description;
}
}
//If we have no description attribute, just return the ToString of the enum
return enumerationValue.ToString();
}
}
}
}

View File

@@ -56,7 +56,7 @@ namespace ElectronNET.API.Extensions
var menuItem = menuItems[index];
if (menuItem?.Submenu?.Length > 0)
{
if(menuItem.Type == MenuType.normal)
if (menuItem.Type == MenuType.normal)
{
menuItem.Type = MenuType.submenu;
}
@@ -68,4 +68,4 @@ namespace ElectronNET.API.Extensions
return menuItems;
}
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
namespace ElectronNET.API
@@ -12,7 +13,9 @@ namespace ElectronNET.API
private static GlobalShortcut _globalShortcut;
private static object _syncRoot = new object();
internal GlobalShortcut() { }
internal GlobalShortcut()
{
}
internal static GlobalShortcut Instance
{
@@ -50,11 +53,11 @@ namespace ElectronNET.API
_shortcuts.Add(accelerator, function);
BridgeConnector.Socket.Off("globalShortcut-pressed");
BridgeConnector.Socket.On("globalShortcut-pressed", (shortcut) =>
BridgeConnector.Socket.On<string>("globalShortcut-pressed", (shortcut) =>
{
if (_shortcuts.ContainsKey(shortcut.ToString()))
if (_shortcuts.TryGetValue(shortcut, out var action))
{
_shortcuts[shortcut.ToString()]();
action();
}
});
@@ -70,18 +73,12 @@ namespace ElectronNET.API
/// <returns>Whether this application has registered accelerator.</returns>
public Task<bool> IsRegisteredAsync(string accelerator)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("globalShortcut-isRegisteredCompleted", (isRegistered) =>
{
BridgeConnector.Socket.Off("globalShortcut-isRegisteredCompleted");
taskCompletionSource.SetResult((bool)isRegistered);
});
var tcs = new TaskCompletionSource<bool>();
BridgeConnector.Socket.Once<bool>("globalShortcut-isRegisteredCompleted", tcs.SetResult);
BridgeConnector.Socket.Emit("globalShortcut-isRegistered", accelerator);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>

View File

@@ -1,7 +1,6 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ElectronNET.API.Serialization;
using System;
using System.Text.Json;
using System.Threading.Tasks;
namespace ElectronNET.API
@@ -17,9 +16,11 @@ namespace ElectronNET.API
{
private static HostHook _electronHostHook;
private static object _syncRoot = new object();
string oneCallguid = Guid.NewGuid().ToString();
private string oneCallguid = Guid.NewGuid().ToString();
internal HostHook() { }
internal HostHook()
{
}
internal static HostHook Instance
{
@@ -47,10 +48,9 @@ namespace ElectronNET.API
/// <param name="arguments">Optional parameters.</param>
public void Call(string socketEventName, params dynamic[] arguments)
{
BridgeConnector.Socket.On(socketEventName + "Error" + oneCallguid, (result) =>
BridgeConnector.Socket.Once<string>(socketEventName + "Error" + oneCallguid, (result) =>
{
BridgeConnector.Socket.Off(socketEventName + "Error" + oneCallguid);
Electron.Dialog.ShowErrorBox("Host Hook Exception", result.ToString());
Electron.Dialog.ShowErrorBox("Host Hook Exception", result);
});
BridgeConnector.Socket.Emit(socketEventName, arguments, oneCallguid);
@@ -65,64 +65,37 @@ namespace ElectronNET.API
/// <returns></returns>
public Task<T> CallAsync<T>(string socketEventName, params dynamic[] arguments)
{
var taskCompletionSource = new TaskCompletionSource<T>();
var tcs = new TaskCompletionSource<T>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On(socketEventName + "Error" + guid, (result) =>
BridgeConnector.Socket.Once<string>(socketEventName + "Error" + guid, (result) =>
{
BridgeConnector.Socket.Off(socketEventName + "Error" + guid);
Electron.Dialog.ShowErrorBox("Host Hook Exception", result.ToString());
taskCompletionSource.SetException(new Exception($"Host Hook Exception {result}"));
Electron.Dialog.ShowErrorBox("Host Hook Exception", result);
tcs.SetException(new Exception($"Host Hook Exception {result}"));
});
BridgeConnector.Socket.On(socketEventName + "Complete" + guid, (result) =>
BridgeConnector.Socket.Once<JsonElement>(socketEventName + "Complete" + guid, (result) =>
{
BridgeConnector.Socket.Off(socketEventName + "Error" + guid);
BridgeConnector.Socket.Off(socketEventName + "Complete" + guid);
T data = default;
try
{
if (result.GetType().IsValueType || result is string)
{
data = (T)result;
}
else
{
var token = JToken.Parse(result.ToString());
if (token is JArray)
{
data = token.ToObject<T>();
}
else if (token is JObject)
{
data = token.ToObject<T>();
}
else
{
data = (T)result;
}
}
data = result.Deserialize<T>(ElectronJson.Options);
}
catch (Exception exception)
{
taskCompletionSource.SetException(exception);
//throw new InvalidCastException("Return value does not match with the generic type.", exception);
tcs.SetException(exception);
}
taskCompletionSource.SetResult(data);
tcs.SetResult(data);
});
BridgeConnector.Socket.Emit(socketEventName, arguments, guid);
return taskCompletionSource.Task;
return tcs.Task;
}
private JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
}
}

View File

@@ -1,10 +1,8 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ElectronNET.API.Serialization;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
namespace ElectronNET.API
@@ -17,17 +15,19 @@ namespace ElectronNET.API
private static IpcMain _ipcMain;
private static object _syncRoot = new object();
internal IpcMain() { }
internal IpcMain()
{
}
internal static IpcMain Instance
{
get
{
if(_ipcMain == null)
if (_ipcMain == null)
{
lock (_syncRoot)
{
if(_ipcMain == null)
if (_ipcMain == null)
{
_ipcMain = new IpcMain();
}
@@ -48,11 +48,11 @@ namespace ElectronNET.API
{
await BridgeConnector.Socket.Emit("registerIpcMainChannel", channel).ConfigureAwait(false);
BridgeConnector.Socket.Off(channel);
BridgeConnector.Socket.On(channel, (args) =>
BridgeConnector.Socket.On<JsonElement>(channel, (args) =>
{
List<object> objectArray = FormatArguments(args);
if(objectArray.Count == 1)
if (objectArray.Count == 1)
{
listener(objectArray.First());
}
@@ -63,19 +63,10 @@ namespace ElectronNET.API
});
}
private List<object> FormatArguments(object args)
private static List<object> FormatArguments(JsonElement args)
{
List<object> objectArray = ((JArray)args).ToObject<object[]>().ToList();
for (int index = 0; index < objectArray.Count; index++)
{
var item = objectArray[index];
if (item == null)
{
objectArray.Remove(item);
}
}
var objectArray = args.Deserialize<object[]>(ElectronJson.Options).ToList();
objectArray.RemoveAll(item => item is null);
return objectArray;
}
@@ -91,7 +82,8 @@ namespace ElectronNET.API
public void OnSync(string channel, Func<object, object> listener)
{
BridgeConnector.Socket.Emit("registerSyncIpcMainChannel", channel);
BridgeConnector.Socket.On(channel, (args) => {
BridgeConnector.Socket.On<JsonElement>(channel, (args) =>
{
List<object> objectArray = FormatArguments(args);
object parameter;
if (objectArray.Count == 1)
@@ -117,7 +109,7 @@ namespace ElectronNET.API
public void Once(string channel, Action<object> listener)
{
BridgeConnector.Socket.Emit("registerOnceIpcMainChannel", channel);
BridgeConnector.Socket.Once<object>(channel, (args) =>
BridgeConnector.Socket.Once<JsonElement>(channel, (args) =>
{
List<object> objectArray = FormatArguments(args);
@@ -152,32 +144,7 @@ namespace ElectronNET.API
/// <param name="data">Arguments data.</param>
public void Send(BrowserWindow browserWindow, string channel, params object[] data)
{
List<JObject> jobjects = new List<JObject>();
List<JArray> jarrays = new List<JArray>();
List<object> objects = new List<object>();
foreach (var parameterObject in data)
{
if(parameterObject.GetType().IsArray || parameterObject.GetType().IsGenericType && parameterObject is IEnumerable)
{
jarrays.Add(JArray.FromObject(parameterObject, _jsonSerializer));
} else if(parameterObject.GetType().IsClass && !parameterObject.GetType().IsPrimitive && !(parameterObject is string))
{
jobjects.Add(JObject.FromObject(parameterObject, _jsonSerializer));
} else if(parameterObject.GetType().IsPrimitive || (parameterObject is string))
{
objects.Add(parameterObject);
}
}
if(jobjects.Count > 0 || jarrays.Count > 0)
{
BridgeConnector.Socket.Emit("sendToIpcRenderer", JObject.FromObject(browserWindow, _jsonSerializer), channel, jarrays.ToArray(), jobjects.ToArray(), objects.ToArray());
}
else
{
BridgeConnector.Socket.Emit("sendToIpcRenderer", JObject.FromObject(browserWindow, _jsonSerializer), channel, data);
}
BridgeConnector.Socket.Emit("sendToIpcRenderer", browserWindow, channel, data);
}
/// <summary>
@@ -191,39 +158,9 @@ namespace ElectronNET.API
/// <param name="data">Arguments data.</param>
public void Send(BrowserView browserView, string channel, params object[] data)
{
List<JObject> jobjects = new List<JObject>();
List<JArray> jarrays = new List<JArray>();
List<object> objects = new List<object>();
foreach (var parameterObject in data)
{
if(parameterObject.GetType().IsArray || parameterObject.GetType().IsGenericType && parameterObject is IEnumerable)
{
jarrays.Add(JArray.FromObject(parameterObject, _jsonSerializer));
} else if(parameterObject.GetType().IsClass && !parameterObject.GetType().IsPrimitive && !(parameterObject is string))
{
jobjects.Add(JObject.FromObject(parameterObject, _jsonSerializer));
} else if(parameterObject.GetType().IsPrimitive || (parameterObject is string))
{
objects.Add(parameterObject);
}
}
if(jobjects.Count > 0 || jarrays.Count > 0)
{
BridgeConnector.Socket.Emit("sendToIpcRendererBrowserView", browserView.Id, channel, jarrays.ToArray(), jobjects.ToArray(), objects.ToArray());
}
else
{
BridgeConnector.Socket.Emit("sendToIpcRendererBrowserView", browserView.Id, channel, data);
}
BridgeConnector.Socket.Emit("sendToIpcRendererBrowserView", browserView.Id, channel, data);
}
private JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
}
}
}

View File

@@ -1,11 +1,10 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System.Collections.Generic;
using ElectronNET.API.Entities;
using ElectronNET.API.Extensions;
using System.Linq;
using ElectronNET.API.Serialization;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text.Json;
namespace ElectronNET.API
{
@@ -17,7 +16,9 @@ namespace ElectronNET.API
private static Menu _menu;
private static object _syncRoot = new object();
internal Menu() { }
internal Menu()
{
}
internal static Menu Instance
{
@@ -27,7 +28,7 @@ namespace ElectronNET.API
{
lock (_syncRoot)
{
if(_menu == null)
if (_menu == null)
{
_menu = new Menu();
}
@@ -44,7 +45,14 @@ namespace ElectronNET.API
/// <value>
/// The menu items.
/// </value>
public IReadOnlyCollection<MenuItem> MenuItems { get { return _menuItems.AsReadOnly(); } }
public IReadOnlyCollection<MenuItem> MenuItems
{
get
{
return _menuItems.AsReadOnly();
}
}
private List<MenuItem> _menuItems = new List<MenuItem>();
/// <summary>
@@ -58,12 +66,13 @@ namespace ElectronNET.API
menuItems.AddMenuItemsId();
menuItems.AddSubmenuTypes();
BridgeConnector.Socket.Emit("menu-setApplicationMenu", JArray.FromObject(menuItems, _jsonSerializer));
BridgeConnector.Socket.Emit("menu-setApplicationMenu", new[] { menuItems });
_menuItems.AddRange(menuItems);
BridgeConnector.Socket.Off("menuItemClicked");
BridgeConnector.Socket.On("menuItemClicked", (id) => {
MenuItem menuItem = _menuItems.GetMenuItem(id.ToString());
BridgeConnector.Socket.On<string>("menuItemClicked", (id) =>
{
MenuItem menuItem = _menuItems.GetMenuItem(id);
menuItem.Click?.Invoke();
});
}
@@ -75,6 +84,7 @@ namespace ElectronNET.API
/// The context menu items.
/// </value>
public IReadOnlyDictionary<int, ReadOnlyCollection<MenuItem>> ContextMenuItems { get; internal set; }
private Dictionary<int, List<MenuItem>> _contextMenuItems = new Dictionary<int, List<MenuItem>>();
/// <summary>
@@ -87,7 +97,7 @@ namespace ElectronNET.API
menuItems.AddMenuItemsId();
menuItems.AddSubmenuTypes();
BridgeConnector.Socket.Emit("menu-setContextMenu", browserWindow.Id, JArray.FromObject(menuItems, _jsonSerializer));
BridgeConnector.Socket.Emit("menu-setContextMenu", browserWindow.Id, menuItems);
if (!_contextMenuItems.ContainsKey(browserWindow.Id))
{
@@ -97,10 +107,14 @@ namespace ElectronNET.API
}
BridgeConnector.Socket.Off("contextMenuItemClicked");
BridgeConnector.Socket.On("contextMenuItemClicked", (results) =>
BridgeConnector.Socket.On<JsonElement>("contextMenuItemClicked", (results) =>
{
var id = ((JArray)results).First.ToString();
var browserWindowId = (int)((JArray)results).Last;
var arr = results.EnumerateArray();
var e = arr.GetEnumerator();
e.MoveNext();
var id = e.Current.GetString();
e.MoveNext();
var browserWindowId = e.Current.GetInt32();
MenuItem menuItem = _contextMenuItems[browserWindowId].GetMenuItem(id);
menuItem.Click?.Invoke();
@@ -116,10 +130,6 @@ namespace ElectronNET.API
BridgeConnector.Socket.Emit("menu-contextMenuPopup", browserWindow.Id);
}
private JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
}
}

View File

@@ -2,19 +2,24 @@
using System.Threading.Tasks;
using ElectronNET.API.Entities;
using ElectronNET.API.Extensions;
using ElectronNET.Common;
namespace ElectronNET.API
{
/// <summary>
/// Read and respond to changes in Chromium's native color theme.
/// </summary>
public sealed class NativeTheme
public sealed class NativeTheme: ApiBase
{
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.DashesLowerFirst;
protected override SocketEventNameTypes SocketEventNameType => SocketEventNameTypes.DashedLower;
protected override SocketTaskMessageNameTypes SocketTaskMessageNameType => SocketTaskMessageNameTypes.DashesLowerFirst;
private static NativeTheme _nativeTheme;
private static object _syncRoot = new object();
internal NativeTheme() { }
internal NativeTheme()
{
}
internal static NativeTheme Instance
{
@@ -102,81 +107,26 @@ namespace ElectronNET.API
/// A <see cref="ThemeSourceMode"/> property that can be <see cref="ThemeSourceMode.System"/>, <see cref="ThemeSourceMode.Light"/> or <see cref="ThemeSourceMode.Dark"/>. It is used to override (<seealso cref="SetThemeSource"/>) and
/// supercede the value that Chromium has chosen to use internally.
/// </summary>
public Task<ThemeSourceMode> GetThemeSourceAsync()
{
var taskCompletionSource = new TaskCompletionSource<ThemeSourceMode>();
BridgeConnector.Socket.On("nativeTheme-themeSource-getCompleted", (themeSource) =>
{
BridgeConnector.Socket.Off("nativeTheme-themeSource-getCompleted");
var themeSourceValue = (ThemeSourceMode)Enum.Parse(typeof(ThemeSourceMode), (string)themeSource, true);
taskCompletionSource.SetResult(themeSourceValue);
});
BridgeConnector.Socket.Emit("nativeTheme-themeSource-get");
return taskCompletionSource.Task;
}
public Task<ThemeSourceMode> GetThemeSourceAsync() => GetPropertyAsync<ThemeSourceMode>();
/// <summary>
/// A <see cref="bool"/> for if the OS / Chromium currently has a dark mode enabled or is
/// being instructed to show a dark-style UI. If you want to modify this value you
/// should use <see cref="SetThemeSource"/>.
/// </summary>
public Task<bool> ShouldUseDarkColorsAsync()
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("nativeTheme-shouldUseDarkColors-completed", (shouldUseDarkColors) => {
BridgeConnector.Socket.Off("nativeTheme-shouldUseDarkColors-completed");
taskCompletionSource.SetResult((bool)shouldUseDarkColors);
});
BridgeConnector.Socket.Emit("nativeTheme-shouldUseDarkColors");
return taskCompletionSource.Task;
}
public Task<bool> ShouldUseDarkColorsAsync() => GetPropertyAsync<bool>();
/// <summary>
/// A <see cref="bool"/> for if the OS / Chromium currently has high-contrast mode enabled or is
/// being instructed to show a high-contrast UI.
/// </summary>
public Task<bool> ShouldUseHighContrastColorsAsync()
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("nativeTheme-shouldUseHighContrastColors-completed", (shouldUseHighContrastColors) => {
BridgeConnector.Socket.Off("nativeTheme-shouldUseHighContrastColors-completed");
taskCompletionSource.SetResult((bool)shouldUseHighContrastColors);
});
BridgeConnector.Socket.Emit("nativeTheme-shouldUseHighContrastColors");
return taskCompletionSource.Task;
}
public Task<bool> ShouldUseHighContrastColorsAsync() => GetPropertyAsync<bool>();
/// <summary>
/// A <see cref="bool"/> for if the OS / Chromium currently has an inverted color scheme or is
/// being instructed to use an inverted color scheme.
/// </summary>
public Task<bool> ShouldUseInvertedColorSchemeAsync()
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("nativeTheme-shouldUseInvertedColorScheme-completed", (shouldUseInvertedColorScheme) => {
BridgeConnector.Socket.Off("nativeTheme-shouldUseInvertedColorScheme-completed");
taskCompletionSource.SetResult((bool)shouldUseInvertedColorScheme);
});
BridgeConnector.Socket.Emit("nativeTheme-shouldUseInvertedColorScheme");
return taskCompletionSource.Task;
}
public Task<bool> ShouldUseInvertedColorSchemeAsync() => GetPropertyAsync<bool>();
/// <summary>
/// Emitted when something in the underlying NativeTheme has changed. This normally means that either the value of <see cref="ShouldUseDarkColorsAsync"/>,
@@ -184,10 +134,8 @@ namespace ElectronNET.API
/// </summary>
public event Action Updated
{
add => ApiEventManager.AddEvent("nativeTheme-updated", GetHashCode(), _updated, value);
remove => ApiEventManager.RemoveEvent("nativeTheme-updated", GetHashCode(), _updated, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action _updated;
}
}

View File

@@ -1,7 +1,4 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ElectronNET.API.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
@@ -12,12 +9,15 @@ namespace ElectronNET.API
/// <summary>
/// Create OS desktop notifications
/// </summary>
public sealed class Notification
public sealed class Notification: ApiBase
{
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.NoDashUpperFirst;
private static Notification _notification;
private static object _syncRoot = new object();
internal Notification() { }
internal Notification()
{
}
internal static Notification Instance
{
@@ -48,7 +48,7 @@ namespace ElectronNET.API
{
GenerateIDsForDefinedActions(notificationOptions);
BridgeConnector.Socket.Emit("createNotification", JObject.FromObject(notificationOptions, _jsonSerializer));
BridgeConnector.Socket.Emit("createNotification", notificationOptions);
}
private static void GenerateIDsForDefinedActions(NotificationOptions notificationOptions)
@@ -61,9 +61,7 @@ namespace ElectronNET.API
isActionDefined = true;
BridgeConnector.Socket.Off("NotificationEventShow");
BridgeConnector.Socket.On("NotificationEventShow", (id) => {
_notificationOptions.Single(x => x.ShowID == id.ToString()).OnShow();
});
BridgeConnector.Socket.On<string>("NotificationEventShow", (id) => { _notificationOptions.Single(x => x.ShowID == id).OnShow(); });
}
if (notificationOptions.OnClick != null)
@@ -72,9 +70,7 @@ namespace ElectronNET.API
isActionDefined = true;
BridgeConnector.Socket.Off("NotificationEventClick");
BridgeConnector.Socket.On("NotificationEventClick", (id) => {
_notificationOptions.Single(x => x.ClickID == id.ToString()).OnClick();
});
BridgeConnector.Socket.On<string>("NotificationEventClick", (id) => { _notificationOptions.Single(x => x.ClickID == id).OnClick(); });
}
if (notificationOptions.OnClose != null)
@@ -83,9 +79,7 @@ namespace ElectronNET.API
isActionDefined = true;
BridgeConnector.Socket.Off("NotificationEventClose");
BridgeConnector.Socket.On("NotificationEventClose", (id) => {
_notificationOptions.Single(x => x.CloseID == id.ToString()).OnClose();
});
BridgeConnector.Socket.On<string>("NotificationEventClose", (id) => { _notificationOptions.Single(x => x.CloseID == id).OnClose(); });
}
if (notificationOptions.OnReply != null)
@@ -94,9 +88,9 @@ namespace ElectronNET.API
isActionDefined = true;
BridgeConnector.Socket.Off("NotificationEventReply");
BridgeConnector.Socket.On("NotificationEventReply", (args) => {
var arguments = ((JArray)args).ToObject<string[]>();
_notificationOptions.Single(x => x.ReplyID == arguments[0].ToString()).OnReply(arguments[1].ToString());
BridgeConnector.Socket.On<string[]>("NotificationEventReply", (args) =>
{
_notificationOptions.Single(x => x.ReplyID == args[0]).OnReply(args[1]);
});
}
@@ -106,9 +100,9 @@ namespace ElectronNET.API
isActionDefined = true;
BridgeConnector.Socket.Off("NotificationEventAction");
BridgeConnector.Socket.On("NotificationEventAction", (args) => {
var arguments = ((JArray)args).ToObject<string[]>();
_notificationOptions.Single(x => x.ReplyID == arguments[0].ToString()).OnAction(arguments[1].ToString());
BridgeConnector.Socket.On<string[]>("NotificationEventAction", (args) =>
{
_notificationOptions.Single(x => x.ActionID == args[0]).OnAction(args[1]);
});
}
@@ -122,26 +116,6 @@ namespace ElectronNET.API
/// Whether or not desktop notifications are supported on the current system.
/// </summary>
/// <returns></returns>
public Task<bool> IsSupportedAsync()
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("notificationIsSupportedComplete", (isSupported) =>
{
BridgeConnector.Socket.Off("notificationIsSupportedComplete");
taskCompletionSource.SetResult((bool)isSupported);
});
BridgeConnector.Socket.Emit("notificationIsSupported");
return taskCompletionSource.Task;
}
private JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
public Task<bool> IsSupportedAsync() => GetPropertyAsync<bool>();
}
}

View File

@@ -1,6 +1,5 @@
using System;
using System.Threading.Tasks;
using ElectronNET.Common;
// ReSharper disable InconsistentNaming
namespace ElectronNET.API
@@ -8,74 +7,65 @@ namespace ElectronNET.API
/// <summary>
/// Monitor power state changes..
/// </summary>
public sealed class PowerMonitor
public sealed class PowerMonitor: ApiBase
{
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.DashesLowerFirst;
protected override SocketEventNameTypes SocketEventNameType => SocketEventNameTypes.DashedLower;
/// <summary>
/// Emitted when the system is about to lock the screen.
/// </summary>
public event Action OnLockScreen
{
add => ApiEventManager.AddEvent("pm-lock-screen", string.Empty, _lockScreen, value);
remove => ApiEventManager.RemoveEvent("pm-lock-screen", string.Empty, _lockScreen, value);
add => AddEvent(value);
remove => RemoveEvent(value);
}
private event Action _lockScreen;
/// <summary>
/// Emitted when the system is about to unlock the screen.
/// </summary>
public event Action OnUnLockScreen
{
add => ApiEventManager.AddEvent("pm-unlock-screen", string.Empty, _unlockScreen, value);
remove => ApiEventManager.RemoveEvent("pm-unlock-screen", string.Empty, _unlockScreen, value);
add => AddEvent(value);
remove => RemoveEvent(value);
}
private event Action _unlockScreen;
/// <summary>
/// Emitted when the system is suspending.
/// </summary>
public event Action OnSuspend
{
add => ApiEventManager.AddEvent("pm-suspend", string.Empty, _suspend, value);
remove => ApiEventManager.RemoveEvent("pm-suspend", string.Empty, _suspend, value);
add => AddEvent(value);
remove => RemoveEvent(value);
}
private event Action _suspend;
/// <summary>
/// Emitted when system is resuming.
/// </summary>
public event Action OnResume
{
add => ApiEventManager.AddEvent("pm-resume", string.Empty, _resume, value);
remove => ApiEventManager.RemoveEvent("pm-resume", string.Empty, _resume, value);
add => AddEvent(value);
remove => RemoveEvent(value);
}
private event Action _resume;
/// <summary>
/// Emitted when the system changes to AC power.
/// </summary>
public event Action OnAC
{
add => ApiEventManager.AddEvent("pm-on-ac", string.Empty, _onAC, value);
remove => ApiEventManager.RemoveEvent("pm-on-ac", string.Empty, _onAC, value);
add => AddEvent(value);
remove => RemoveEvent(value);
}
private event Action _onAC;
/// <summary>
/// Emitted when system changes to battery power.
/// </summary>
public event Action OnBattery
{
add => ApiEventManager.AddEvent("pm-on-battery", string.Empty, _onBattery, value);
remove => ApiEventManager.RemoveEvent("pm-on-battery", string.Empty, _onBattery, value);
add => AddEvent(value);
remove => RemoveEvent(value);
}
private event Action _onBattery;
/// <summary>
/// Emitted when the system is about to reboot or shut down. If the event handler
/// invokes `e.preventDefault()`, Electron will attempt to delay system shutdown in
@@ -84,16 +74,16 @@ namespace ElectronNET.API
/// </summary>
public event Action OnShutdown
{
add => ApiEventManager.AddEvent("pm-shutdown", string.Empty, _shutdown, value);
remove => ApiEventManager.RemoveEvent("pm-shutdown", string.Empty, _shutdown, value);
add => AddEvent(value);
remove => RemoveEvent(value);
}
private event Action _shutdown;
private static PowerMonitor _powerMonitor;
private static object _syncRoot = new object();
internal PowerMonitor() { }
internal PowerMonitor()
{
}
internal static PowerMonitor Instance
{
@@ -114,4 +104,4 @@ namespace ElectronNET.API
}
}
}
}
}

View File

@@ -1,8 +1,7 @@
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using ElectronNET.API.Entities;
using ElectronNET.API.Serialization;
using System.Text.Json;
using System.Threading.Tasks;
namespace ElectronNET.API
{
@@ -10,9 +9,13 @@ namespace ElectronNET.API
/// Electron's process object is extended from the Node.js process object. It adds the
/// events, properties, and methods.
/// </summary>
public sealed class Process
public sealed class Process: ApiBase
{
internal Process() { }
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.DashesLowerFirst;
protected override SocketTaskMessageNameTypes SocketTaskMessageNameType => SocketTaskMessageNameTypes.DashesLowerFirst;
internal Process()
{
}
internal static Process Instance
{
@@ -41,22 +44,7 @@ namespace ElectronNET.API
/// The process.execPath property returns the absolute pathname of the executable that
/// started the Node.js process. Symbolic links, if any, are resolved.
/// </summary>
public Task<string> ExecPathAsync
{
get
{
var taskCompletionSource = new TaskCompletionSource<string>();
BridgeConnector.Socket.On("process-execPath-Completed", (result) =>
{
BridgeConnector.Socket.Off("process-execPath-Completed");
taskCompletionSource.SetResult(result.ToString());
});
BridgeConnector.Socket.Emit("process-execPath");
return taskCompletionSource.Task;
}
}
public Task<string> ExecPathAsync => GetPropertyAsync<string>();
/// <summary>
/// The process.argv property returns an array containing the command-line arguments passed
@@ -65,210 +53,56 @@ namespace ElectronNET.API
/// will be the path to the JavaScript file being executed. The remaining elements will be
/// any additional command-line arguments
/// </summary>
public Task<string[]> ArgvAsync
{
get
{
var taskCompletionSource = new TaskCompletionSource<string[]>();
BridgeConnector.Socket.On("process-argv-Completed", (result) =>
{
BridgeConnector.Socket.Off("process-argv-Completed");
taskCompletionSource.SetResult(((JArray)result).ToObject<string[]>());
});
BridgeConnector.Socket.Emit("process-argv");
return taskCompletionSource.Task;
}
}
public Task<string[]> ArgvAsync => GetPropertyAsync<string[]>();
/// <summary>
/// The process.execPath property returns the absolute pathname of the executable that
/// started the Node.js process. Symbolic links, if any, are resolved.
/// </summary>
public Task<string> TypeAsync
{
get
{
var taskCompletionSource = new TaskCompletionSource<string>();
public Task<string> TypeAsync => GetPropertyAsync<string>();
BridgeConnector.Socket.On("process-type-Completed", (result) =>
{
BridgeConnector.Socket.Off("process-type-Completed");
taskCompletionSource.SetResult(result.ToString());
});
BridgeConnector.Socket.Emit("process-type");
return taskCompletionSource.Task;
}
}
/// <summary>
/// The process.versions property returns an object listing the version strings of
/// chrome and electron.
/// </summary>
public Task<ProcessVersions> VersionsAsync
{
get
{
var taskCompletionSource = new TaskCompletionSource<ProcessVersions>();
public Task<ProcessVersions> VersionsAsync => GetPropertyAsync<ProcessVersions>();
BridgeConnector.Socket.On("process-versions-Completed", (result) =>
{
BridgeConnector.Socket.Off("process-versions-Completed");
taskCompletionSource.SetResult(((JObject)result).ToObject<ProcessVersions>());
});
BridgeConnector.Socket.Emit("process-versions");
return taskCompletionSource.Task;
}
}
/// <summary>
/// A Boolean. When app is started by being passed as parameter to the default app, this
/// property is true in the main process, otherwise it is false.
/// </summary>
public Task<bool> DefaultAppAsync
{
get
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("process-defaultApp-Completed", (result) =>
{
BridgeConnector.Socket.Off("process-defaultApp-Completed");
taskCompletionSource.SetResult(bool.Parse(result.ToString()));
});
BridgeConnector.Socket.Emit("process-defaultApp");
return taskCompletionSource.Task;
}
}
public Task<bool> DefaultAppAsync => GetPropertyAsync<bool>();
/// <summary>
/// A Boolean, true when the current renderer context is the "main" renderer frame. If you
/// want the ID of the current frame you should use webFrame.routingId
/// </summary>
public Task<bool> IsMainFrameAsync
{
get
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("process-isMainFrame-Completed", (result) =>
{
BridgeConnector.Socket.Off("process-isMainFrame-Completed");
taskCompletionSource.SetResult(bool.Parse(result.ToString()));
});
BridgeConnector.Socket.Emit("process-isMainFrame");
return taskCompletionSource.Task;
}
}
public Task<bool> IsMainFrameAsync => GetPropertyAsync<bool>();
/// <summary>
/// A String representing the path to the resources directory.
/// </summary>
public Task<string> ResourcesPathAsync
{
get
{
var taskCompletionSource = new TaskCompletionSource<string>();
BridgeConnector.Socket.On("process-resourcesPath-Completed", (result) =>
{
BridgeConnector.Socket.Off("process-resourcesPath-Completed");
taskCompletionSource.SetResult(result.ToString());
});
BridgeConnector.Socket.Emit("process-resourcesPath");
return taskCompletionSource.Task;
}
}
public Task<string> ResourcesPathAsync => GetPropertyAsync<string>();
/// <summary>
/// The number of seconds the current Node.js process has been running. The return value
/// includes fractions of a second. Use Math.floor() to get whole seconds.
/// </summary>
public Task<double> UpTimeAsync
{
get
{
var taskCompletionSource = new TaskCompletionSource<double>();
BridgeConnector.Socket.On("process-uptime-Completed", (result) =>
{
BridgeConnector.Socket.Off("process-uptime-Completed");
taskCompletionSource.SetResult(double.Parse(result.ToString()));
});
BridgeConnector.Socket.Emit("process-uptime");
return taskCompletionSource.Task;
}
}
public Task<double> UpTimeAsync => GetPropertyAsync<double>();
/// <summary>
/// The PID of the electron process
/// </summary>
public Task<int> PidAsync
{
get
{
var taskCompletionSource = new TaskCompletionSource<int>();
BridgeConnector.Socket.On("process-pid-Completed", (result) =>
{
BridgeConnector.Socket.Off("process-pid-Completed");
taskCompletionSource.SetResult(int.Parse(result.ToString()));
});
BridgeConnector.Socket.Emit("process-pid");
return taskCompletionSource.Task;
}
}
public Task<int> PidAsync => GetPropertyAsync<int>();
/// <summary>
/// The operating system CPU architecture for which the Node.js binary was compiled
/// </summary>
public Task<string> ArchAsync
{
get
{
var taskCompletionSource = new TaskCompletionSource<string>();
BridgeConnector.Socket.On("process-arch-Completed", (result) =>
{
BridgeConnector.Socket.Off("process-arch-Completed");
taskCompletionSource.SetResult(result.ToString());
});
BridgeConnector.Socket.Emit("process-arch");
return taskCompletionSource.Task;
}
}
public Task<string> ArchAsync => GetPropertyAsync<string>();
/// <summary>
/// A string identifying the operating system platform on which the Node.js process is running
/// </summary>
public Task<string> PlatformAsync
{
get
{
var taskCompletionSource = new TaskCompletionSource<string>();
BridgeConnector.Socket.On("process-platform-Completed", (result) =>
{
BridgeConnector.Socket.Off("process-platform-Completed");
taskCompletionSource.SetResult(result.ToString());
});
BridgeConnector.Socket.Emit("process-platform");
return taskCompletionSource.Task;
}
}
public Task<string> PlatformAsync => GetPropertyAsync<string>();
}
}

View File

@@ -1,40 +1,39 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ElectronNET.API.Entities;
using System;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using ElectronNET.Common;
using ElectronNET.API.Serialization;
namespace ElectronNET.API
{
/// <summary>
/// Retrieve information about screen size, displays, cursor position, etc.
/// </summary>
public sealed class Screen
public sealed class Screen: ApiBase
{
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.DashesLowerFirst;
protected override SocketTaskMessageNameTypes SocketTaskMessageNameType => SocketTaskMessageNameTypes.DashesLowerFirst;
protected override SocketEventNameTypes SocketEventNameType => SocketEventNameTypes.DashedLower;
/// <summary>
/// Emitted when an new Display has been added.
/// </summary>
public event Action<Display> OnDisplayAdded
{
add => ApiEventManager.AddEvent("screen-display-added", GetHashCode(), _onDisplayAdded, value, (args) => ((JObject)args).ToObject<Display>());
remove => ApiEventManager.RemoveEvent("screen-display-added", GetHashCode(), _onDisplayAdded, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action<Display> _onDisplayAdded;
/// <summary>
/// Emitted when oldDisplay has been removed.
/// </summary>
public event Action<Display> OnDisplayRemoved
{
add => ApiEventManager.AddEvent("screen-display-removed", GetHashCode(), _onDisplayRemoved, value, (args) => ((JObject)args).ToObject<Display>());
remove => ApiEventManager.RemoveEvent("screen-display-removed", GetHashCode(), _onDisplayRemoved, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action<Display> _onDisplayRemoved;
/// <summary>
/// Emitted when one or more metrics change in a display.
/// The changedMetrics is an array of strings that describe the changes.
@@ -42,8 +41,32 @@ namespace ElectronNET.API
/// </summary>
public event Action<Display, string[]> OnDisplayMetricsChanged
{
add => ApiEventManager.AddScreenEvent("screen-display-metrics-changed", GetHashCode(), _onDisplayMetricsChanged, value);
remove => ApiEventManager.RemoveScreenEvent("screen-display-metrics-changed", GetHashCode(), _onDisplayMetricsChanged, value);
add
{
if (_onDisplayMetricsChanged == null)
{
BridgeConnector.Socket.On<JsonElement>("screen-display-metrics-changed" + GetHashCode(), (args) =>
{
var arr = args.EnumerateArray().ToArray();
var display = arr[0].Deserialize(ElectronJsonContext.Default.Display);
var metrics = arr[1].Deserialize<string[]>(ElectronJson.Options);
_onDisplayMetricsChanged(display, metrics);
});
BridgeConnector.Socket.Emit("register-screen-display-metrics-changed", GetHashCode());
}
_onDisplayMetricsChanged += value;
}
remove
{
_onDisplayMetricsChanged -= value;
if (_onDisplayMetricsChanged == null)
{
BridgeConnector.Socket.Off("screen-display-metrics-changed" + GetHashCode());
}
}
}
private event Action<Display, string[]> _onDisplayMetricsChanged;
@@ -51,7 +74,9 @@ namespace ElectronNET.API
private static Screen _screen;
private static object _syncRoot = new object();
internal Screen() { }
internal Screen()
{
}
internal static Screen Instance
{
@@ -76,128 +101,37 @@ namespace ElectronNET.API
/// The current absolute position of the mouse pointer.
/// </summary>
/// <returns></returns>
public Task<Point> GetCursorScreenPointAsync()
{
var taskCompletionSource = new TaskCompletionSource<Point>();
BridgeConnector.Socket.On("screen-getCursorScreenPointCompleted", (point) =>
{
BridgeConnector.Socket.Off("screen-getCursorScreenPointCompleted");
taskCompletionSource.SetResult(((JObject)point).ToObject<Point>());
});
BridgeConnector.Socket.Emit("screen-getCursorScreenPoint");
return taskCompletionSource.Task;
}
public Task<Point> GetCursorScreenPointAsync() => GetPropertyAsync<Point>();
/// <summary>
/// macOS: The height of the menu bar in pixels.
/// </summary>
/// <returns>The height of the menu bar in pixels.</returns>
public Task<int> GetMenuBarHeightAsync()
{
var taskCompletionSource = new TaskCompletionSource<int>();
BridgeConnector.Socket.On("screen-getMenuBarHeightCompleted", (height) =>
{
BridgeConnector.Socket.Off("screen-getMenuBarHeightCompleted");
taskCompletionSource.SetResult(int.Parse(height.ToString()));
});
BridgeConnector.Socket.Emit("screen-getMenuBarHeight");
return taskCompletionSource.Task;
}
public Task<Rectangle> GetMenuBarWorkAreaAsync() => GetPropertyAsync<Rectangle>();
/// <summary>
/// The primary display.
/// </summary>
/// <returns></returns>
public Task<Display> GetPrimaryDisplayAsync()
{
var taskCompletionSource = new TaskCompletionSource<Display>();
BridgeConnector.Socket.On("screen-getPrimaryDisplayCompleted", (display) =>
{
BridgeConnector.Socket.Off("screen-getPrimaryDisplayCompleted");
taskCompletionSource.SetResult(((JObject)display).ToObject<Display>());
});
BridgeConnector.Socket.Emit("screen-getPrimaryDisplay");
return taskCompletionSource.Task;
}
public Task<Display> GetPrimaryDisplayAsync() => GetPropertyAsync<Display>();
/// <summary>
/// An array of displays that are currently available.
/// </summary>
/// <returns>An array of displays that are currently available.</returns>
public Task<Display[]> GetAllDisplaysAsync()
{
var taskCompletionSource = new TaskCompletionSource<Display[]>();
BridgeConnector.Socket.On("screen-getAllDisplaysCompleted", (displays) =>
{
BridgeConnector.Socket.Off("screen-getAllDisplaysCompleted");
taskCompletionSource.SetResult(((JArray)displays).ToObject<Display[]>());
});
BridgeConnector.Socket.Emit("screen-getAllDisplays");
return taskCompletionSource.Task;
}
public Task<Display[]> GetAllDisplaysAsync() => GetPropertyAsync<Display[]>();
/// <summary>
/// The display nearest the specified point.
/// </summary>
/// <returns>The display nearest the specified point.</returns>
public Task<Display> GetDisplayNearestPointAsync(Point point)
{
var taskCompletionSource = new TaskCompletionSource<Display>();
BridgeConnector.Socket.On("screen-getDisplayNearestPointCompleted", (display) =>
{
BridgeConnector.Socket.Off("screen-getDisplayNearestPointCompleted");
taskCompletionSource.SetResult(((JObject)display).ToObject<Display>());
});
BridgeConnector.Socket.Emit("screen-getDisplayNearestPoint", JObject.FromObject(point, _jsonSerializer));
return taskCompletionSource.Task;
}
public Task<Display> GetDisplayNearestPointAsync(Point point) => GetPropertyAsync<Display>(point);
/// <summary>
/// The display that most closely intersects the provided bounds.
/// </summary>
/// <param name="rectangle"></param>
/// <returns>The display that most closely intersects the provided bounds.</returns>
public Task<Display> GetDisplayMatchingAsync(Rectangle rectangle)
{
var taskCompletionSource = new TaskCompletionSource<Display>();
BridgeConnector.Socket.On("screen-getDisplayMatching", (display) =>
{
BridgeConnector.Socket.Off("screen-getDisplayMatching");
taskCompletionSource.SetResult(((JObject)display).ToObject<Display>());
});
BridgeConnector.Socket.Emit("screen-getDisplayMatching", JObject.FromObject(rectangle, _jsonSerializer));
return taskCompletionSource.Task;
}
private JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
public Task<Display> GetDisplayMatchingAsync(Rectangle rectangle) => GetPropertyAsync<Display>(rectangle);
}
}
}

View File

@@ -1,7 +1,4 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ElectronNET.API.Entities;
using System;
using System.Threading.Tasks;
@@ -50,18 +47,13 @@ namespace ElectronNET.API
/// <returns></returns>
public Task ClearAuthCacheAsync(RemovePassword options)
{
var taskCompletionSource = new TaskCompletionSource<object>();
var tcs = new TaskCompletionSource<object>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("webContents-session-clearAuthCache-completed" + guid, () =>
{
BridgeConnector.Socket.Off("webContents-session-clearAuthCache-completed" + guid);
taskCompletionSource.SetResult(null);
});
BridgeConnector.Socket.Once("webContents-session-clearAuthCache-completed" + guid, () => tcs.SetResult(null));
BridgeConnector.Socket.Emit("webContents-session-clearAuthCache", Id, options, guid);
BridgeConnector.Socket.Emit("webContents-session-clearAuthCache", Id, JObject.FromObject(options, _jsonSerializer), guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -69,18 +61,13 @@ namespace ElectronNET.API
/// </summary>
public Task ClearAuthCacheAsync()
{
var taskCompletionSource = new TaskCompletionSource<object>();
var tcs = new TaskCompletionSource<object>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("webContents-session-clearAuthCache-completed" + guid, () =>
{
BridgeConnector.Socket.Off("webContents-session-clearAuthCache-completed" + guid);
taskCompletionSource.SetResult(null);
});
BridgeConnector.Socket.Once("webContents-session-clearAuthCache-completed" + guid, () => tcs.SetResult(null));
BridgeConnector.Socket.Emit("webContents-session-clearAuthCache", Id, guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -89,18 +76,13 @@ namespace ElectronNET.API
/// <returns></returns>
public Task ClearCacheAsync()
{
var taskCompletionSource = new TaskCompletionSource<object>();
var tcs = new TaskCompletionSource<object>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("webContents-session-clearCache-completed" + guid, () =>
{
BridgeConnector.Socket.Off("webContents-session-clearCache-completed" + guid);
taskCompletionSource.SetResult(null);
});
BridgeConnector.Socket.Once("webContents-session-clearCache-completed" + guid, () => tcs.SetResult(null));
BridgeConnector.Socket.Emit("webContents-session-clearCache", Id, guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -109,18 +91,13 @@ namespace ElectronNET.API
/// <returns></returns>
public Task ClearHostResolverCacheAsync()
{
var taskCompletionSource = new TaskCompletionSource<object>();
var tcs = new TaskCompletionSource<object>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("webContents-session-clearHostResolverCache-completed" + guid, () =>
{
BridgeConnector.Socket.Off("webContents-session-clearHostResolverCache-completed" + guid);
taskCompletionSource.SetResult(null);
});
BridgeConnector.Socket.Once("webContents-session-clearHostResolverCache-completed" + guid, () => tcs.SetResult(null));
BridgeConnector.Socket.Emit("webContents-session-clearHostResolverCache", Id, guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -129,18 +106,13 @@ namespace ElectronNET.API
/// <returns></returns>
public Task ClearStorageDataAsync()
{
var taskCompletionSource = new TaskCompletionSource<object>();
var tcs = new TaskCompletionSource<object>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("webContents-session-clearStorageData-completed" + guid, () =>
{
BridgeConnector.Socket.Off("webContents-session-clearStorageData-completed" + guid);
taskCompletionSource.SetResult(null);
});
BridgeConnector.Socket.Once("webContents-session-clearStorageData-completed" + guid, () => tcs.SetResult(null));
BridgeConnector.Socket.Emit("webContents-session-clearStorageData", Id, guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -150,18 +122,13 @@ namespace ElectronNET.API
/// <returns></returns>
public Task ClearStorageDataAsync(ClearStorageDataOptions options)
{
var taskCompletionSource = new TaskCompletionSource<object>();
var tcs = new TaskCompletionSource<object>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("webContents-session-clearStorageData-options-completed" + guid, () =>
{
BridgeConnector.Socket.Off("webContents-session-clearStorageData-options-completed" + guid);
taskCompletionSource.SetResult(null);
});
BridgeConnector.Socket.Once("webContents-session-clearStorageData-options-completed" + guid, () => tcs.SetResult(null));
BridgeConnector.Socket.Emit("webContents-session-clearStorageData-options", Id, options, guid);
BridgeConnector.Socket.Emit("webContents-session-clearStorageData-options", Id, JObject.FromObject(options, _jsonSerializer), guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -174,7 +141,7 @@ namespace ElectronNET.API
/// <param name="options"></param>
public void CreateInterruptedDownload(CreateInterruptedDownloadOptions options)
{
BridgeConnector.Socket.Emit("webContents-session-createInterruptedDownload", Id, JObject.FromObject(options, _jsonSerializer));
BridgeConnector.Socket.Emit("webContents-session-createInterruptedDownload", Id, options);
}
/// <summary>
@@ -192,7 +159,7 @@ namespace ElectronNET.API
/// <param name="options"></param>
public void EnableNetworkEmulation(EnableNetworkEmulationOptions options)
{
BridgeConnector.Socket.Emit("webContents-session-enableNetworkEmulation", Id, JObject.FromObject(options, _jsonSerializer));
BridgeConnector.Socket.Emit("webContents-session-enableNetworkEmulation", Id, options);
}
/// <summary>
@@ -210,20 +177,13 @@ namespace ElectronNET.API
/// <returns></returns>
public Task<int[]> GetBlobDataAsync(string identifier)
{
var taskCompletionSource = new TaskCompletionSource<int[]>();
var tcs = new TaskCompletionSource<int[]>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("webContents-session-getBlobData-completed" + guid, (buffer) =>
{
var result = ((JArray)buffer).ToObject<int[]>();
BridgeConnector.Socket.Off("webContents-session-getBlobData-completed" + guid);
taskCompletionSource.SetResult(result);
});
BridgeConnector.Socket.Once<int[]>("webContents-session-getBlobData-completed" + guid, tcs.SetResult);
BridgeConnector.Socket.Emit("webContents-session-getBlobData", Id, identifier, guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -232,18 +192,13 @@ namespace ElectronNET.API
/// <returns>Callback is invoked with the session's current cache size.</returns>
public Task<int> GetCacheSizeAsync()
{
var taskCompletionSource = new TaskCompletionSource<int>();
var tcs = new TaskCompletionSource<int>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("webContents-session-getCacheSize-completed" + guid, (size) =>
{
BridgeConnector.Socket.Off("webContents-session-getCacheSize-completed" + guid);
taskCompletionSource.SetResult((int)size);
});
BridgeConnector.Socket.Once<int>("webContents-session-getCacheSize-completed" + guid, tcs.SetResult);
BridgeConnector.Socket.Emit("webContents-session-getCacheSize", Id, guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -252,19 +207,13 @@ namespace ElectronNET.API
/// <returns></returns>
public Task<string[]> GetPreloadsAsync()
{
var taskCompletionSource = new TaskCompletionSource<string[]>();
var tcs = new TaskCompletionSource<string[]>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("webContents-session-getPreloads-completed" + guid, (preloads) =>
{
var result = ((JArray)preloads).ToObject<string[]>();
BridgeConnector.Socket.Off("webContents-session-getPreloads-completed" + guid);
taskCompletionSource.SetResult(result);
});
BridgeConnector.Socket.Once<string[]>("webContents-session-getPreloads-completed" + guid, tcs.SetResult);
BridgeConnector.Socket.Emit("webContents-session-getPreloads", Id, guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -273,18 +222,13 @@ namespace ElectronNET.API
/// <returns></returns>
public Task<string> GetUserAgent()
{
var taskCompletionSource = new TaskCompletionSource<string>();
var tcs = new TaskCompletionSource<string>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("webContents-session-getUserAgent-completed" + guid, (userAgent) =>
{
BridgeConnector.Socket.Off("webContents-session-getUserAgent-completed" + guid);
taskCompletionSource.SetResult(userAgent.ToString());
});
BridgeConnector.Socket.Once<string>("webContents-session-getUserAgent-completed" + guid, tcs.SetResult);
BridgeConnector.Socket.Emit("webContents-session-getUserAgent", Id, guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -295,18 +239,13 @@ namespace ElectronNET.API
/// <returns></returns>
public Task<string> ResolveProxyAsync(string url)
{
var taskCompletionSource = new TaskCompletionSource<string>();
var tcs = new TaskCompletionSource<string>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("webContents-session-resolveProxy-completed" + guid, (proxy) =>
{
BridgeConnector.Socket.Off("webContents-session-resolveProxy-completed" + guid);
taskCompletionSource.SetResult(proxy.ToString());
});
BridgeConnector.Socket.Once<string>("webContents-session-resolveProxy-completed" + guid, tcs.SetResult);
BridgeConnector.Socket.Emit("webContents-session-resolveProxy", Id, url, guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -337,18 +276,13 @@ namespace ElectronNET.API
/// <returns></returns>
public Task SetProxyAsync(ProxyConfig config)
{
var taskCompletionSource = new TaskCompletionSource<object>();
var tcs = new TaskCompletionSource<object>();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.On("webContents-session-setProxy-completed" + guid, () =>
{
BridgeConnector.Socket.Off("webContents-session-setProxy-completed" + guid);
taskCompletionSource.SetResult(null);
});
BridgeConnector.Socket.Once("webContents-session-setProxy-completed" + guid, () => tcs.SetResult(null));
BridgeConnector.Socket.Emit("webContents-session-setProxy", Id, config, guid);
BridgeConnector.Socket.Emit("webContents-session-setProxy", Id, JObject.FromObject(config, _jsonSerializer), guid);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -385,19 +319,12 @@ namespace ElectronNET.API
/// <returns></returns>
public Task<ChromeExtensionInfo[]> GetAllExtensionsAsync()
{
var taskCompletionSource = new TaskCompletionSource<ChromeExtensionInfo[]>();
BridgeConnector.Socket.On("webContents-session-getAllExtensions-completed", (extensionslist) =>
{
BridgeConnector.Socket.Off("webContents-session-getAllExtensions-completed");
var chromeExtensionInfos = ((JArray)extensionslist).ToObject<ChromeExtensionInfo[]>();
taskCompletionSource.SetResult(chromeExtensionInfos);
});
var tcs = new TaskCompletionSource<ChromeExtensionInfo[]>();
BridgeConnector.Socket.Once<ChromeExtensionInfo[]>("webContents-session-getAllExtensions-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("webContents-session-getAllExtensions", Id);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -439,25 +366,14 @@ namespace ElectronNET.API
/// <returns></returns>
public Task<Extension> LoadExtensionAsync(string path, bool allowFileAccess = false)
{
var taskCompletionSource = new TaskCompletionSource<Extension>();
BridgeConnector.Socket.On("webContents-session-loadExtension-completed", (extension) =>
{
BridgeConnector.Socket.Off("webContents-session-loadExtension-completed");
taskCompletionSource.SetResult(((JObject)extension).ToObject<Extension>());
});
var tcs = new TaskCompletionSource<Extension>();
BridgeConnector.Socket.Once<Extension>("webContents-session-loadExtension-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("webContents-session-loadExtension", Id, path, allowFileAccess);
return taskCompletionSource.Task;
return tcs.Task;
}
private JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
}
}

View File

@@ -1,9 +1,8 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System.Threading.Tasks;
using ElectronNET.API.Entities;
using ElectronNET.API.Extensions;
using ElectronNET.API.Serialization;
using System.Text.Json;
using System.Threading.Tasks;
namespace ElectronNET.API
{
@@ -15,7 +14,9 @@ namespace ElectronNET.API
private static Shell _shell;
private static object _syncRoot = new object();
internal Shell() { }
internal Shell()
{
}
internal static Shell Instance
{
@@ -42,16 +43,13 @@ namespace ElectronNET.API
/// <param name="fullPath">The full path to the directory / file.</param>
public Task ShowItemInFolderAsync(string fullPath)
{
var taskCompletionSource = new TaskCompletionSource<object>();
BridgeConnector.Socket.On("shell-showItemInFolderCompleted", () =>
{
BridgeConnector.Socket.Off("shell-showItemInFolderCompleted");
});
var tcs = new TaskCompletionSource<object>();
// Is this really useful?
BridgeConnector.Socket.Once("shell-showItemInFolderCompleted", () => { });
BridgeConnector.Socket.Emit("shell-showItemInFolder", fullPath);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -61,18 +59,12 @@ namespace ElectronNET.API
/// <returns>The error message corresponding to the failure if a failure occurred, otherwise <see cref="string.Empty"/>.</returns>
public Task<string> OpenPathAsync(string path)
{
var taskCompletionSource = new TaskCompletionSource<string>();
BridgeConnector.Socket.On("shell-openPathCompleted", (errorMessage) =>
{
BridgeConnector.Socket.Off("shell-openPathCompleted");
taskCompletionSource.SetResult((string) errorMessage);
});
var tcs = new TaskCompletionSource<string>();
BridgeConnector.Socket.Once<string>("shell-openPathCompleted", tcs.SetResult);
BridgeConnector.Socket.Emit("shell-openPath", path);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -95,14 +87,9 @@ namespace ElectronNET.API
/// <returns>The error message corresponding to the failure if a failure occurred, otherwise <see cref="string.Empty"/>.</returns>
public Task<string> OpenExternalAsync(string url, OpenExternalOptions options)
{
var taskCompletionSource = new TaskCompletionSource<string>();
var tcs = new TaskCompletionSource<string>();
BridgeConnector.Socket.On("shell-openExternalCompleted", (error) =>
{
BridgeConnector.Socket.Off("shell-openExternalCompleted");
taskCompletionSource.SetResult((string) error);
});
BridgeConnector.Socket.Once<string>("shell-openExternalCompleted", tcs.SetResult);
if (options == null)
{
@@ -110,10 +97,10 @@ namespace ElectronNET.API
}
else
{
BridgeConnector.Socket.Emit("shell-openExternal", url, JObject.FromObject(options, _jsonSerializer));
BridgeConnector.Socket.Emit("shell-openExternal", url, options);
}
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -123,18 +110,12 @@ namespace ElectronNET.API
/// <returns> Whether the item was successfully moved to the trash.</returns>
public Task<bool> TrashItemAsync(string fullPath)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("shell-trashItem-completed", (success) =>
{
BridgeConnector.Socket.Off("shell-trashItem-completed");
taskCompletionSource.SetResult((bool) success);
});
var tcs = new TaskCompletionSource<bool>();
BridgeConnector.Socket.Once<bool>("shell-trashItem-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("shell-trashItem", fullPath);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -154,18 +135,12 @@ namespace ElectronNET.API
/// <returns>Whether the shortcut was created successfully.</returns>
public Task<bool> WriteShortcutLinkAsync(string shortcutPath, ShortcutLinkOperation operation, ShortcutDetails options)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
var tcs = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("shell-writeShortcutLinkCompleted", (success) =>
{
BridgeConnector.Socket.Off("shell-writeShortcutLinkCompleted");
BridgeConnector.Socket.Once<bool>("shell-writeShortcutLinkCompleted", tcs.SetResult);
BridgeConnector.Socket.Emit("shell-writeShortcutLink", shortcutPath, operation.GetDescription(), options);
taskCompletionSource.SetResult((bool) success);
});
BridgeConnector.Socket.Emit("shell-writeShortcutLink", shortcutPath, operation.GetDescription(), JObject.FromObject(options, _jsonSerializer));
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -176,28 +151,14 @@ namespace ElectronNET.API
/// <returns><see cref="ShortcutDetails"/> of the shortcut.</returns>
public Task<ShortcutDetails> ReadShortcutLinkAsync(string shortcutPath)
{
var taskCompletionSource = new TaskCompletionSource<ShortcutDetails>();
BridgeConnector.Socket.On("shell-readShortcutLinkCompleted", (shortcutDetails) =>
{
BridgeConnector.Socket.Off("shell-readShortcutLinkCompleted");
var shortcutObject = shortcutDetails as JObject;
var details = shortcutObject?.ToObject<ShortcutDetails>();
taskCompletionSource.SetResult(details);
});
var tcs = new TaskCompletionSource<ShortcutDetails>();
BridgeConnector.Socket.Once<ShortcutDetails>("shell-readShortcutLinkCompleted", tcs.SetResult);
BridgeConnector.Socket.Emit("shell-readShortcutLink", shortcutPath);
return taskCompletionSource.Task;
return tcs.Task;
}
private readonly JsonSerializer _jsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
}
}

View File

@@ -1,12 +1,12 @@
using ElectronNET.API.Entities;
using ElectronNET.API.Entities;
using ElectronNET.API.Extensions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using ElectronNET.Common;
using ElectronNET.API.Serialization;
// ReSharper disable InconsistentNaming
namespace ElectronNET.API
@@ -14,15 +14,41 @@ namespace ElectronNET.API
/// <summary>
/// Add icons and context menus to the system's notification area.
/// </summary>
public sealed class Tray
public sealed class Tray: ApiBase
{
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.DashesLowerFirst;
protected override SocketEventNameTypes SocketEventNameType => SocketEventNameTypes.DashedLower;
/// <summary>
/// Emitted when the tray icon is clicked.
/// </summary>
public event Action<TrayClickEventArgs, Rectangle> OnClick
{
add => ApiEventManager.AddTrayEvent("tray-click", GetHashCode(), _click, value);
remove => ApiEventManager.RemoveTrayEvent("tray-click", GetHashCode(), _click, value);
add
{
if (_click == null)
{
BridgeConnector.Socket.On<JsonElement>("tray-click" + GetHashCode(), (result) =>
{
var array = result.EnumerateArray().ToArray();
var trayClickEventArgs = array[0].Deserialize(ElectronJsonContext.Default.TrayClickEventArgs);
var bounds = array[1].Deserialize(ElectronJsonContext.Default.Rectangle);
_click(trayClickEventArgs, bounds);
});
BridgeConnector.Socket.Emit("register-tray-click", GetHashCode());
}
_click += value;
}
remove
{
_click -= value;
if (_click == null)
{
BridgeConnector.Socket.Off("tray-click" + GetHashCode());
}
}
}
private event Action<TrayClickEventArgs, Rectangle> _click;
@@ -32,8 +58,31 @@ namespace ElectronNET.API
/// </summary>
public event Action<TrayClickEventArgs, Rectangle> OnRightClick
{
add => ApiEventManager.AddTrayEvent("tray-right-click", GetHashCode(), _rightClick, value);
remove => ApiEventManager.RemoveTrayEvent("tray-right-click", GetHashCode(), _rightClick, value);
add
{
if (_rightClick == null)
{
BridgeConnector.Socket.On<JsonElement>("tray-right-click" + GetHashCode(), (result) =>
{
var array = result.EnumerateArray().ToArray();
var trayClickEventArgs = array[0].Deserialize(ElectronJsonContext.Default.TrayClickEventArgs);
var bounds = array[1].Deserialize(ElectronJsonContext.Default.Rectangle);
_rightClick(trayClickEventArgs, bounds);
});
BridgeConnector.Socket.Emit("register-tray-right-click", GetHashCode());
}
_rightClick += value;
}
remove
{
_rightClick -= value;
if (_rightClick == null)
{
BridgeConnector.Socket.Off("tray-right-click" + GetHashCode());
}
}
}
private event Action<TrayClickEventArgs, Rectangle> _rightClick;
@@ -43,8 +92,31 @@ namespace ElectronNET.API
/// </summary>
public event Action<TrayClickEventArgs, Rectangle> OnDoubleClick
{
add => ApiEventManager.AddTrayEvent("tray-double-click", GetHashCode(), _doubleClick, value);
remove => ApiEventManager.RemoveTrayEvent("tray-double-click", GetHashCode(), _doubleClick, value);
add
{
if (_doubleClick == null)
{
BridgeConnector.Socket.On<JsonElement>("tray-double-click" + GetHashCode(), (result) =>
{
var array = result.EnumerateArray().ToArray();
var trayClickEventArgs = array[0].Deserialize(ElectronJsonContext.Default.TrayClickEventArgs);
var bounds = array[1].Deserialize(ElectronJsonContext.Default.Rectangle);
_doubleClick(trayClickEventArgs, bounds);
});
BridgeConnector.Socket.Emit("register-tray-double-click", GetHashCode());
}
_doubleClick += value;
}
remove
{
_doubleClick -= value;
if (_doubleClick == null)
{
BridgeConnector.Socket.Off("tray-double-click" + GetHashCode());
}
}
}
private event Action<TrayClickEventArgs, Rectangle> _doubleClick;
@@ -54,41 +126,37 @@ namespace ElectronNET.API
/// </summary>
public event Action OnBalloonShow
{
add => ApiEventManager.AddEvent("tray-balloon-show", GetHashCode(), _balloonShow, value);
remove => ApiEventManager.RemoveEvent("tray-balloon-show", GetHashCode(), _balloonShow, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action _balloonShow;
/// <summary>
/// Windows: Emitted when the tray balloon is clicked.
/// </summary>
public event Action OnBalloonClick
{
add => ApiEventManager.AddEvent("tray-balloon-click", GetHashCode(), _balloonClick, value);
remove => ApiEventManager.RemoveEvent("tray-balloon-click", GetHashCode(), _balloonClick, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action _balloonClick;
/// <summary>
/// Windows: Emitted when the tray balloon is closed
/// because of timeout or user manually closes it.
/// </summary>
public event Action OnBalloonClosed
{
add => ApiEventManager.AddEvent("tray-balloon-closed", GetHashCode(), _balloonClosed, value);
remove => ApiEventManager.RemoveEvent("tray-balloon-closed", GetHashCode(), _balloonClosed, value);
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private event Action _balloonClosed;
// TODO: Implement macOS Events
private static Tray _tray;
private static readonly object _syncRoot = new();
internal Tray() { }
internal Tray()
{
}
internal static Tray Instance
{
@@ -137,7 +205,7 @@ namespace ElectronNET.API
public async Task Show(string image, MenuItem[] menuItems)
{
menuItems.AddMenuItemsId();
await BridgeConnector.Socket.Emit("create-tray", image, JArray.FromObject(menuItems, this._jsonSerializer)).ConfigureAwait(false);
await BridgeConnector.Socket.Emit("create-tray", image, menuItems).ConfigureAwait(false);
_items.Clear();
_items.AddRange(menuItems);
@@ -209,7 +277,7 @@ namespace ElectronNET.API
/// <param name="options"></param>
public async Task DisplayBalloon(DisplayBalloonOptions options)
{
await BridgeConnector.Socket.Emit("tray-displayBalloon", JObject.FromObject(options, this._jsonSerializer)).ConfigureAwait(false);
await BridgeConnector.Socket.Emit("tray-displayBalloon", options).ConfigureAwait(false);
}
/// <summary>
@@ -218,27 +286,18 @@ namespace ElectronNET.API
/// <returns></returns>
public async Task<bool> IsDestroyedAsync()
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On<bool>("tray-isDestroyedCompleted", (isDestroyed) =>
{
BridgeConnector.Socket.Off("tray-isDestroyedCompleted");
taskCompletionSource.SetResult(isDestroyed);
});
var tcs = new TaskCompletionSource<bool>();
BridgeConnector.Socket.Once<bool>("tray-isDestroyedCompleted", tcs.SetResult);
await BridgeConnector.Socket.Emit("tray-isDestroyed").ConfigureAwait(false);
return await taskCompletionSource.Task.ConfigureAwait(false);
return await tcs.Task.ConfigureAwait(false);
}
private readonly JsonSerializer _jsonSerializer = new()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
private const string ModuleName = "tray";
/// <summary>
/// Subscribe to an unmapped event on the <see cref="Tray"/> module.
/// </summary>
@@ -246,6 +305,7 @@ namespace ElectronNET.API
/// <param name="action">The handler</param>
public void On(string eventName, Action action)
=> Events.Instance.On(ModuleName, eventName, action);
/// <summary>
/// Subscribe to an unmapped event on the <see cref="Tray"/> module.
/// </summary>
@@ -253,6 +313,7 @@ namespace ElectronNET.API
/// <param name="action">The handler</param>
public async Task On<T>(string eventName, Action<T> action)
=> await Events.Instance.On(ModuleName, eventName, action).ConfigureAwait(false);
/// <summary>
/// Subscribe to an unmapped event on the <see cref="Tray"/> module once.
/// </summary>
@@ -260,6 +321,7 @@ namespace ElectronNET.API
/// <param name="action">The handler</param>
public void Once(string eventName, Action action)
=> Events.Instance.Once(ModuleName, eventName, action);
/// <summary>
/// Subscribe to an unmapped event on the <see cref="Tray"/> module once.
/// </summary>

View File

@@ -1,10 +1,7 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ElectronNET.API.Entities;
using System;
using System.Threading.Tasks;
using ElectronNET.Common;
// ReSharper disable InconsistentNaming
namespace ElectronNET.API;
@@ -12,15 +9,19 @@ namespace ElectronNET.API;
/// <summary>
/// Render and control web pages.
/// </summary>
public class WebContents
public class WebContents: ApiBase
{
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.DashesLowerFirst;
protected override SocketTaskMessageNameTypes SocketTaskMessageNameType => SocketTaskMessageNameTypes.DashesLowerFirst;
protected override SocketEventNameTypes SocketEventNameType => SocketEventNameTypes.CamelCase;
/// <summary>
/// Gets the identifier.
/// </summary>
/// <value>
/// The identifier.
/// </value>
public int Id { get; private set; }
public override int Id { get; protected set; }
/// <summary>
/// Manage browser sessions, cookies, cache, proxy settings, etc.
@@ -32,103 +33,85 @@ public class WebContents
/// </summary>
public event Action<bool> OnCrashed
{
add => ApiEventManager.AddEvent("webContents-crashed", Id, _crashed, value, (args) => (bool)args);
remove => ApiEventManager.RemoveEvent("webContents-crashed", Id, _crashed, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action<bool> _crashed;
/// <summary>
/// Emitted when the navigation is done, i.e. the spinner of the tab has
/// stopped spinning, and the onload event was dispatched.
/// </summary>
public event Action OnDidFinishLoad
{
add => ApiEventManager.AddEvent("webContents-didFinishLoad", Id, _didFinishLoad, value);
remove => ApiEventManager.RemoveEvent("webContents-didFinishLoad", Id, _didFinishLoad, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _didFinishLoad;
/// <summary>
/// Emitted when any frame (including main) starts navigating.
/// </summary>
public event Action<string> OnDidStartNavigation
{
add => ApiEventManager.AddEvent("webContents-didStartNavigation", Id, _didStartNavigation, value);
remove => ApiEventManager.RemoveEvent("webContents-didStartNavigation", Id, _didStartNavigation, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action<string> _didStartNavigation;
/// <summary>
/// Emitted when a main frame navigation is done.
/// This event is not emitted for in-page navigations, such as clicking anchor links or updating the window.location.hash. Use did-navigate-in-page event for this purpose.
/// </summary>
public event Action<OnDidNavigateInfo> OnDidNavigate
{
add => ApiEventManager.AddEvent("webContents-didNavigate", Id, _didNavigate, value);
remove => ApiEventManager.RemoveEvent("webContents-didNavigate", Id, _didNavigate, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action<OnDidNavigateInfo> _didNavigate;
/// <summary>
/// Emitted when a server side redirect occurs during navigation. For example a 302 redirect.
/// This event will be emitted after OnDidStartNavigation and always before the OnDidRedirectNavigation event for the same navigation.
/// </summary>
public event Action<string> OnWillRedirect
{
add => ApiEventManager.AddEvent("webContents-willRedirect", Id, _willRedirect, value);
remove => ApiEventManager.RemoveEvent("webContents-willRedirect", Id, _willRedirect, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action<string> _willRedirect;
/// <summary>
/// Emitted after a server side redirect occurs during navigation. For example a 302 redirect.
/// </summary>
public event Action<string> OnDidRedirectNavigation
{
add => ApiEventManager.AddEvent("webContents-didRedirectNavigation", Id, _didRedirectNavigation, value);
remove => ApiEventManager.RemoveEvent("webContents-didRedirectNavigation", Id, _didRedirectNavigation, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action<string> _didRedirectNavigation;
/// <summary>
/// This event is like OnDidFinishLoad but emitted when the load failed.
/// </summary>
public event Action<OnDidFailLoadInfo> OnDidFailLoad
{
add => ApiEventManager.AddEvent("webContents-didFailLoad", Id, _didFailLoad, value, (args) => ((JObject)args).ToObject<OnDidFailLoadInfo>());
remove => ApiEventManager.RemoveEvent("webContents-didFailLoad", Id, _didFailLoad, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action<OnDidFailLoadInfo> _didFailLoad;
/// <summary>
/// Emitted when an input event is sent to the WebContents.
/// </summary>
public event Action<InputEvent> InputEvent
{
add => ApiEventManager.AddEvent("webContents-input-event", Id, _inputEvent, value, (args) => ((JObject)args).ToObject<InputEvent>());
remove => ApiEventManager.RemoveEvent("webContents-input-event", Id, _inputEvent, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action<InputEvent> _inputEvent;
/// <summary>
/// Emitted when the document in the top-level frame is loaded.
/// </summary>
public event Action OnDomReady
{
add => ApiEventManager.AddEvent("webContents-domReady", Id, _domReady, value);
remove => ApiEventManager.RemoveEvent("webContents-domReady", Id, _domReady, value);
add => AddEvent(value, Id);
remove => RemoveEvent(value, Id);
}
private event Action _domReady;
internal WebContents(int id)
{
Id = id;
@@ -149,55 +132,26 @@ public class WebContents
/// <param name="openDevToolsOptions"></param>
public void OpenDevTools(OpenDevToolsOptions openDevToolsOptions)
{
BridgeConnector.Socket.Emit("webContentsOpenDevTools", Id, JObject.FromObject(openDevToolsOptions, _jsonSerializer));
BridgeConnector.Socket.Emit("webContentsOpenDevTools", Id, openDevToolsOptions);
}
/// <summary>
/// Get system printers.
/// </summary>
/// <returns>printers</returns>
public Task<PrinterInfo[]> GetPrintersAsync()
{
var taskCompletionSource = new TaskCompletionSource<PrinterInfo[]>();
BridgeConnector.Socket.On("webContents-getPrinters-completed", (printers) =>
{
BridgeConnector.Socket.Off("webContents-getPrinters-completed");
taskCompletionSource.SetResult(((Newtonsoft.Json.Linq.JArray)printers).ToObject<PrinterInfo[]>());
});
BridgeConnector.Socket.Emit("webContents-getPrinters", Id);
return taskCompletionSource.Task;
}
public Task<PrinterInfo[]> GetPrintersAsync() => GetPropertyAsync<PrinterInfo[]>();
/// <summary>
/// Prints window's web page.
/// </summary>
/// <param name="options"></param>
/// <returns>success</returns>
public Task<bool> PrintAsync(PrintOptions options = null)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("webContents-print-completed", (success) =>
{
BridgeConnector.Socket.Off("webContents-print-completed");
taskCompletionSource.SetResult((bool)success);
});
if(options == null)
{
BridgeConnector.Socket.Emit("webContents-print", Id, "");
}
else
{
BridgeConnector.Socket.Emit("webContents-print", Id, JObject.FromObject(options, _jsonSerializer));
}
return taskCompletionSource.Task;
}
public Task<bool> PrintAsync(PrintOptions options) => GetPropertyAsync<bool>(options);
/// <summary>
/// Prints window's web page.
/// </summary>
/// <returns>success</returns>
public Task<bool> PrintAsync() => GetPropertyAsync<bool>(string.Empty);
/// <summary>
/// Prints window's web page as PDF with Chromium's preview printing custom
@@ -210,24 +164,20 @@ public class WebContents
/// <returns>success</returns>
public Task<bool> PrintToPDFAsync(string path, PrintToPDFOptions options = null)
{
var taskCompletionSource = new TaskCompletionSource<bool>();
var tcs = new TaskCompletionSource<bool>();
BridgeConnector.Socket.On("webContents-printToPDF-completed", (success) =>
{
BridgeConnector.Socket.Off("webContents-printToPDF-completed");
taskCompletionSource.SetResult((bool)success);
});
BridgeConnector.Socket.Once<bool>("webContents-printToPDF-completed", tcs.SetResult);
if(options == null)
if (options == null)
{
BridgeConnector.Socket.Emit("webContents-printToPDF", Id, "", path);
}
else
{
BridgeConnector.Socket.Emit("webContents-printToPDF", Id, JObject.FromObject(options, _jsonSerializer), path);
BridgeConnector.Socket.Emit("webContents-printToPDF", Id, options, path);
}
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -246,19 +196,14 @@ public class WebContents
/// Code execution will be suspended until web page stop loading.
/// </para>
/// </remarks>
public Task<object> ExecuteJavaScriptAsync(string code, bool userGesture = false)
public Task<T> ExecuteJavaScriptAsync<T>(string code, bool userGesture = false)
{
var taskCompletionSource = new TaskCompletionSource<object>();
BridgeConnector.Socket.On("webContents-executeJavaScript-completed", (result) =>
{
BridgeConnector.Socket.Off("webContents-executeJavaScript-completed");
taskCompletionSource.SetResult(result);
});
var tcs = new TaskCompletionSource<T>();
BridgeConnector.Socket.Once<T>("webContents-executeJavaScript-completed", tcs.SetResult);
BridgeConnector.Socket.Emit("webContents-executeJavaScript", Id, code, userGesture);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -268,18 +213,12 @@ public class WebContents
/// <returns>URL of the loaded page</returns>
public Task<string> GetUrl()
{
var taskCompletionSource = new TaskCompletionSource<string>();
var eventString = "webContents-getUrl" + Id;
BridgeConnector.Socket.On(eventString, (url) =>
{
BridgeConnector.Socket.Off(eventString);
taskCompletionSource.SetResult((string)url);
});
var tcs = new TaskCompletionSource<string>();
BridgeConnector.Socket.Once<string>("webContents-getUrl" + Id, tcs.SetResult);
BridgeConnector.Socket.Emit("webContents-getUrl", Id);
return taskCompletionSource.Task;
return tcs.Task;
}
/// <summary>
@@ -314,24 +253,22 @@ public class WebContents
/// <param name="options"></param>
public Task LoadURLAsync(string url, LoadURLOptions options)
{
var taskCompletionSource = new TaskCompletionSource<object>();
var tcs = new TaskCompletionSource<object>();
BridgeConnector.Socket.On("webContents-loadURL-complete" + Id, () =>
{
BridgeConnector.Socket.Off("webContents-loadURL-complete" + Id);
BridgeConnector.Socket.Off("webContents-loadURL-error" + Id);
taskCompletionSource.SetResult(null);
});
BridgeConnector.Socket.On("webContents-loadURL-error" + Id, (error) =>
BridgeConnector.Socket.Once("webContents-loadURL-complete" + Id, () =>
{
BridgeConnector.Socket.Off("webContents-loadURL-error" + Id);
taskCompletionSource.SetException(new InvalidOperationException(error.ToString()));
tcs.SetResult(null);
});
BridgeConnector.Socket.Emit("webContents-loadURL", Id, url, JObject.FromObject(options, _jsonSerializer));
BridgeConnector.Socket.Once<string>("webContents-loadURL-error" + Id, (error) =>
{
tcs.SetException(new InvalidOperationException(error));
});
return taskCompletionSource.Task;
BridgeConnector.Socket.Emit("webContents-loadURL", Id, url, options);
return tcs.Task;
}
/// <summary>
@@ -345,11 +282,4 @@ public class WebContents
{
BridgeConnector.Socket.Emit("webContents-insertCSS", Id, isBrowserWindow, path);
}
private readonly JsonSerializer _jsonSerializer = new()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
};
}
}

View File

@@ -1,5 +1,6 @@
using Newtonsoft.Json.Linq;
using ElectronNET.API.Serialization;
using System;
using System.Text.Json;
namespace ElectronNET.API.Entities
{
@@ -8,6 +9,7 @@ namespace ElectronNET.API.Entities
public int Id { get; set; }
public string Url { get; set; }
public string Method { get; set; }
public int? WebContentsId { get; set; }
// Ensure all necessary properties are included as per Electron documentation
}
@@ -32,18 +34,17 @@ namespace ElectronNET.API.Entities
{
if (_onBeforeRequest == null)
{
BridgeConnector.Socket.On($"webContents-session-webRequest-onBeforeRequest{Id}",
BridgeConnector.Socket.On<JsonElement>($"webContents-session-webRequest-onBeforeRequest{Id}",
(args) =>
{
////var details = ((JObject)args[0]).ToObject<OnBeforeRequestDetails>();
////var callback = args.Length > 1 ? (Action<object>)((response) => { BridgeConnector.Socket.Emit($"webContents-session-webRequest-onBeforeRequest-response{Id}", response); }) : null;
var details = ((JObject)args).ToObject<OnBeforeRequestDetails>();
var callback = (Action<object>)((response) => { BridgeConnector.Socket.Emit($"webContents-session-webRequest-onBeforeRequest-response{Id}", response); });
{
//// var details0 = args[0].Deserialize<OnBeforeRequestDetails>(ElectronNET.ElectronJson.Options);
var details = args.Deserialize<OnBeforeRequestDetails>(ElectronJson.Options);
var callback = (Action<object>)((response) => { BridgeConnector.Socket.Emit($"webContents-session-webRequest-onBeforeRequest-response{Id}", response); });
_onBeforeRequest?.Invoke(details, callback);
});
_onBeforeRequest?.Invoke(details, callback);
});
BridgeConnector.Socket.Emit("register-webContents-session-webRequest-onBeforeRequest", Id, JObject.FromObject(filter));
BridgeConnector.Socket.Emit("register-webContents-session-webRequest-onBeforeRequest", Id, filter);
}
_onBeforeRequest += listener;
@@ -58,4 +59,4 @@ namespace ElectronNET.API.Entities
}
}
}
}
}

View File

@@ -1,12 +1,10 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using ElectronNET.API.Entities;
using ElectronNET.API.Serialization;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text.Json;
using System.Threading.Tasks;
namespace ElectronNET.API
@@ -19,7 +17,9 @@ namespace ElectronNET.API
private static WindowManager _windowManager;
private static readonly object SyncRoot = new();
internal WindowManager() { }
internal WindowManager()
{
}
internal static WindowManager Instance
{
@@ -55,6 +55,7 @@ namespace ElectronNET.API
_isQuitOnWindowAllClosed = value;
}
}
private bool _isQuitOnWindowAllClosed = true;
/// <summary>
@@ -95,36 +96,28 @@ namespace ElectronNET.API
/// <returns></returns>
public async Task<BrowserWindow> CreateWindowAsync(BrowserWindowOptions options, string loadUrl = "http://localhost")
{
var taskCompletionSource = new TaskCompletionSource<BrowserWindow>();
var tcs = new TaskCompletionSource<BrowserWindow>();
BridgeConnector.Socket.On("BrowserWindowCreated", (id) =>
BridgeConnector.Socket.Once<int>("BrowserWindowCreated", (id) =>
{
BridgeConnector.Socket.Off("BrowserWindowCreated");
var browserWindowId = int.Parse(id.ToString()!);
var browserWindow = new BrowserWindow(browserWindowId);
var browserWindow = new BrowserWindow(id);
_browserWindows.Add(browserWindow);
taskCompletionSource.SetResult(browserWindow);
tcs.SetResult(browserWindow);
});
BridgeConnector.Socket.On<object>("BrowserWindowClosed", (ids) =>
BridgeConnector.Socket.Once<int[]>("BrowserWindowClosed", (ids) =>
{
BridgeConnector.Socket.Off("BrowserWindowClosed");
var browserWindowIds = ((JArray)ids).ToObject<int[]>();
for (int index = 0; index < _browserWindows.Count; index++)
{
if (!browserWindowIds.Contains(_browserWindows[index].Id))
if (!ids.Contains(_browserWindows[index].Id))
{
_browserWindows.RemoveAt(index);
}
}
});
if (loadUrl.ToUpper() == "HTTP://LOCALHOST" && ElectronNetRuntime.AspNetWebPort.HasValue)
if (loadUrl.Equals("http://localhost", StringComparison.OrdinalIgnoreCase) && ElectronNetRuntime.AspNetWebPort.HasValue)
{
loadUrl = $"{loadUrl}:{ElectronNetRuntime.AspNetWebPort}";
}
@@ -142,7 +135,7 @@ namespace ElectronNET.API
options.X = 0;
options.Y = 0;
await BridgeConnector.Socket.Emit("createBrowserWindow", JObject.FromObject(options, this._jsonSerializer), loadUrl).ConfigureAwait(false);
await BridgeConnector.Socket.Emit("createBrowserWindow", options, loadUrl).ConfigureAwait(false);
}
else
{
@@ -153,10 +146,10 @@ namespace ElectronNET.API
options.X -= 7;
}
await BridgeConnector.Socket.Emit("createBrowserWindow", JObject.FromObject(options, this._jsonSerializer), loadUrl).ConfigureAwait(false);
await BridgeConnector.Socket.Emit("createBrowserWindow", options, loadUrl).ConfigureAwait(false);
}
return await taskCompletionSource.Task.ConfigureAwait(false);
return await tcs.Task.ConfigureAwait(false);
}
private bool IsWindows10()
@@ -184,34 +177,21 @@ namespace ElectronNET.API
/// <returns></returns>
public async Task<BrowserView> CreateBrowserViewAsync(BrowserViewConstructorOptions options)
{
var taskCompletionSource = new TaskCompletionSource<BrowserView>();
var tcs = new TaskCompletionSource<BrowserView>();
BridgeConnector.Socket.On("BrowserViewCreated", (id) =>
BridgeConnector.Socket.Once<int>("BrowserViewCreated", (id) =>
{
BridgeConnector.Socket.Off("BrowserViewCreated");
string browserViewId = id.ToString();
BrowserView browserView = new BrowserView(int.Parse(browserViewId));
BrowserView browserView = new(id);
_browserViews.Add(browserView);
taskCompletionSource.SetResult(browserView);
tcs.SetResult(browserView);
});
var ownjsonSerializer = new JsonSerializer()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
await BridgeConnector.Socket.Emit("createBrowserView", JObject.FromObject(options, ownjsonSerializer)).ConfigureAwait(false);
await BridgeConnector.Socket.Emit("createBrowserView", options).ConfigureAwait(false);
return await taskCompletionSource.Task.ConfigureAwait(false);
return await tcs.Task.ConfigureAwait(false);
}
private readonly JsonSerializer _jsonSerializer = new()
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
}
}
}

View File

@@ -16,7 +16,8 @@ namespace ElectronNET.API
private readonly TextInfo _textInfo = new CultureInfo("en-US", false).TextInfo;
private Events()
{ }
{
}
public static Events Instance
{
@@ -94,6 +95,5 @@ namespace ElectronNET.API
BridgeConnector.Socket.Once(listener, action);
await BridgeConnector.Socket.Emit(subscriber, eventName, listener).ConfigureAwait(false);
}
}
}
}

View File

@@ -2,11 +2,12 @@
// ReSharper disable once CheckNamespace
namespace ElectronNET.API;
using ElectronNET.API.Serialization;
using SocketIO.Serializer.SystemTextJson;
using System;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using SocketIO.Serializer.NewtonsoftJson;
using SocketIO = SocketIOClient.SocketIO;
internal class SocketIoFacade
@@ -17,14 +18,9 @@ internal class SocketIoFacade
public SocketIoFacade(string uri)
{
_socket = new SocketIO(uri);
var jsonSerializer = new NewtonsoftJsonSerializer(new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore,
DefaultValueHandling = DefaultValueHandling.Ignore
});
_socket.Serializer = jsonSerializer;
_socket.Serializer = new SystemTextJsonSerializer(ElectronJson.Options);
// Use default System.Text.Json serializer from SocketIOClient.
// Outgoing args are normalized to camelCase via SerializeArg in Emit.
}
public event EventHandler BridgeDisconnected;
@@ -33,10 +29,7 @@ internal class SocketIoFacade
public void Connect()
{
_socket.OnError += (sender, e) =>
{
Console.WriteLine($"BridgeConnector Error: {sender} {e}");
};
_socket.OnError += (sender, e) => { Console.WriteLine($"BridgeConnector Error: {sender} {e}"); };
_socket.OnConnected += (_, _) =>
{
@@ -57,10 +50,7 @@ internal class SocketIoFacade
{
lock (_lockObj)
{
_socket.On(eventName, _ =>
{
Task.Run(action);
});
_socket.On(eventName, _ => { Task.Run(action); });
}
}
@@ -76,14 +66,14 @@ internal class SocketIoFacade
}
}
// TODO: Remove this method when SocketIoClient supports object deserialization
// Keep object overload for compatibility; value will be a JsonElement boxed as object.
public void On(string eventName, Action<object> action)
{
lock (_lockObj)
{
_socket.On(eventName, response =>
{
var value = response.GetValue<object>();
var value = (object)response.GetValue<JsonElement>();
////Console.WriteLine($"Called Event {eventName} - data {value}");
Task.Run(() => action(value));
});
@@ -96,7 +86,7 @@ internal class SocketIoFacade
{
_socket.On(eventName, _ =>
{
_socket.Off(eventName);
this.Off(eventName);
Task.Run(action);
});
}
@@ -107,10 +97,10 @@ internal class SocketIoFacade
lock (_lockObj)
{
_socket.On(eventName, (socketIoResponse) =>
{
_socket.Off(eventName);
Task.Run(() => action(socketIoResponse.GetValue<T>()));
});
{
this.Off(eventName);
Task.Run(() => action(socketIoResponse.GetValue<T>()));
});
}
}
@@ -131,4 +121,4 @@ internal class SocketIoFacade
{
_socket.Dispose();
}
}
}

View File

@@ -1,99 +0,0 @@
using System;
using ElectronNET.API;
using ElectronNET.API.Entities;
using Newtonsoft.Json.Linq;
namespace ElectronNET.Common;
internal static class ApiEventManager
{
internal static void AddEvent(string eventName, object id, Action callback, Action value, string suffix = "")
{
if (callback == null)
{
BridgeConnector.Socket.On(eventName + id, () => { callback(); });
BridgeConnector.Socket.Emit($"register-{eventName}{suffix}", id);
}
callback += value;
}
internal static void RemoveEvent(string eventName, object id, Action callback, Action value)
{
callback -= value;
if (callback == null) BridgeConnector.Socket.Off(eventName + id);
}
internal static void AddEvent<T>(string eventName, object id, Action<T> callback, Action<T> value, Func<object, T> converter, string suffix = "")
{
if (callback == null)
{
BridgeConnector.Socket.On(eventName + id, (args) =>
{
var converted = converter.Invoke(args);
callback(converted);
});
BridgeConnector.Socket.Emit($"register-{eventName}{suffix}", id);
}
callback += value;
}
internal static void AddEvent<T>(string eventName, object id, Action<T> callback, Action<T> value)
{
if (callback == null)
{
BridgeConnector.Socket.On<T>(eventName + id, (args) => callback(args));
BridgeConnector.Socket.Emit($"register-{eventName}", id);
}
callback += value;
}
internal static void RemoveEvent<T>(string eventName, object id, Action<T> callback, Action<T> value)
{
callback -= value;
if (callback == null) BridgeConnector.Socket.Off(eventName + id);
}
internal static void AddTrayEvent(string eventName, object id, Action<TrayClickEventArgs, Rectangle> callback, Action<TrayClickEventArgs, Rectangle> value)
{
if (callback == null)
{
BridgeConnector.Socket.On<dynamic>(eventName + id, (result) =>
{
var args = ((JArray)result).ToObject<object[]>();
var trayClickEventArgs = ((JObject)args[0]).ToObject<TrayClickEventArgs>();
var bounds = ((JObject)args[1]).ToObject<Rectangle>();
callback(trayClickEventArgs, bounds);
});
BridgeConnector.Socket.Emit($"register-{eventName}", id);
callback += value;
}
}
internal static void RemoveTrayEvent(string eventName, object id, Action<TrayClickEventArgs, Rectangle> callback, Action<TrayClickEventArgs, Rectangle> value)
{
callback -= value;
if (callback == null) BridgeConnector.Socket.Off(eventName + id);
}
internal static void AddScreenEvent(string eventName, object id, Action<Display, string[]> callback, Action<Display, string[]> value)
{
if (callback == null)
{
BridgeConnector.Socket.On(eventName + id, (args) =>
{
var display = ((JArray)args).First.ToObject<Display>();
var metrics = ((JArray)args).Last.ToObject<string[]>();
callback(display, metrics);
});
BridgeConnector.Socket.Emit($"register-{eventName}", id);
callback += value;
}
}
internal static void RemoveScreenEvent(string eventName, object id, Action<Display, string[]> callback, Action<Display, string[]> value)
{
callback -= value;
if (callback == null) BridgeConnector.Socket.Off(eventName + id);
}
}

View File

@@ -1,9 +1,11 @@
namespace ElectronNET.Common
{
using System;
using ElectronNET.Runtime.Data;
using ElectronNET.Runtime.Services;
using System.Globalization;
using System.Text.RegularExpressions;
using System;
using ElectronNET.Runtime.Data;
using ElectronNET.Runtime.Services;
namespace ElectronNET.Common
{
internal static class Extensions
{
public static bool IsUnpackaged(this StartupMethod method)
@@ -49,6 +51,26 @@
return str;
}
public static string StripOn(this string str)
{
if (string.IsNullOrWhiteSpace(str) || !str.StartsWith("On", StringComparison.Ordinal))
{
return str;
}
return str.Substring(2);
}
public static string ToDashedEventName(this string str)
{
return string.Join("-", Regex.Split(str.StripOn(), "(?<!^)(?=[A-Z])")).ToLower(CultureInfo.InvariantCulture);
}
public static string ToCamelCaseEventName(this string str)
{
return str.StripOn().LowerFirst();
}
public static bool IsReady(this LifetimeServiceBase service)
{

View File

@@ -18,7 +18,7 @@
/// and .net versions and on every platform where .net runs. This is just the innermost core, that's why
/// there are many dead ends, but it has all the crucial parts.
/// </remarks>
/// <seealso cref="System.IDisposable" />
/// <seealso cref="IDisposable" />
[SuppressMessage("ReSharper", "SuspiciousLockOverSynchronizationPrimitive")]
public class ProcessRunner : IDisposable
{
@@ -322,7 +322,7 @@
/// <paramref name="cancellationToken"/> has been triggered.
/// This method does not end the process itself.</remarks>
/// <returns>true, if the process has exited, false if the process is still running.</returns>
public async Task<bool> WaitForExitAsync(CancellationToken cancellationToken = default(CancellationToken))
public async Task<bool> WaitForExitAsync(CancellationToken cancellationToken = default)
{
var proc = this.process;

View File

@@ -16,7 +16,7 @@
private ProcessWindowStyle windowStyle;
/// <summary>
/// Default constructor. At least the <see cref='System.Diagnostics.ProcessStartInfo.FileName'/>
/// Default constructor. At least the <see cref='ProcessStartInfo.FileName'/>
/// property must be set before starting the process.
/// </summary>
public RunnerParams()

View File

@@ -1,54 +1,45 @@
namespace ElectronNET.Converter;
using ElectronNET.API.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
/// <summary>
///
/// </summary>
public class ModifierTypeListConverter : JsonConverter<List<ModifierType>>
{
/// <summary>
///
/// </summary>
/// <param name="reader"></param>
/// <param name="objectType"></param>
/// <param name="existingValue"></param>
/// <param name="hasExistingValue"></param>
/// <param name="serializer"></param>
/// <returns></returns>
public override List<ModifierType> ReadJson(JsonReader reader, Type objectType, List<ModifierType> existingValue, bool hasExistingValue, JsonSerializer serializer)
public override List<ModifierType> Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var token = JToken.Load(reader);
if (token.Type == JTokenType.Null)
if (reader.TokenType == JsonTokenType.Null)
{
return null;
}
return token.ToObject<List<string>>().Select(m => (ModifierType)Enum.Parse(typeof(ModifierType), m)).ToList();
var list = new List<ModifierType>();
if (reader.TokenType != JsonTokenType.StartArray)
{
throw new JsonException("Expected array for ModifierType list");
}
while (reader.Read())
{
if (reader.TokenType == JsonTokenType.EndArray) break;
if (reader.TokenType != JsonTokenType.String) throw new JsonException("Expected string enum value");
var s = reader.GetString();
list.Add((ModifierType)Enum.Parse(typeof(ModifierType), s, ignoreCase: true));
}
return list;
}
/// <summary>
///
/// </summary>
/// <param name="writer"></param>
/// <param name="value"></param>
/// <param name="serializer"></param>
public override void WriteJson(JsonWriter writer, List<ModifierType> value, JsonSerializer serializer)
public override void Write(Utf8JsonWriter writer, List<ModifierType> value, JsonSerializerOptions options)
{
writer.WriteStartArray();
foreach (var modifier in value)
{
writer.WriteValue(modifier.ToString());
writer.WriteStringValue(modifier.ToString());
}
writer.WriteEndArray();
}
}
}

View File

@@ -1,43 +1,46 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using ElectronNET.API.Entities;
using ElectronNET.API.Serialization;
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace ElectronNET.Converter;
public class PageSizeConverter : JsonConverter<PageSize>
{
public override PageSize ReadJson(JsonReader reader, Type objectType, PageSize existingValue, bool hasExistingValue, JsonSerializer serializer)
public override PageSize Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonToken.String)
if (reader.TokenType == JsonTokenType.String)
{
return (string)reader.Value;
return reader.GetString();
}
else if (reader.TokenType == JsonToken.StartObject)
else if (reader.TokenType == JsonTokenType.StartObject)
{
return serializer.Deserialize<PageSize>(reader);
return JsonSerializer.Deserialize<PageSize>(ref reader, ElectronJson.Options);
}
else
{
throw new JsonSerializationException("Invalid value for PageSize. Expected true, false, or an object.");
throw new JsonException("Invalid value for PageSize. Expected string or an object.");
}
}
public override void WriteJson(JsonWriter writer, PageSize value, JsonSerializer serializer)
public override void Write(Utf8JsonWriter writer, PageSize value, JsonSerializerOptions options)
{
if (value is null)
{
writer.WriteUndefined();
return;
}
var str = (string)value;
if (str is not null)
{
writer.WriteValue(str);
writer.WriteStringValue(str);
}
else
{
serializer.Serialize(writer, value);
JsonSerializer.Serialize(writer, value, ElectronJson.Options);
}
}
}

View File

@@ -1,43 +1,46 @@
using ElectronNET.API.Entities;
using Newtonsoft.Json;
using ElectronNET.API.Entities;
using ElectronNET.API.Serialization;
using System;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace ElectronNET.Converter;
public class TitleBarOverlayConverter : JsonConverter<TitleBarOverlay>
{
public override TitleBarOverlay ReadJson(JsonReader reader, Type objectType, TitleBarOverlay existingValue, bool hasExistingValue, JsonSerializer serializer)
public override TitleBarOverlay Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonToken.Boolean)
if (reader.TokenType == JsonTokenType.True || reader.TokenType == JsonTokenType.False)
{
return (bool)reader.Value;
return (bool)reader.GetBoolean();
}
else if (reader.TokenType == JsonToken.StartObject)
else if (reader.TokenType == JsonTokenType.StartObject)
{
return serializer.Deserialize<TitleBarOverlay>(reader);
using var doc = JsonDocument.ParseValue(ref reader);
return doc.RootElement.Deserialize<TitleBarOverlay>(ElectronJson.Options);
}
else
{
throw new JsonSerializationException("Invalid value for TitleBarOverlay. Expected true, false, or an object.");
throw new JsonException("Invalid value for TitleBarOverlay. Expected boolean or an object.");
}
}
public override void WriteJson(JsonWriter writer, TitleBarOverlay value, JsonSerializer serializer)
public override void Write(Utf8JsonWriter writer, TitleBarOverlay value, JsonSerializerOptions options)
{
if (value is null)
{
writer.WriteUndefined();
return;
}
var @bool = (bool?)value;
if (@bool.HasValue)
{
writer.WriteValue(@bool.Value);
writer.WriteBooleanValue(@bool.Value);
}
else
{
serializer.Serialize(writer, value);
JsonSerializer.Serialize(writer, value, ElectronJson.Options);
}
}
}
}

View File

@@ -3,7 +3,7 @@
<Import Project="..\common.props" />
<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<TargetFrameworks>net6.0;net8.0;net10.0</TargetFrameworks>
<PackageOutputPath>..\..\artifacts</PackageOutputPath>
<PackageId>$(PackageNamePrefix).API</PackageId>
<Title>$(PackageId)</Title>
@@ -27,8 +27,6 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="SocketIO.Serializer.NewtonsoftJson" Version="3.1.2" />
<PackageReference Include="SocketIOClient" Version="3.1.2" />
<PackageReference Include="System.Drawing.Common" Version="8.0.16" />
<PackageReference Include="System.Text.Json" Version="8.0.5" />
@@ -38,4 +36,4 @@
<InternalsVisibleTo Include="ElectronNET.AspNet" />
<InternalsVisibleTo Include="ElectronNET.Core.AspNet" />
</ItemGroup>
</Project>
</Project>

View File

@@ -1,12 +1,12 @@
namespace ElectronNET
{
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
using ElectronNET.API;
using ElectronNET.Runtime;
using ElectronNET.Runtime.Controllers;
using ElectronNET.Runtime.Data;
using System;
using System.Collections.Immutable;
using System.Threading.Tasks;
public static class ElectronNetRuntime
{

View File

@@ -1,10 +1,10 @@
namespace ElectronNET.Runtime.Controllers
{
using System.Threading.Tasks;
using ElectronNET.API;
using ElectronNET.Runtime.Services;
using ElectronNET.Runtime.Services.ElectronProcess;
using ElectronNET.Runtime.Services.SocketBridge;
using System.Threading.Tasks;
internal abstract class RuntimeControllerBase : LifetimeServiceBase, IElectronNetRuntimeController
{
@@ -20,7 +20,6 @@
protected override Task StartCore()
{
return Task.CompletedTask;
}
@@ -28,6 +27,5 @@
{
return Task.CompletedTask;
}
}
}
}

View File

@@ -1,13 +1,13 @@
namespace ElectronNET.Runtime.Controllers
{
using System;
using System.Threading.Tasks;
using ElectronNET.API;
using ElectronNET.Common;
using ElectronNET.Runtime.Data;
using ElectronNET.Runtime.Helpers;
using ElectronNET.Runtime.Services.ElectronProcess;
using ElectronNET.Runtime.Services.SocketBridge;
using System;
using System.Threading.Tasks;
internal class RuntimeControllerDotNetFirst : RuntimeControllerBase
{
@@ -68,7 +68,6 @@
private void SocketBridge_Ready(object sender, EventArgs e)
{
this.TransitionState(LifetimeState.Ready);
}
private void SocketBridge_Stopped(object sender, EventArgs e)
@@ -102,6 +101,5 @@
this.electronProcess.Stop();
return Task.CompletedTask;
}
}
}
}

View File

@@ -1,11 +1,11 @@
namespace ElectronNET.Runtime.Controllers
{
using System;
using System.Threading.Tasks;
using ElectronNET.API;
using ElectronNET.Runtime.Data;
using ElectronNET.Runtime.Services.ElectronProcess;
using ElectronNET.Runtime.Services.SocketBridge;
using System;
using System.Threading.Tasks;
internal class RuntimeControllerElectronFirst : RuntimeControllerBase
{
@@ -103,6 +103,5 @@
this.socketBridge.Stop();
return Task.CompletedTask;
}
}
}
}

View File

@@ -1,8 +1,8 @@
namespace ElectronNET.Runtime
{
using ElectronNET.Runtime.Data;
using System;
using System.Threading.Tasks;
using ElectronNET.Runtime.Data;
public interface IElectronNetRuntimeController
{

View File

@@ -1,11 +1,11 @@
namespace ElectronNET.Runtime.Services.ElectronProcess
{
using ElectronNET.Common;
using ElectronNET.Runtime.Data;
using System;
using System.ComponentModel;
using System.IO;
using System.Threading.Tasks;
using ElectronNET.Common;
using ElectronNET.Runtime.Data;
/// <summary>
/// Launches and manages the Electron app process.

View File

@@ -1,10 +1,10 @@
namespace ElectronNET.Runtime.Services.ElectronProcess
{
using ElectronNET.Runtime.Data;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading.Tasks;
using ElectronNET.Runtime.Data;
/// <summary>
/// Launches and manages the Electron app process.

View File

@@ -1,9 +1,9 @@
namespace ElectronNET.Runtime.Services
{
using ElectronNET.Runtime.Data;
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using ElectronNET.Runtime.Data;
public abstract class LifetimeServiceBase
{
@@ -14,7 +14,9 @@
private LifetimeState state = LifetimeState.Uninitialized;
protected LifetimeServiceBase() { }
protected LifetimeServiceBase()
{
}
public event EventHandler Starting;
@@ -132,4 +134,4 @@
}
}
}
}
}

View File

@@ -1,11 +1,11 @@
namespace ElectronNET.Runtime.Services.SocketBridge
{
using System;
using System.Threading.Tasks;
using ElectronNET.API;
using ElectronNET.Runtime.Data;
using System;
using System.Threading.Tasks;
internal class SocketBridgeService : LifetimeServiceBase
internal class SocketBridgeService : LifetimeServiceBase
{
private readonly int socketPort;
private readonly string socketUrl;
@@ -40,7 +40,10 @@
private void Connect()
{
this.socket.Connect();
this.TransitionState(LifetimeState.Started);
if (this.State < LifetimeState.Started)
{
this.TransitionState(LifetimeState.Started);
}
}
private void Socket_BridgeDisconnected(object sender, EventArgs e)
@@ -53,4 +56,4 @@
this.TransitionState(LifetimeState.Ready);
}
}
}
}

View File

@@ -103,7 +103,7 @@
{
ElectronNetRuntime.ElectronProcessId = result;
Console.WriteLine("Electron Process ID: " + result);
Console.WriteLine("Electron Process ID: " + result);
}
}
}
@@ -122,16 +122,27 @@
}
ElectronNetRuntime.ElectronExecutable = executable;
}
private BuildInfo GatherBuildInfo()
{
var buildInfo = new BuildInfo();
var attributes = Assembly.GetEntryAssembly()?.GetCustomAttributes<AssemblyMetadataAttribute>().ToList();
var electronAssembly = Assembly.GetEntryAssembly();
if (attributes?.Count > 0)
if (electronAssembly == null)
{
return buildInfo;
}
if (electronAssembly.GetName().Name == "testhost" || electronAssembly.GetName().Name == "ReSharperTestRunner")
{
electronAssembly = AppDomain.CurrentDomain.GetData("ElectronTestAssembly") as Assembly ?? electronAssembly;
}
var attributes = electronAssembly.GetCustomAttributes<AssemblyMetadataAttribute>().ToList();
if (attributes.Count > 0)
{
buildInfo.ElectronExecutable = attributes.FirstOrDefault(e => e.Key == nameof(buildInfo.ElectronExecutable))?.Value;
buildInfo.ElectronVersion = attributes.FirstOrDefault(e => e.Key == nameof(buildInfo.ElectronVersion))?.Value;
@@ -166,4 +177,4 @@
return buildInfo;
}
}
}
}

View File

@@ -0,0 +1,34 @@
using ElectronNET.API.Entities;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace ElectronNET.API.Serialization
{
internal static class ElectronJson
{
public static readonly JsonSerializerOptions Options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
WriteIndented = false,
Converters =
{
new JsonStringEnumConverter(JsonNamingPolicy.CamelCase)
}
};
}
// Use source generation where feasible for hot paths
[JsonSourceGenerationOptions(WriteIndented = false, PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(TrayClickEventArgs))]
[JsonSerializable(typeof(Rectangle))]
[JsonSerializable(typeof(Display))]
[JsonSerializable(typeof(UpdateInfo))]
[JsonSerializable(typeof(ProgressInfo))]
[JsonSerializable(typeof(UpdateCheckResult))]
[JsonSerializable(typeof(SemVer))]
internal partial class ElectronJsonContext : JsonSerializerContext
{
}
}

View File

@@ -3,7 +3,7 @@
<Import Project="..\common.props" />
<PropertyGroup>
<TargetFrameworks>net6.0;net8.0</TargetFrameworks>
<TargetFrameworks>net6.0;net8.0;net10.0</TargetFrameworks>
<PackageOutputPath>..\..\artifacts</PackageOutputPath>
<PackageId>$(PackageNamePrefix).AspNet</PackageId>
<Title>$(PackageId)</Title>
@@ -20,12 +20,18 @@
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net8.0|AnyCPU'">
<NoWarn>1701;1702;4014;CS4014;CA1416;CS1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net10.0|AnyCPU'">
<NoWarn>1701;1702;4014;CS4014;CA1416;CS1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net6.0|AnyCPU'">
<NoWarn>1701;1702;4014;CS4014;CA1416;CS1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net8.0|AnyCPU'">
<NoWarn>1701;1702;4014;CS4014;CA1416;CS1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|net10.0|AnyCPU'">
<NoWarn>1701;1702;4014;CS4014;CA1416;CS1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>

View File

@@ -5,7 +5,7 @@
using ElectronNET.Runtime.Services;
using Microsoft.Extensions.Hosting;
internal class AspNetLifetimeAdapter : LifetimeServiceBase
internal class AspNetLifetimeAdapter : LifetimeServiceBase
{
private readonly IHostApplicationLifetime lifetimeService;
@@ -24,4 +24,4 @@
return Task.CompletedTask;
}
}
}
}

View File

@@ -34,81 +34,81 @@ module.exports = (socket) => {
});
});
// Properties *****
socket.on('autoUpdater-autoDownload-get', () => {
electronSocket.emit('autoUpdater-autoDownload-get-reply', electron_updater_1.autoUpdater.autoDownload);
socket.on('autoUpdater-autoDownload', () => {
electronSocket.emit('autoUpdater-autoDownload-completed', electron_updater_1.autoUpdater.autoDownload);
});
socket.on('autoUpdater-autoDownload-set', (value) => {
electron_updater_1.autoUpdater.autoDownload = value;
});
socket.on('autoUpdater-autoInstallOnAppQuit-get', () => {
electronSocket.emit('autoUpdater-autoInstallOnAppQuit-get-reply', electron_updater_1.autoUpdater.autoInstallOnAppQuit);
socket.on('autoUpdater-autoInstallOnAppQuit', () => {
electronSocket.emit('autoUpdater-autoInstallOnAppQuit-completed', electron_updater_1.autoUpdater.autoInstallOnAppQuit);
});
socket.on('autoUpdater-autoInstallOnAppQuit-set', (value) => {
electron_updater_1.autoUpdater.autoInstallOnAppQuit = value;
});
socket.on('autoUpdater-allowPrerelease-get', () => {
electronSocket.emit('autoUpdater-allowPrerelease-get-reply', electron_updater_1.autoUpdater.allowPrerelease);
socket.on('autoUpdater-allowPrerelease', () => {
electronSocket.emit('autoUpdater-allowPrerelease-completed', electron_updater_1.autoUpdater.allowPrerelease);
});
socket.on('autoUpdater-allowPrerelease-set', (value) => {
electron_updater_1.autoUpdater.allowPrerelease = value;
});
socket.on('autoUpdater-fullChangelog-get', () => {
electronSocket.emit('autoUpdater-fullChangelog-get-reply', electron_updater_1.autoUpdater.fullChangelog);
socket.on('autoUpdater-fullChangelog', () => {
electronSocket.emit('autoUpdater-fullChangelog-completed', electron_updater_1.autoUpdater.fullChangelog);
});
socket.on('autoUpdater-fullChangelog-set', (value) => {
electron_updater_1.autoUpdater.fullChangelog = value;
});
socket.on('autoUpdater-allowDowngrade-get', () => {
electronSocket.emit('autoUpdater-allowDowngrade-get-reply', electron_updater_1.autoUpdater.allowDowngrade);
socket.on('autoUpdater-allowDowngrade', () => {
electronSocket.emit('autoUpdater-allowDowngrade-completed', electron_updater_1.autoUpdater.allowDowngrade);
});
socket.on('autoUpdater-allowDowngrade-set', (value) => {
electron_updater_1.autoUpdater.allowDowngrade = value;
});
socket.on('autoUpdater-updateConfigPath-get', () => {
electronSocket.emit('autoUpdater-updateConfigPath-get-reply', electron_updater_1.autoUpdater.updateConfigPath || '');
socket.on('autoUpdater-updateConfigPath', () => {
electronSocket.emit('autoUpdater-updateConfigPath-completed', electron_updater_1.autoUpdater.updateConfigPath || '');
});
socket.on('autoUpdater-updateConfigPath-set', (value) => {
electron_updater_1.autoUpdater.updateConfigPath = value;
});
socket.on('autoUpdater-currentVersion-get', () => {
electronSocket.emit('autoUpdater-currentVersion-get-reply', electron_updater_1.autoUpdater.currentVersion);
socket.on('autoUpdater-currentVersion', () => {
electronSocket.emit('autoUpdater-currentVersion-completed', electron_updater_1.autoUpdater.currentVersion);
});
socket.on('autoUpdater-channel-get', () => {
electronSocket.emit('autoUpdater-channel-get-reply', electron_updater_1.autoUpdater.channel || '');
socket.on('autoUpdater-channel', () => {
electronSocket.emit('autoUpdater-channel-completed', electron_updater_1.autoUpdater.channel || '');
});
socket.on('autoUpdater-channel-set', (value) => {
electron_updater_1.autoUpdater.channel = value;
});
socket.on('autoUpdater-requestHeaders-get', () => {
electronSocket.emit('autoUpdater-requestHeaders-get-reply', electron_updater_1.autoUpdater.requestHeaders);
socket.on('autoUpdater-requestHeaders', () => {
electronSocket.emit('autoUpdater-requestHeaders-completed', electron_updater_1.autoUpdater.requestHeaders);
});
socket.on('autoUpdater-requestHeaders-set', (value) => {
electron_updater_1.autoUpdater.requestHeaders = value;
});
socket.on('autoUpdaterCheckForUpdatesAndNotify', async (guid) => {
socket.on('autoUpdater-checkForUpdatesAndNotify', async (guid) => {
electron_updater_1.autoUpdater.checkForUpdatesAndNotify().then((updateCheckResult) => {
electronSocket.emit('autoUpdaterCheckForUpdatesAndNotifyComplete' + guid, updateCheckResult);
electronSocket.emit('autoUpdater-checkForUpdatesAndNotify-completed' + guid, updateCheckResult);
}).catch((error) => {
electronSocket.emit('autoUpdaterCheckForUpdatesAndNotifyError' + guid, error);
electronSocket.emit('autoUpdater-checkForUpdatesAndNotifyError' + guid, error);
});
});
socket.on('autoUpdaterCheckForUpdates', async (guid) => {
socket.on('autoUpdater-checkForUpdates', async (guid) => {
electron_updater_1.autoUpdater.checkForUpdates().then((updateCheckResult) => {
electronSocket.emit('autoUpdaterCheckForUpdatesComplete' + guid, updateCheckResult);
electronSocket.emit('autoUpdater-checkForUpdates-completed' + guid, updateCheckResult);
}).catch((error) => {
electronSocket.emit('autoUpdaterCheckForUpdatesError' + guid, error);
electronSocket.emit('autoUpdater-checkForUpdatesError' + guid, error);
});
});
socket.on('autoUpdaterQuitAndInstall', async (isSilent, isForceRunAfter) => {
socket.on('autoUpdater-quitAndInstall', async (isSilent, isForceRunAfter) => {
electron_updater_1.autoUpdater.quitAndInstall(isSilent, isForceRunAfter);
});
socket.on('autoUpdaterDownloadUpdate', async (guid) => {
socket.on('autoUpdater-downloadUpdate', async (guid) => {
const downloadedPath = await electron_updater_1.autoUpdater.downloadUpdate();
electronSocket.emit('autoUpdaterDownloadUpdateComplete' + guid, downloadedPath);
electronSocket.emit('autoUpdater-downloadUpdate-completed' + guid, downloadedPath);
});
socket.on('autoUpdaterGetFeedURL', async (guid) => {
socket.on('autoUpdater-getFeedURL', async (guid) => {
const feedUrl = await electron_updater_1.autoUpdater.getFeedURL();
electronSocket.emit('autoUpdaterGetFeedURLComplete' + guid, feedUrl || '');
electronSocket.emit('autoUpdater-getFeedURL-completed' + guid, feedUrl || '');
});
};
//# sourceMappingURL=autoUpdater.js.map

View File

@@ -43,101 +43,101 @@ export = (socket: Socket) => {
// Properties *****
socket.on('autoUpdater-autoDownload-get', () => {
electronSocket.emit('autoUpdater-autoDownload-get-reply', autoUpdater.autoDownload);
socket.on('autoUpdater-autoDownload', () => {
electronSocket.emit('autoUpdater-autoDownload-completed', autoUpdater.autoDownload);
});
socket.on('autoUpdater-autoDownload-set', (value) => {
autoUpdater.autoDownload = value;
});
socket.on('autoUpdater-autoInstallOnAppQuit-get', () => {
electronSocket.emit('autoUpdater-autoInstallOnAppQuit-get-reply', autoUpdater.autoInstallOnAppQuit);
socket.on('autoUpdater-autoInstallOnAppQuit', () => {
electronSocket.emit('autoUpdater-autoInstallOnAppQuit-completed', autoUpdater.autoInstallOnAppQuit);
});
socket.on('autoUpdater-autoInstallOnAppQuit-set', (value) => {
autoUpdater.autoInstallOnAppQuit = value;
});
socket.on('autoUpdater-allowPrerelease-get', () => {
electronSocket.emit('autoUpdater-allowPrerelease-get-reply', autoUpdater.allowPrerelease);
socket.on('autoUpdater-allowPrerelease', () => {
electronSocket.emit('autoUpdater-allowPrerelease-completed', autoUpdater.allowPrerelease);
});
socket.on('autoUpdater-allowPrerelease-set', (value) => {
autoUpdater.allowPrerelease = value;
});
socket.on('autoUpdater-fullChangelog-get', () => {
electronSocket.emit('autoUpdater-fullChangelog-get-reply', autoUpdater.fullChangelog);
socket.on('autoUpdater-fullChangelog', () => {
electronSocket.emit('autoUpdater-fullChangelog-completed', autoUpdater.fullChangelog);
});
socket.on('autoUpdater-fullChangelog-set', (value) => {
autoUpdater.fullChangelog = value;
});
socket.on('autoUpdater-allowDowngrade-get', () => {
electronSocket.emit('autoUpdater-allowDowngrade-get-reply', autoUpdater.allowDowngrade);
socket.on('autoUpdater-allowDowngrade', () => {
electronSocket.emit('autoUpdater-allowDowngrade-completed', autoUpdater.allowDowngrade);
});
socket.on('autoUpdater-allowDowngrade-set', (value) => {
autoUpdater.allowDowngrade = value;
});
socket.on('autoUpdater-updateConfigPath-get', () => {
electronSocket.emit('autoUpdater-updateConfigPath-get-reply', autoUpdater.updateConfigPath || '');
socket.on('autoUpdater-updateConfigPath', () => {
electronSocket.emit('autoUpdater-updateConfigPath-completed', autoUpdater.updateConfigPath || '');
});
socket.on('autoUpdater-updateConfigPath-set', (value) => {
autoUpdater.updateConfigPath = value;
});
socket.on('autoUpdater-currentVersion-get', () => {
electronSocket.emit('autoUpdater-currentVersion-get-reply', autoUpdater.currentVersion);
socket.on('autoUpdater-currentVersion', () => {
electronSocket.emit('autoUpdater-currentVersion-completed', autoUpdater.currentVersion);
});
socket.on('autoUpdater-channel-get', () => {
electronSocket.emit('autoUpdater-channel-get-reply', autoUpdater.channel || '');
socket.on('autoUpdater-channel', () => {
electronSocket.emit('autoUpdater-channel-completed', autoUpdater.channel || '');
});
socket.on('autoUpdater-channel-set', (value) => {
autoUpdater.channel = value;
});
socket.on('autoUpdater-requestHeaders-get', () => {
electronSocket.emit('autoUpdater-requestHeaders-get-reply', autoUpdater.requestHeaders);
socket.on('autoUpdater-requestHeaders', () => {
electronSocket.emit('autoUpdater-requestHeaders-completed', autoUpdater.requestHeaders);
});
socket.on('autoUpdater-requestHeaders-set', (value) => {
autoUpdater.requestHeaders = value;
});
socket.on('autoUpdaterCheckForUpdatesAndNotify', async (guid) => {
socket.on('autoUpdater-checkForUpdatesAndNotify', async (guid) => {
autoUpdater.checkForUpdatesAndNotify().then((updateCheckResult) => {
electronSocket.emit('autoUpdaterCheckForUpdatesAndNotifyComplete' + guid, updateCheckResult);
electronSocket.emit('autoUpdater-checkForUpdatesAndNotify-completed' + guid, updateCheckResult);
}).catch((error) => {
electronSocket.emit('autoUpdaterCheckForUpdatesAndNotifyError' + guid, error);
electronSocket.emit('autoUpdater-checkForUpdatesAndNotifyError' + guid, error);
});
});
socket.on('autoUpdaterCheckForUpdates', async (guid) => {
socket.on('autoUpdater-checkForUpdates', async (guid) => {
autoUpdater.checkForUpdates().then((updateCheckResult) => {
electronSocket.emit('autoUpdaterCheckForUpdatesComplete' + guid, updateCheckResult);
electronSocket.emit('autoUpdater-checkForUpdates-completed' + guid, updateCheckResult);
}).catch((error) => {
electronSocket.emit('autoUpdaterCheckForUpdatesError' + guid, error);
electronSocket.emit('autoUpdater-checkForUpdatesError' + guid, error);
});
});
socket.on('autoUpdaterQuitAndInstall', async (isSilent, isForceRunAfter) => {
socket.on('autoUpdater-quitAndInstall', async (isSilent, isForceRunAfter) => {
autoUpdater.quitAndInstall(isSilent, isForceRunAfter);
});
socket.on('autoUpdaterDownloadUpdate', async (guid) => {
socket.on('autoUpdater-downloadUpdate', async (guid) => {
const downloadedPath = await autoUpdater.downloadUpdate();
electronSocket.emit('autoUpdaterDownloadUpdateComplete' + guid, downloadedPath);
electronSocket.emit('autoUpdater-downloadUpdate-completed' + guid, downloadedPath);
});
socket.on('autoUpdaterGetFeedURL', async (guid) => {
socket.on('autoUpdater-getFeedURL', async (guid) => {
const feedUrl = await autoUpdater.getFeedURL();
electronSocket.emit('autoUpdaterGetFeedURLComplete' + guid, feedUrl || '');
electronSocket.emit('autoUpdater-getFeedURL-completed' + guid, feedUrl || '');
});
};

View File

@@ -22,11 +22,11 @@ const browserViewApi = (socket) => {
browserViews.push(browserView);
electronSocket.emit('BrowserViewCreated', browserView['id']);
});
socket.on('browserView-getBounds', (id) => {
socket.on('browserView-bounds', (id) => {
const bounds = getBrowserViewById(id).getBounds();
electronSocket.emit('browserView-getBounds-reply', bounds);
electronSocket.emit('browserView-bounds-completed', bounds);
});
socket.on('browserView-setBounds', (id, bounds) => {
socket.on('browserView-bounds-set', (id, bounds) => {
getBrowserViewById(id).setBounds(bounds);
});
socket.on('browserView-setAutoResize', (id, options) => {

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