Skip to content

Commit 0393b0b

Browse files
committed
Merge branch 'master' into switch-to-new-socket-lib
2 parents 87d97ef + 953f1e2 commit 0393b0b

28 files changed

+572
-1403
lines changed

ElectronNET.API/App.cs

Lines changed: 36 additions & 408 deletions
Large diffs are not rendered by default.

ElectronNET.API/AutoUpdater.cs

Lines changed: 11 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -16,95 +16,31 @@ public sealed class AutoUpdater
1616
/// <summary>
1717
/// Whether to automatically download an update when it is found. (Default is true)
1818
/// </summary>
19-
public Task<bool> IsAutoDownloadEnabledAsync()
20-
{
21-
var taskCompletionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
22-
23-
BridgeConnector.On<bool>("autoUpdater-autoDownload-get-reply", (result) =>
24-
{
25-
BridgeConnector.Off("autoUpdater-autoDownload-get-reply");
26-
taskCompletionSource.SetResult(result);
27-
});
28-
29-
BridgeConnector.Emit("autoUpdater-autoDownload-get");
30-
31-
return taskCompletionSource.Task;
32-
}
19+
public Task<bool> IsAutoDownloadEnabledAsync() => BridgeConnector.OnResult<bool>("autoUpdater-autoDownload-get", "autoUpdater-autoDownload-get-reply");
3320

3421
/// <summary>
3522
/// Whether to automatically install a downloaded update on app quit (if `QuitAndInstall` was not called before).
3623
///
3724
/// Applicable only on Windows and Linux.
3825
/// </summary>
39-
public Task<bool> IsAutoInstallOnAppQuitEnabledAsync()
40-
{
41-
var taskCompletionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
42-
43-
BridgeConnector.On<bool>("autoUpdater-autoInstallOnAppQuit-get-reply", (result) =>
44-
{
45-
BridgeConnector.Off("autoUpdater-autoInstallOnAppQuit-get-reply");
46-
taskCompletionSource.SetResult(result);
47-
});
48-
49-
BridgeConnector.Emit("autoUpdater-autoInstallOnAppQuit-get");
50-
51-
return taskCompletionSource.Task;
52-
}
26+
public Task<bool> IsAutoInstallOnAppQuitEnabledAsync() => BridgeConnector.OnResult<bool>("autoUpdater-autoInstallOnAppQuit-get", "autoUpdater-autoInstallOnAppQuit-get-reply");
5327

5428
/// <summary>
5529
/// *GitHub provider only.* Whether to allow update to pre-release versions.
5630
/// Defaults to "true" if application version contains prerelease components (e.g. "0.12.1-alpha.1", here "alpha" is a prerelease component), otherwise "false".
5731
///
5832
/// If "true", downgrade will be allowed("allowDowngrade" will be set to "true").
5933
/// </summary>
60-
public Task<bool> IsAllowPrereleaseEnabledAsync()
61-
{
62-
var taskCompletionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
63-
64-
BridgeConnector.On<bool>("autoUpdater-allowPrerelease-get-reply", (result) =>
65-
{
66-
BridgeConnector.Off("autoUpdater-allowPrerelease-get-reply");
67-
taskCompletionSource.SetResult(result);
68-
});
69-
70-
BridgeConnector.Emit("autoUpdater-allowPrerelease-get");
71-
72-
return taskCompletionSource.Task;
73-
}
34+
public Task<bool> IsAllowPrereleaseEnabledAsync() => BridgeConnector.OnResult<bool>("autoUpdater-allowPrerelease-get", "autoUpdater-allowPrerelease-get-reply");
7435

7536
/// <summary>
7637
/// *GitHub provider only.*
7738
/// Get all release notes (from current version to latest), not just the latest (Default is false).
7839
/// </summary>
79-
public Task<bool> IsFullChangeLogEnabledAsync()
80-
{
81-
var taskCompletionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
82-
83-
BridgeConnector.On<bool>("autoUpdater-fullChangelog-get-reply", (result) =>
84-
{
85-
BridgeConnector.Off("autoUpdater-fullChangelog-get-reply");
86-
taskCompletionSource.SetResult(result);
87-
});
88-
89-
BridgeConnector.Emit("autoUpdater-fullChangelog-get");
90-
91-
return taskCompletionSource.Task;
92-
}
93-
94-
public Task<bool> IsAllowDowngradeEnabledAsync()
95-
{
96-
var taskCompletionSource = new TaskCompletionSource<bool>(TaskCreationOptions.RunContinuationsAsynchronously);
97-
98-
BridgeConnector.On<bool>("autoUpdater-allowDowngrade-get-reply", (result) =>
99-
{
100-
BridgeConnector.Off("autoUpdater-allowDowngrade-get-reply");
101-
taskCompletionSource.SetResult(result);
102-
});
40+
public Task<bool> IsFullChangeLogEnabledAsync() => BridgeConnector.OnResult<bool>("autoUpdater-fullChangelog-get", "autoUpdater-fullChangelog-get-reply");
10341

104-
BridgeConnector.Emit("autoUpdater-allowDowngrade-get");
105-
106-
return taskCompletionSource.Task;
107-
}
42+
public Task<bool> IsAllowDowngradeEnabledAsync() => BridgeConnector.OnResult<bool>("autoUpdater-allowDowngrade-get", "autoUpdater-allowDowngrade-get-reply");
43+
10844

