Skip to content

Commit 4e9de2a

Browse files
FreFre
authored andcommitted
Aanpassingen autoupdate & async code
1 parent f1ceaa2 commit 4e9de2a

File tree

12 files changed

+404
-29
lines changed

12 files changed

+404
-29
lines changed

ElectronNET.API/App.cs

Lines changed: 72 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,27 @@ internal set
407407
/// which will be preferred over name by Electron.
408408
/// </summary>
409409
public string Name
410+
{
411+
[Obsolete("Use the asynchronous version NameAsync instead")]
412+
get
413+
{
414+
return AsyncHelper.RunSync(async () => await NameAsync);
415+
}
416+
set
417+
{
418+
BridgeConnector.Socket.Emit("appSetName", value);
419+
}
420+
}
421+
422+
/// <summary>
423+
/// A <see cref="string"/> property that indicates the current application's name, which is the name in the
424+
/// application's package.json file.
425+
///
426+
/// Usually the name field of package.json is a short lowercase name, according to the npm modules spec. You
427+
/// should usually also specify a productName field, which is your application's full capitalized name, and
428+
/// which will be preferred over name by Electron.
429+
/// </summary>
430+
public Task<string> NameAsync
410431
{
411432
get
412433
{
@@ -423,14 +444,34 @@ public string Name
423444
BridgeConnector.Socket.Emit("appGetName");
424445

425446
return taskCompletionSource.Task;
426-
}).Result;
427-
}
428-
set
429-
{
430-
BridgeConnector.Socket.Emit("appSetName", value);
447+
});
431448
}
432449
}
433450

451+
/// <summary>
452+
///
453+
/// </summary>
454+
/// <returns></returns>
455+
public Task<string> GetName()
456+
457+
{
458+
459+
var taskCompletionSource = new TaskCompletionSource<string>();
460+
461+
BridgeConnector.Socket.On("appGetNameCompleted", (result) =>
462+
{
463+
BridgeConnector.Socket.Off("appGetNameCompleted");
464+
taskCompletionSource.SetResult((string)result);
465+
});
466+
467+
BridgeConnector.Socket.Emit("appGetName");
468+
469+
return taskCompletionSource.Task;
470+
471+
}
472+
473+
474+
434475
internal App()
435476
{
436477
CommandLine = new CommandLine();
@@ -1479,6 +1520,27 @@ public void SetAboutPanelOptions(AboutPanelOptions options)
14791520
/// is used.
14801521
/// </summary>
14811522
public string UserAgentFallback
1523+
{
1524+
[Obsolete("Use the asynchronous version UserAgentFallbackAsync instead")]
1525+
get
1526+
{
1527+
return AsyncHelper.RunSync(async () => await UserAgentFallbackAsync);
1528+
}
1529+
set
1530+
{
1531+
BridgeConnector.Socket.Emit("appSetUserAgentFallback", value);
1532+
}
1533+
}
1534+
1535+
/// <summary>
1536+
/// A <see cref="string"/> which is the user agent string Electron will use as a global fallback.
1537+
/// <para/>
1538+
/// This is the user agent that will be used when no user agent is set at the webContents or
1539+
/// session level. It is useful for ensuring that your entire app has the same user agent. Set to a
1540+
/// custom value as early as possible in your app's initialization to ensure that your overridden value
1541+
/// is used.
1542+
/// </summary>
1543+
public Task<string> UserAgentFallbackAsync
14821544
{
14831545
get
14841546
{
@@ -1487,19 +1549,15 @@ public string UserAgentFallback
14871549
var taskCompletionSource = new TaskCompletionSource<string>();
14881550

14891551
BridgeConnector.Socket.On("appGetUserAgentFallbackCompleted", (result) =>
1490-
{
1491-
BridgeConnector.Socket.Off("appGetUserAgentFallbackCompleted");
1492-
taskCompletionSource.SetResult((string)result);
1493-
});
1552+
{
1553+
BridgeConnector.Socket.Off("appGetUserAgentFallbackCompleted");
1554+
taskCompletionSource.SetResult((string)result);
1555+
});
14941556

14951557
BridgeConnector.Socket.Emit("appGetUserAgentFallback");
14961558

14971559
return taskCompletionSource.Task;
1498-
}).Result;
1499-
}
1500-
set
1501-
{
1502-
BridgeConnector.Socket.Emit("appSetUserAgentFallback", value);
1560+
});
15031561
}
15041562
}
15051563

