using ElectronNET.API.Entities;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
// ReSharper disable InconsistentNaming
namespace ElectronNET.API
{
///
/// Enable apps to automatically update themselves. Based on electron-updater.
///
public sealed class AutoUpdater : ApiBase
{
protected override SocketTaskEventNameTypes SocketTaskEventNameType => SocketTaskEventNameTypes.DashesLowerFirst;
protected override SocketTaskMessageNameTypes SocketTaskMessageNameType => SocketTaskMessageNameTypes.DashesLowerFirst;
protected override SocketEventNameTypes SocketEventNameType => SocketEventNameTypes.DashedLower;
///
/// Whether to automatically download an update when it is found. (Default is true)
///
public bool AutoDownload
{
get
{
return Task.Run(() => this.InvokeAsync()).Result;
}
set
{
BridgeConnector.Socket.Emit("autoUpdater-autoDownload-set", value);
}
}
///
/// Whether to automatically install a downloaded update on app quit (if `QuitAndInstall` was not called before).
///
/// Applicable only on Windows and Linux.
///
public bool AutoInstallOnAppQuit
{
get
{
return Task.Run(() => this.InvokeAsync()).Result;
}
set
{
BridgeConnector.Socket.Emit("autoUpdater-autoInstallOnAppQuit-set", value);
}
}
///
/// *GitHub provider only.* Whether to allow update to pre-release versions.
/// Defaults to "true" if application version contains prerelease components (e.g. "0.12.1-alpha.1", here "alpha" is a prerelease component), otherwise "false".
///
/// If "true", downgrade will be allowed("allowDowngrade" will be set to "true").
///
public bool AllowPrerelease
{
get
{
return Task.Run(() => this.InvokeAsync()).Result;
}
set
{
BridgeConnector.Socket.Emit("autoUpdater-allowPrerelease-set", value);
}
}
///
/// *GitHub provider only.*
/// Get all release notes (from current version to latest), not just the latest (Default is false).
///
public bool FullChangelog
{
get
{
return Task.Run(() => this.InvokeAsync()).Result;
}
set
{
BridgeConnector.Socket.Emit("autoUpdater-fullChangelog-set", value);
}
}
///
/// Whether to allow version downgrade (when a user from the beta channel wants to go back to the stable channel).
/// Taken in account only if channel differs (pre-release version component in terms of semantic versioning).
/// Default is false.
///
public bool AllowDowngrade
{
get
{
return Task.Run(() => this.InvokeAsync()).Result;
}
set
{
BridgeConnector.Socket.Emit("autoUpdater-allowDowngrade-set", value);
}
}
///
/// For test only.
///
public string UpdateConfigPath
{
get
{
return Task.Run(() => this.InvokeAsync()).Result;
}
}
///
/// The current application version
///
public Task CurrentVersionAsync
{
get
{
return Task.Run(() => this.InvokeAsync());
}
}
///
/// Get the update channel. Not applicable for GitHub.
/// Doesn’t return channel from the update configuration, only if was previously set.
///
[Obsolete("Use the asynchronous version ChannelAsync instead")]
public string Channel
{
get
{
return ChannelAsync.Result;
}
}
///
/// Get the update channel. Not applicable for GitHub.
/// Doesn’t return channel from the update configuration, only if was previously set.
///
public Task ChannelAsync
{
get
{
return Task.Run(() => this.InvokeAsync());
}
}
///
/// Set the update channel. Not applicable for GitHub.
///
public string SetChannel
{
set
{
BridgeConnector.Socket.Emit("autoUpdater-channel-set", value);
}
}
///
/// The request headers.
///
public Task> RequestHeadersAsync
{
get
{
return Task.Run(() => this.InvokeAsync>());
}
}
///
/// The request headers.
///
public Dictionary RequestHeaders
{
set
{
BridgeConnector.Socket.Emit("autoUpdater-requestHeaders-set", value);
}
}
///
/// Emitted when there is an error while updating.
///
public event Action OnError
{
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
///
/// Emitted when checking if an update has started.
///
public event Action OnCheckingForUpdate
{
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
///
/// Emitted when there is an available update.
/// The update is downloaded automatically if AutoDownload is true.
///
public event Action OnUpdateAvailable
{
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
///
/// Emitted when there is no available update.
///
public event Action OnUpdateNotAvailable
{
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
///
/// Emitted on download progress.
///
public event Action OnDownloadProgress
{
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
///
/// Emitted on download complete.
///
public event Action OnUpdateDownloaded
{
add => AddEvent(value, GetHashCode());
remove => RemoveEvent(value, GetHashCode());
}
private static AutoUpdater _autoUpdater;
private static object _syncRoot = new object();
internal AutoUpdater()
{
}
internal static AutoUpdater Instance
{
get
{
if (_autoUpdater == null)
{
lock (_syncRoot)
{
if (_autoUpdater == null)
{
_autoUpdater = new AutoUpdater();
}
}
}
return _autoUpdater;
}
}
///
/// Asks the server whether there is an update.
///
///
public Task CheckForUpdatesAsync()
{
var taskCompletionSource = new TaskCompletionSource();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.Once("autoUpdater-checkForUpdates-completed" + guid, (result) =>
{
try
{
BridgeConnector.Socket.Off("autoUpdater-checkForUpdatesError" + guid);
taskCompletionSource.SetResult(result);
}
catch (Exception ex)
{
taskCompletionSource.SetException(ex);
}
});
BridgeConnector.Socket.Once("autoUpdater-checkForUpdatesError" + guid, (result) =>
{
BridgeConnector.Socket.Off("autoUpdater-checkForUpdates-completed" + guid);
string message = "An error occurred in CheckForUpdatesAsync";
if (!string.IsNullOrEmpty(result)) message = result;
taskCompletionSource.SetException(new Exception(message));
});
BridgeConnector.Socket.Emit("autoUpdater-checkForUpdates", guid);
return taskCompletionSource.Task;
}
///
/// Asks the server whether there is an update.
///
/// This will immediately download an update, then install when the app quits.
///
///
public Task CheckForUpdatesAndNotifyAsync()
{
var taskCompletionSource = new TaskCompletionSource();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.Once("autoUpdater-checkForUpdatesAndNotify-completed" + guid, (result) =>
{
try
{
BridgeConnector.Socket.Off("autoUpdater-checkForUpdatesAndNotifyError" + guid);
taskCompletionSource.SetResult(result);
}
catch (Exception ex)
{
taskCompletionSource.SetException(ex);
}
});
BridgeConnector.Socket.Once("autoUpdater-checkForUpdatesAndNotifyError" + guid, (result) =>
{
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("autoUpdater-checkForUpdatesAndNotify", guid);
return taskCompletionSource.Task;
}
///
/// Restarts the app and installs the update after it has been downloaded.
/// It should only be called after `update-downloaded` has been emitted.
///
/// Note: QuitAndInstall() will close all application windows first and only emit `before-quit` event on `app` after that.
/// This is different from the normal quit event sequence.
///
/// *windows-only* Runs the installer in silent mode. Defaults to `false`.
/// Run the app after finish even on silent install. Not applicable for macOS. Ignored if `isSilent` is set to `false`.
public void QuitAndInstall(bool isSilent = false, bool isForceRunAfter = false)
{
BridgeConnector.Socket.Emit("autoUpdater-quitAndInstall", isSilent, isForceRunAfter);
}
///
/// Start downloading update manually. You can use this method if "AutoDownload" option is set to "false".
///
/// Path to downloaded file.
public Task DownloadUpdateAsync()
{
var tcs = new TaskCompletionSource();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.Once("autoUpdater-downloadUpdate-completed" + guid, tcs.SetResult);
BridgeConnector.Socket.Emit("autoUpdater-downloadUpdate", guid);
return tcs.Task;
}
///
/// Feed URL.
///
/// Feed URL.
public Task GetFeedURLAsync()
{
var tcs = new TaskCompletionSource();
string guid = Guid.NewGuid().ToString();
BridgeConnector.Socket.Once("autoUpdater-getFeedURL-completed" + guid, tcs.SetResult);
BridgeConnector.Socket.Emit("autoUpdater-getFeedURL", guid);
return tcs.Task;
}
}
}