10945
/// <summary>
11046
/// Whether to automatically download an update when it is found. (Default is true)
@@ -172,72 +108,23 @@ public bool AllowDowngrade
172108
/// <summary>
173109
/// For test only.
174110
/// </summary>
175-
public Task<string> GetUpdateConfigPathAsync()
176-
{
177-
var taskCompletionSource = new TaskCompletionSource<string>(TaskCreationOptions.RunContinuationsAsynchronously);
178-
179-
BridgeConnector.On<string>("autoUpdater-updateConfigPath-get-reply", (result) =>
180-
{
181-
BridgeConnector.Off("autoUpdater-updateConfigPath-get-reply");
182-
taskCompletionSource.SetResult(result.ToString());
183-
});
184-
185-
BridgeConnector.Emit("autoUpdater-updateConfigPath-get");
186-
187-
return taskCompletionSource.Task;
188-
}
111+
public Task<string> GetUpdateConfigPathAsync() => BridgeConnector.OnResult<string>("autoUpdater-updateConfigPath-get", "autoUpdater-updateConfigPath-get-reply");
189112

190113
/// <summary>
191114
/// The current application version
192115
/// </summary>
193-
public Task<SemVer> GetCurrentVersionAsync()
194-
{
195-
var taskCompletionSource = new TaskCompletionSource<SemVer>(TaskCreationOptions.RunContinuationsAsynchronously);
196-
197-
BridgeConnector.On<SemVer>("autoUpdater-currentVersion-get-reply", (version) =>
198-
{
199-
BridgeConnector.Off("autoUpdater-currentVersion-get-reply");
200-
taskCompletionSource.SetResult(version);
201-
});
202-
BridgeConnector.Emit("autoUpdater-currentVersion-get");
203-
204-
return taskCompletionSource.Task;
205-
}
116+
public Task<SemVer> GetCurrentVersionAsync() => BridgeConnector.OnResult<SemVer>("autoUpdater-updateConcurrentVersionfigPath-get", "autoUpdater-currentVersion-get-reply");
206117

207118
/// <summary>
208119
/// Get the update channel. Not applicable for GitHub.
209120
/// Doesn’t return channel from the update configuration, only if was previously set.
210121
/// </summary>
211-
public Task<string> GetChannelAsync()
212-
{
213-
var taskCompletionSource = new TaskCompletionSource<string>(TaskCreationOptions.RunContinuationsAsynchronously);
214-
215-
BridgeConnector.On<string>("autoUpdater-channel-get-reply", (result) =>
216-
{
217-
BridgeConnector.Off("autoUpdater-channel-get-reply");
218-
taskCompletionSource.SetResult(result.ToString());
219-
});
220-
BridgeConnector.Emit("autoUpdater-channel-get");
221-
222-
return taskCompletionSource.Task;
223-
}
224-
225-
122+
public Task<string> GetChannelAsync() => BridgeConnector.OnResult<string>("autoUpdater-channel-get", "autoUpdater-channel-get-reply");
226123

227124
/// <summary>
228125
/// The request headers.
229126
/// </summary>
230-
public Task<Dictionary<string, string>> GetRequestHeadersAsync()
231-
{
232-
var taskCompletionSource = new TaskCompletionSource<Dictionary<string, string>>(TaskCreationOptions.RunContinuationsAsynchronously);
233-
BridgeConnector.On<Dictionary<string, string>>("autoUpdater-requestHeaders-get-reply", (headers) =>
234-
{
235-
BridgeConnector.Off("autoUpdater-requestHeaders-get-reply");
236-
taskCompletionSource.SetResult(headers);
237-
});
238-
BridgeConnector.Emit("autoUpdater-requestHeaders-get");
239-
return taskCompletionSource.Task;
240-
}
127+
public Task<Dictionary<string, string>> GetRequestHeadersAsync() => BridgeConnector.OnResult<Dictionary<string, string>>("autoUpdater-requestHeaders-get", "autoUpdater-requestHeaders-get-reply");
241128