ElectronNET.API/AsyncHelper.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using System;
2+
using System.Threading;
3+
using System.Threading.Tasks;
4+
5+
namespace ElectronNET.API
6+
{
7+
internal static class AsyncHelper
8+
{
9+
private static readonly TaskFactory _taskFactory = new
10+
TaskFactory(CancellationToken.None,
11+
TaskCreationOptions.None,
12+
TaskContinuationOptions.None,
13+
TaskScheduler.Default);
14+
15+
public static TResult RunSync<TResult>(Func<Task<TResult>> func)
16+
=> _taskFactory
17+
.StartNew(func)
18+
.Unwrap()
19+
.GetAwaiter()
20+
.GetResult();
21+
22+
public static void RunSync(Func<Task> func)
23+
=> _taskFactory
24+
.StartNew(func)
25+
.Unwrap()
26+
.GetAwaiter()
27+
.GetResult();
28+
29+
public static async Task<TResult> TimeoutAfter<TResult>(this Task<TResult> task, TimeSpan timeout)
30+
{
31+
using (var timeoutCancellationTokenSource = new CancellationTokenSource())
32+
{
33+
var completedTask = await Task.WhenAny(task, Task.Delay(timeout, timeoutCancellationTokenSource.Token));
34+
if (completedTask == task)
35+
{
36+
timeoutCancellationTokenSource.Cancel();
37+
return await task; // Very important in order to propagate exceptions
38+
}
39+
else
40+
{
41+
throw new TimeoutException($"{nameof(TimeoutAfter)}: The operation has timed out after {timeout:mm\\:ss}");
42+
}
43+
}
44+
}
45+
}
46+
}

ElectronNET.API/AutoUpdater.cs

Lines changed: 125 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
using ElectronNET.API.Entities;
2+
using Newtonsoft.Json;
23
using Newtonsoft.Json.Linq;
4+
using Newtonsoft.Json.Serialization;
35
using System;
6+
using System.Collections.Generic;
7+
using System.Runtime.CompilerServices;
8+
using System.Security.Cryptography.X509Certificates;
9+
using System.Threading;
410
using System.Threading.Tasks;
511

612
namespace ElectronNET.API
@@ -182,11 +188,48 @@ public string UpdateConfigPath
182188
}
183189
}
184190

191+
/// <summary>
192+
/// The current application version
193+
/// </summary>
194+
public Task<SemVer> CurrentVersionAsync
195+
{
196+
get
197+
{
198+
return Task.Run<SemVer>(() =>
199+
{
200+
var taskCompletionSource = new TaskCompletionSource<SemVer>();
201+
202+
BridgeConnector.Socket.On("autoUpdater-currentVersion-get-reply", (result) =>
203+
{
204+
BridgeConnector.Socket.Off("autoUpdater-currentVersion-get-reply");
205+
SemVer version = ((JObject)result).ToObject<SemVer>();
206+
taskCompletionSource.SetResult(version);
207+
});
208+
BridgeConnector.Socket.Emit("autoUpdater-currentVersion-get");
209+
210+
return taskCompletionSource.Task;
211+
});
212+
}
213+
}
214+
185215
/// <summary>
186216
/// Get the update channel. Not applicable for GitHub.
187217
/// Doesn’t return channel from the update configuration, only if was previously set.
188218
/// </summary>
219+
[Obsolete("Use the asynchronous version ChannelAsync instead")]
189220
public string Channel
221+
{
222+
get
223+
{
224+
return AsyncHelper.RunSync(async () => await ChannelAsync);
225+
}
226+
}
227+
228+
/// <summary>
229+
/// Get the update channel. Not applicable for GitHub.
230+
/// Doesn’t return channel from the update configuration, only if was previously set.
231+
/// </summary>
232+
public Task<string> ChannelAsync
190233
{
191234
get
192235
{
@@ -199,18 +242,52 @@ public string Channel
199242
BridgeConnector.Socket.Off("autoUpdater-channel-get-reply");
200243
taskCompletionSource.SetResult(result.ToString());
201244
});
202-
203245
BridgeConnector.Socket.Emit("autoUpdater-channel-get");
204246

205247
return taskCompletionSource.Task;
206-
}).Result;
248+
});
249+
}
250+
}
251+
252+
253+
254+
/// <summary>
255+
/// The request headers.
256+
/// </summary>
257+
public Task<Dictionary<string, string>> RequestHeadersAsync
258+
{
259+
get
260+
{
261+
return Task.Run(() =>
262+
{
263+
var taskCompletionSource = new TaskCompletionSource<Dictionary<string, string>>();
264+
BridgeConnector.Socket.On("autoUpdater-requestHeaders-get-reply", (headers) =>
265+
{
266+
BridgeConnector.Socket.Off("autoUpdater-requestHeaders-get-reply");
267+
Dictionary<string, string> result = ((JObject)headers).ToObject<Dictionary<string, string>>();
268+
taskCompletionSource.SetResult(result);
269+
});
270+
BridgeConnector.Socket.Emit("autoUpdater-requestHeaders-get");
271+
return taskCompletionSource.Task;
272+
});
207273
}
208274
}
209275