242129
/// <summary>
243130
/// The request headers.
@@ -246,7 +133,7 @@ public Dictionary<string, string> RequestHeaders
246133
{
247134
set
248135
{
249-
BridgeConnector.Emit("autoUpdater-requestHeaders-set", JObject.FromObject(value, _jsonSerializer));
136+
BridgeConnector.Emit("autoUpdater-requestHeaders-set", value);
250137
}
251138
}
252139

@@ -581,10 +468,5 @@ public Task<string> GetFeedURLAsync()
581468

582469
return taskCompletionSource.Task;
583470
}
584-
585-
private readonly JsonSerializer _jsonSerializer = new JsonSerializer()
586-
{
587-
ContractResolver = new CamelCasePropertyNamesContractResolver()
588-
};
589471
}
590472
}

ElectronNET.API/BridgeConnector.cs

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
using System;
22
using System.Collections.Concurrent;
33
using System.Collections.Generic;
4+
using System.Linq;
45
using System.Threading;
56
using System.Threading.Tasks;
7+
using Newtonsoft.Json;
8+
using Newtonsoft.Json.Serialization;
69
using SocketIOClient;
10+
using SocketIOClient.JsonSerializer;
711
using SocketIOClient.Newtonsoft.Json;
812

913
namespace ElectronNET.API
@@ -149,7 +153,7 @@ public static void Once<T>(string eventString, Action<T> fn)
149153

150154
public static async Task<T> OnResult<T>(string triggerEvent, string completedEvent, params object[] args)
151155
{
152-
string eventKey = triggerEvent;
156+
string eventKey = completedEvent;
153157

154158
if (args is object && args.Length > 0) // If there are arguments passed, we generate a unique event key with the arguments
155159
// this allow us to wait for previous events first before registering new ones
@@ -162,7 +166,7 @@ public static async Task<T> OnResult<T>(string triggerEvent, string completedEve
162166
eventKey = $"{eventKey}-{(uint)hash.ToHashCode()}";
163167
}
164168

165-
if (EventTasks<T>.TryGetOrAdd(triggerEvent, eventKey, out var taskCompletionSource, out var waitThisFirstAndThenTryAgain))
169+
if (EventTasks<T>.TryGetOrAdd(completedEvent, eventKey, out var taskCompletionSource, out var waitThisFirstAndThenTryAgain))
166170
{
167171
if (waitThisFirstAndThenTryAgain is object)
168172
{
@@ -188,7 +192,7 @@ public static async Task<T> OnResult<T>(string triggerEvent, string completedEve
188192
{
189193
Off(completedEvent);
190194
taskCompletionSource.SetResult(result);
191-
EventTasks<T>.DoneWith(triggerEvent, eventKey, taskCompletionSource);
195+
EventTasks<T>.DoneWith(completedEvent, eventKey, taskCompletionSource);
192196
});
193197

194198
Emit(triggerEvent, args);
@@ -201,21 +205,56 @@ public static async Task<T> OnResult<T>(string triggerEvent, string completedEve
201205

202206
public static async Task<T> OnResult<T>(string triggerEvent, string completedEvent, CancellationToken cancellationToken, params object[] args)
203207
{
204-
var taskCompletionSource = new TaskCompletionSource<T>(TaskCreationOptions.RunContinuationsAsynchronously);
208+
string eventKey = completedEvent;
205209

206-
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
210+
if (args is object && args.Length > 0) // If there are arguments passed, we generate a unique event key with the arguments
211+
// this allow us to wait for previous events first before registering new ones
207212
{
213+
var hash = new HashCode();
214+
foreach (var obj in args)
215+
{
216+
hash.Add(obj);
217+
}
218+
eventKey = $"{eventKey}-{(uint)hash.ToHashCode()}";
219+
}
208220

209-
On<T>(completedEvent, (result) =>
221+
if (EventTasks<T>.TryGetOrAdd(completedEvent, eventKey, out var taskCompletionSource, out var waitThisFirstAndThenTryAgain))
222+
{
223+
if (waitThisFirstAndThenTryAgain is object)
210224
{
211-
Off(completedEvent);
212-
taskCompletionSource.SetResult(result);
213-
});
225+
//There was a pending call with different parameters, so we need to wait that first and then call here again
226+
try
227+
{
228+
await Task.Run(() => waitThisFirstAndThenTryAgain, cancellationToken);
229+
}
230+
catch
231+
{
232+
//Ignore any exceptions here so we can set a new event below
233+
//The exception will also be visible to the original first caller due to taskCompletionSource.Task
234+
}
214235

215-
Emit(triggerEvent, args);
236+
//Try again to set the event
237+
return await OnResult<T>(triggerEvent, completedEvent, cancellationToken, args);
238+
}
239+
else
240+
{
241+
using (cancellationToken.Register(() => taskCompletionSource.TrySetCanceled()))
242+
{
243+
//A new TaskCompletionSource was added, so we need to register the completed event here
244+
245+
On<T>(completedEvent, (result) =>
246+
{
247+
Off(completedEvent);
248+
taskCompletionSource.SetResult(result);
249+
EventTasks<T>.DoneWith(completedEvent, eventKey, taskCompletionSource);
250+
});
216251

217-
return await taskCompletionSource.Task.ConfigureAwait(false);
252+
Emit(triggerEvent, args);
253+
}
254+
}
218255
}
256+
257+
return await taskCompletionSource.Task;
219258
}
220259
private static SocketIO Socket
221260
{
@@ -235,7 +274,7 @@ private static SocketIO Socket
235274
EIO = 3
236275
});
237276

238-
socket.JsonSerializer = new NewtonsoftJsonSerializer(socket.Options.EIO);
277+
socket.JsonSerializer = new CamelCaseNewtonsoftJsonSerializer(socket.Options.EIO);
239278

240279

241280
socket.OnConnected += (_, __) =>
@@ -258,5 +297,22 @@ private static SocketIO Socket
258297
return _socket;
259298
}
260299
}
300+
301+
private class CamelCaseNewtonsoftJsonSerializer : NewtonsoftJsonSerializer
302+
{
303+
public CamelCaseNewtonsoftJsonSerializer(int eio) : base(eio)
304+
{
305+
}
306+
307+
public override JsonSerializerSettings CreateOptions()
308+
{
309+
return new JsonSerializerSettings()
310+
{
311+
ContractResolver = new CamelCasePropertyNamesContractResolver(),
312+
NullValueHandling = NullValueHandling.Ignore,
313+
DefaultValueHandling = DefaultValueHandling.Ignore
314+
};
315+
}
316+
}
261317
}
262318
}