210276
/// <summary>
211-
/// Emitted when there is an error while updating.
277+
/// The request headers.
212278
/// </summary>
213-
public event Action<string> OnError
279+
public Dictionary<string, string> RequestHeaders
280+
{
281+
set
282+
{
283+
BridgeConnector.Socket.Emit("autoUpdater-requestHeaders-set", JObject.FromObject(value, _jsonSerializer));
284+
}
285+
}
286+
287+
/// <summary>
288+
/// Emitted when there is an error while updating.
289+
/// </summary>
290+
public event Action<string> OnError
214291
{
215292
add
216293
{
@@ -416,9 +493,26 @@ public Task<UpdateCheckResult> CheckForUpdatesAsync()
416493
string guid = Guid.NewGuid().ToString();
417494

418495
BridgeConnector.Socket.On("autoUpdaterCheckForUpdatesComplete" + guid, (updateCheckResult) =>
496+
{
497+
try
498+
{
499+
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesComplete" + guid);
500+
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesError" + guid);
501+
taskCompletionSource.SetResult(JObject.Parse(updateCheckResult.ToString()).ToObject<UpdateCheckResult>());
502+
}
503+
catch (Exception ex)
504+
{
505+
taskCompletionSource.SetException(ex);
506+
}
507+
});
508+
BridgeConnector.Socket.On("autoUpdaterCheckForUpdatesError" + guid, (error) =>
419509
{
420510
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesComplete" + guid);
421-
taskCompletionSource.SetResult(JObject.Parse(updateCheckResult.ToString()).ToObject<UpdateCheckResult>());
511+
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesError" + guid);
512+
string message = "An error occurred in CheckForUpdatesAsync";
513+
if (error != null && !string.IsNullOrEmpty(error.ToString()))
514+
message = JsonConvert.SerializeObject(error);
515+
taskCompletionSource.SetException(new ElectronException(message));
422516
});
423517

424518
BridgeConnector.Socket.Emit("autoUpdaterCheckForUpdates", guid);
@@ -438,9 +532,29 @@ public Task<UpdateCheckResult> CheckForUpdatesAndNotifyAsync()
438532
string guid = Guid.NewGuid().ToString();
439533

440534
BridgeConnector.Socket.On("autoUpdaterCheckForUpdatesAndNotifyComplete" + guid, (updateCheckResult) =>
535+
{
536+
try
537+
{
538+
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesAndNotifyComplete" + guid);
539+
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesAndNotifyError" + guid);
540+
if (updateCheckResult == null)
541+
taskCompletionSource.SetResult(null);
542+
else
543+
taskCompletionSource.SetResult(JObject.Parse(updateCheckResult.ToString()).ToObject<UpdateCheckResult>());
544+
}
545+
catch (Exception ex)
546+
{
547+
taskCompletionSource.SetException(ex);
548+
}
549+
});
550+
BridgeConnector.Socket.On("autoUpdaterCheckForUpdatesAndNotifyError" + guid, (error) =>
441551
{
442552
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesAndNotifyComplete" + guid);
443-
taskCompletionSource.SetResult(JObject.Parse(updateCheckResult.ToString()).ToObject<UpdateCheckResult>());
553+
BridgeConnector.Socket.Off("autoUpdaterCheckForUpdatesAndNotifyError" + guid);
554+
string message = "An error occurred in autoUpdaterCheckForUpdatesAndNotify";
555+
if (error != null)
556+
message = JsonConvert.SerializeObject(error);
557+
taskCompletionSource.SetException(new ElectronException(message));
444558
});
445559

446560
BridgeConnector.Socket.Emit("autoUpdaterCheckForUpdatesAndNotify", guid);
@@ -501,5 +615,10 @@ public Task<string> GetFeedURLAsync()
501615

502616
return taskCompletionSource.Task;
503617
}
618+
619+
private readonly JsonSerializer _jsonSerializer = new JsonSerializer()
620+
{
621+
ContractResolver = new CamelCasePropertyNamesContractResolver()
622+
};
504623
}
505624
}

ElectronNET.API/BridgeConnector.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ public static Socket Socket
2323
{
2424
Console.WriteLine("BridgeConnector connected!");
2525
});
26+
_socket.On(Socket.EVENT_CONNECT_ERROR, (args) =>
27+
{
28+
Console.WriteLine("Socket error! {0}", args??"no args");
29+
});
30+
_socket.On(Socket.EVENT_DISCONNECT, (args) =>
31+
{
32+
Console.WriteLine("Socket Disconnect! {0}", args ?? "no args");
33+
});
2634
}
2735
}
2836
}

ElectronNET.API/ElectronNET.API.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ This package contains the API to access the "native" electron API.</Description>
4040
<PrivateAssets>all</PrivateAssets>
4141
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
4242
</PackageReference>
43+
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
4344
<PackageReference Include="SocketIoClientDotNet" Version="1.0.5" />
4445
<PackageReference Include="System.Drawing.Common" Version="4.7.0" />
4546
</ItemGroup>

0 commit comments

Comments
 (0)