ElectronNET.API/BrowserView.cs

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,24 +31,11 @@ public class BrowserView
3131
///
3232
/// (experimental)
3333
/// </summary>
34-
public Task<Rectangle> GetBoundsAsync()
35-
{
36-
var taskCompletionSource = new TaskCompletionSource<Rectangle>(TaskCreationOptions.RunContinuationsAsynchronously);
37-
38-
BridgeConnector.On<Rectangle>("browserView-getBounds-reply", (result) =>
39-
{
40-
BridgeConnector.Off("browserView-getBounds-reply");
41-
taskCompletionSource.SetResult(result);
42-
});
43-
44-
BridgeConnector.Emit("browserView-getBounds", Id);
45-
46-
return taskCompletionSource.Task;
47-
}
34+
public Task<Rectangle> GetBoundsAsync() => BridgeConnector.OnResult<Rectangle>("browserView-getBounds", "browserView-getBounds-reply" + Id, Id);
4835

4936
public void SetBounds(Rectangle value)
5037
{
51-
BridgeConnector.Emit("browserView-setBounds", Id, JObject.FromObject(value, _jsonSerializer));
38+
BridgeConnector.Emit("browserView-setBounds", Id, value);
5239
}
5340

5441
/// <summary>
@@ -69,7 +56,7 @@ internal BrowserView(int id)
6956
/// <param name="options"></param>
7057
public void SetAutoResize(AutoResizeOptions options)
7158
{
72-
BridgeConnector.Emit("browserView-setAutoResize", Id, JObject.FromObject(options, _jsonSerializer));
59+
BridgeConnector.Emit("browserView-setAutoResize", Id, options);
7360
}
7461

7562
/// <summary>
@@ -82,11 +69,5 @@ public void SetBackgroundColor(string color)
8269
{
8370
BridgeConnector.Emit("browserView-setBackgroundColor", Id, color);
8471
}
85-
86-
private JsonSerializer _jsonSerializer = new JsonSerializer()
87-
{
88-
ContractResolver = new CamelCasePropertyNamesContractResolver(),
89-
NullValueHandling = NullValueHandling.Ignore
90-
};
9172
}
9273
}

0 commit comments

Comments
 (0)