1
0
mirror of https://github.com/chylex/TweetDuck.git synced 2025-05-02 02:34:08 +02:00

Rewrite update system to predownload update installers

This commit is contained in:
chylex 2017-05-17 18:21:06 +02:00
parent 9e44a86be0
commit 0e8c6c066f
14 changed files with 200 additions and 160 deletions

View File

@ -12,6 +12,7 @@ static class Arguments{
// internal args // internal args
public const string ArgRestart = "-restart"; public const string ArgRestart = "-restart";
public const string ArgImportCookies = "-importcookies"; public const string ArgImportCookies = "-importcookies";
public const string ArgUpdated = "-updated";
// class data and methods // class data and methods
private static readonly CommandLineArgs Current = CommandLineArgs.FromStringArray('-', Environment.GetCommandLineArgs()); private static readonly CommandLineArgs Current = CommandLineArgs.FromStringArray('-', Environment.GetCommandLineArgs());
@ -28,7 +29,18 @@ public static CommandLineArgs GetCurrentClean(){
CommandLineArgs args = Current.Clone(); CommandLineArgs args = Current.Clone();
args.RemoveFlag(ArgRestart); args.RemoveFlag(ArgRestart);
args.RemoveFlag(ArgImportCookies); args.RemoveFlag(ArgImportCookies);
args.RemoveFlag(ArgUpdated);
return args; return args;
} }
public static CommandLineArgs GetCurrentForInstaller(){
CommandLineArgs args = GetCurrentClean();
args.AddFlag(ArgUpdated);
return args;
}
public static string GetCurrentForInstallerCmd(){
return GetCurrentForInstaller().ToString().Replace("\"", "^\"");
}
} }
} }

View File

@ -41,6 +41,7 @@ private void InitializeComponent() {
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.Activated += new System.EventHandler(this.FormBrowser_Activated); this.Activated += new System.EventHandler(this.FormBrowser_Activated);
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormBrowser_FormClosing); this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormBrowser_FormClosing);
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FormBrowser_FormClosed);
this.ResizeEnd += new System.EventHandler(this.FormBrowser_ResizeEnd); this.ResizeEnd += new System.EventHandler(this.FormBrowser_ResizeEnd);
this.Resize += new System.EventHandler(this.FormBrowser_Resize); this.Resize += new System.EventHandler(this.FormBrowser_Resize);
this.ResumeLayout(false); this.ResumeLayout(false);

View File

@ -247,6 +247,12 @@ private void FormBrowser_FormClosing(object sender, FormClosingEventArgs e){
} }
} }
private void FormBrowser_FormClosed(object sender, FormClosedEventArgs e){
if (isLoaded && UpdateInstallerPath == null){
updates.CleanupDownload();
}
}
private void Config_MuteToggled(object sender, EventArgs e){ private void Config_MuteToggled(object sender, EventArgs e){
UpdateProperties(PropertyBridge.Properties.MuteNotifications); UpdateProperties(PropertyBridge.Properties.MuteNotifications);
} }
@ -284,24 +290,14 @@ private void updates_UpdateAccepted(object sender, UpdateAcceptedEventArgs e){
form.Close(); form.Close();
} }
} }
updates.BeginUpdateDownload(this, e.UpdateInfo, update => {
if (update.DownloadStatus == UpdateDownloadStatus.Done){
UpdateInstallerPath = update.InstallerPath;
}
Hide();
FormUpdateDownload downloadForm = new FormUpdateDownload(e.UpdateInfo);
downloadForm.MoveToCenter(this);
downloadForm.ShowDialog();
downloadForm.Dispose();
if (downloadForm.UpdateStatus == FormUpdateDownload.Status.Succeeded){
UpdateInstallerPath = downloadForm.InstallerPath;
ForceClose(); ForceClose();
} });
else if (downloadForm.UpdateStatus == FormUpdateDownload.Status.Manual){
ForceClose();
}
else{
Show();
}
} }
private void updates_UpdateDismissed(object sender, UpdateDismissedEventArgs e){ private void updates_UpdateDismissed(object sender, UpdateDismissedEventArgs e){

View File

@ -34,6 +34,7 @@ static class Program{
public static readonly string PluginConfigFilePath = Path.Combine(StoragePath, "TD_PluginConfig.cfg"); public static readonly string PluginConfigFilePath = Path.Combine(StoragePath, "TD_PluginConfig.cfg");
private static readonly string ErrorLogFilePath = Path.Combine(StoragePath, "TD_Log.txt"); private static readonly string ErrorLogFilePath = Path.Combine(StoragePath, "TD_Log.txt");
private static readonly string ConsoleLogFilePath = Path.Combine(StoragePath, "TD_Console.txt"); private static readonly string ConsoleLogFilePath = Path.Combine(StoragePath, "TD_Console.txt");
private static readonly string InstallerPath = Path.Combine(StoragePath, "TD_Updates");
public static readonly string ScriptPath = Path.Combine(ProgramPath, "scripts"); public static readonly string ScriptPath = Path.Combine(ProgramPath, "scripts");
public static readonly string PluginPath = Path.Combine(ProgramPath, "plugins"); public static readonly string PluginPath = Path.Combine(ProgramPath, "plugins");
@ -126,6 +127,10 @@ private static void Main(){
if (Arguments.HasFlag(Arguments.ArgImportCookies)){ if (Arguments.HasFlag(Arguments.ArgImportCookies)){
ExportManager.ImportCookies(); ExportManager.ImportCookies();
} }
if (Arguments.HasFlag(Arguments.ArgUpdated)){
WindowsUtils.TryDeleteFolderWhenAble(InstallerPath, 8000);
}
CefSharpSettings.WcfEnabled = false; CefSharpSettings.WcfEnabled = false;
@ -163,7 +168,8 @@ private static void Main(){
FormBrowser mainForm = new FormBrowser(plugins, new UpdaterSettings{ FormBrowser mainForm = new FormBrowser(plugins, new UpdaterSettings{
AllowPreReleases = Arguments.HasFlag(Arguments.ArgDebugUpdates), AllowPreReleases = Arguments.HasFlag(Arguments.ArgDebugUpdates),
DismissedUpdate = UserConfig.DismissedUpdate DismissedUpdate = UserConfig.DismissedUpdate,
InstallerDownloadFolder = InstallerPath
}); });
Application.Run(mainForm); Application.Run(mainForm);
@ -172,7 +178,7 @@ private static void Main(){
ExitCleanup(); ExitCleanup();
// ProgramPath has a trailing backslash // ProgramPath has a trailing backslash
string updaterArgs = "/SP- /SILENT /CLOSEAPPLICATIONS /UPDATEPATH=\""+ProgramPath+"\" /RUNARGS=\""+Arguments.GetCurrentClean().ToString().Replace("\"", "^\"")+"\""+(IsPortable ? " /PORTABLE=1" : ""); string updaterArgs = "/SP- /SILENT /CLOSEAPPLICATIONS /UPDATEPATH=\""+ProgramPath+"\" /RUNARGS=\""+Arguments.GetCurrentForInstallerCmd()+"\""+(IsPortable ? " /PORTABLE=1" : "");
bool runElevated = !IsPortable || !WindowsUtils.CheckFolderWritePermission(ProgramPath); bool runElevated = !IsPortable || !WindowsUtils.CheckFolderWritePermission(ProgramPath);
WindowsUtils.StartProcess(mainForm.UpdateInstallerPath, updaterArgs, runElevated); WindowsUtils.StartProcess(mainForm.UpdateInstallerPath, updaterArgs, runElevated);

View File

@ -113,7 +113,7 @@
ele.remove(); ele.remove();
if (download){ if (download){
$TDU.onUpdateAccepted(version, download); $TDU.onUpdateAccepted();
} }
else{ else{
$TDU.openBrowser(updateDownloadFallback); $TDU.openBrowser(updateDownloadFallback);
@ -125,7 +125,7 @@
}); });
buttonDiv.children(".tdu-btn-dismiss,.tdu-btn-unsupported").click(function(){ buttonDiv.children(".tdu-btn-dismiss,.tdu-btn-unsupported").click(function(){
$TDU.onUpdateDismissed(version); $TDU.onUpdateDismissed();
ele.slideUp(function(){ ele.remove(); }); ele.slideUp(function(){ ele.remove(); });
}); });
@ -161,10 +161,13 @@
if (hasUpdate){ if (hasUpdate){
var obj = release.assets.find(asset => asset.name === updateFileName) || { browser_download_url: "" }; var obj = release.assets.find(asset => asset.name === updateFileName) || { browser_download_url: "" };
displayNotification(tagName, obj.browser_download_url); displayNotification(tagName, obj.browser_download_url);
if (eventID){ // ignore undefined and 0
$TDU.onUpdateCheckFinished(eventID, tagName, obj.browser_download_url);
}
} }
else if (eventID){ // ignore undefined and 0
if (eventID){ // ignore undefined and 0 $TDU.onUpdateCheckFinished(eventID, null, null);
$TDU.onUpdateCheckFinished(eventID, hasUpdate, tagName);
} }
}); });
}; };

View File

@ -255,6 +255,7 @@
<Compile Include="Core\Utils\NativeMethods.cs" /> <Compile Include="Core\Utils\NativeMethods.cs" />
<Compile Include="Updates\Events\UpdateAcceptedEventArgs.cs" /> <Compile Include="Updates\Events\UpdateAcceptedEventArgs.cs" />
<Compile Include="Updates\Events\UpdateCheckEventArgs.cs" /> <Compile Include="Updates\Events\UpdateCheckEventArgs.cs" />
<Compile Include="Updates\UpdateDownloadStatus.cs" />
<Compile Include="Updates\UpdateHandler.cs" /> <Compile Include="Updates\UpdateHandler.cs" />
<Compile Include="Updates\UpdateInfo.cs" /> <Compile Include="Updates\UpdateInfo.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />

View File

@ -3,13 +3,13 @@
namespace TweetDuck.Updates.Events{ namespace TweetDuck.Updates.Events{
class UpdateCheckEventArgs : EventArgs{ class UpdateCheckEventArgs : EventArgs{
public int EventId { get; } public int EventId { get; }
public bool UpdateAvailable { get; } public UpdateInfo UpdateInfo { get; }
public string LatestVersion { get; }
public UpdateCheckEventArgs(int eventId, bool updateAvailable, string latestVersion){ public bool UpdateAvailable => UpdateInfo != null;
public UpdateCheckEventArgs(int eventId, UpdateInfo updateInfo){
EventId = eventId; EventId = eventId;
UpdateAvailable = updateAvailable; UpdateInfo = updateInfo;
LatestVersion = latestVersion;
} }
} }
} }

View File

@ -23,31 +23,19 @@ protected override void Dispose(bool disposing) {
/// the contents of this method with the code editor. /// the contents of this method with the code editor.
/// </summary> /// </summary>
private void InitializeComponent() { private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormUpdateDownload)); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormUpdateDownload));
this.progressDownload = new System.Windows.Forms.ProgressBar();
this.btnCancel = new System.Windows.Forms.Button(); this.btnCancel = new System.Windows.Forms.Button();
this.labelDescription = new System.Windows.Forms.Label(); this.labelDescription = new System.Windows.Forms.Label();
this.labelStatus = new System.Windows.Forms.Label(); this.timerDownloadCheck = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout(); this.SuspendLayout();
// //
// progressDownload
//
this.progressDownload.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.progressDownload.Location = new System.Drawing.Point(12, 32);
this.progressDownload.MarqueeAnimationSpeed = 40;
this.progressDownload.Maximum = 1000;
this.progressDownload.Name = "progressDownload";
this.progressDownload.Size = new System.Drawing.Size(361, 23);
this.progressDownload.Style = System.Windows.Forms.ProgressBarStyle.Marquee;
this.progressDownload.TabIndex = 0;
//
// btnCancel // btnCancel
// //
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.AutoSize = true; this.btnCancel.AutoSize = true;
this.btnCancel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.btnCancel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
this.btnCancel.Location = new System.Drawing.Point(317, 61); this.btnCancel.Location = new System.Drawing.Point(195, 34);
this.btnCancel.Name = "btnCancel"; this.btnCancel.Name = "btnCancel";
this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0); this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
this.btnCancel.Size = new System.Drawing.Size(56, 23); this.btnCancel.Size = new System.Drawing.Size(56, 23);
@ -65,41 +53,33 @@ private void InitializeComponent() {
this.labelDescription.Size = new System.Drawing.Size(0, 13); this.labelDescription.Size = new System.Drawing.Size(0, 13);
this.labelDescription.TabIndex = 2; this.labelDescription.TabIndex = 2;
// //
// labelStatus // timerDownloadCheck
// //
this.labelStatus.AutoSize = true; this.timerDownloadCheck.Interval = 500;
this.labelStatus.Location = new System.Drawing.Point(9, 62); this.timerDownloadCheck.Tick += new System.EventHandler(this.timerDownloadCheck_Tick);
this.labelStatus.Name = "labelStatus";
this.labelStatus.Size = new System.Drawing.Size(0, 13);
this.labelStatus.TabIndex = 3;
// //
// FormUpdateDownload // FormUpdateDownload
// //
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(385, 96); this.ClientSize = new System.Drawing.Size(263, 69);
this.Controls.Add(this.labelStatus);
this.Controls.Add(this.labelDescription); this.Controls.Add(this.labelDescription);
this.Controls.Add(this.btnCancel); this.Controls.Add(this.btnCancel);
this.Controls.Add(this.progressDownload);
this.DoubleBuffered = true; this.DoubleBuffered = true;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
this.MaximizeBox = false; this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "FormUpdateDownload"; this.Name = "FormUpdateDownload";
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormUpdateDownload_FormClosing);
this.Shown += new System.EventHandler(this.FormUpdateDownload_Shown);
this.ResumeLayout(false); this.ResumeLayout(false);
this.PerformLayout(); this.PerformLayout();
} }
#endregion #endregion
private System.Windows.Forms.ProgressBar progressDownload;
private System.Windows.Forms.Button btnCancel; private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.Label labelDescription; private System.Windows.Forms.Label labelDescription;
private System.Windows.Forms.Label labelStatus; private System.Windows.Forms.Timer timerDownloadCheck;
} }
} }

View File

@ -1,114 +1,41 @@
using System; using System;
using System.ComponentModel;
using System.IO;
using System.Net;
using System.Windows.Forms; using System.Windows.Forms;
using TweetDuck.Core.Controls;
using TweetDuck.Core.Utils; using TweetDuck.Core.Utils;
namespace TweetDuck.Updates{ namespace TweetDuck.Updates{
sealed partial class FormUpdateDownload : Form{ sealed partial class FormUpdateDownload : Form{
private const double BytesToKB = 1024.0;
public string InstallerPath => Path.Combine(Path.GetTempPath(), updateInfo.FileName);
public enum Status{
Waiting, Failed, Cancelled, Manual, Succeeded
}
public Status UpdateStatus { get; private set; }
private readonly WebClient webClient;
private readonly UpdateInfo updateInfo; private readonly UpdateInfo updateInfo;
public FormUpdateDownload(UpdateInfo info){ public FormUpdateDownload(UpdateInfo info){
InitializeComponent(); InitializeComponent();
this.updateInfo = info;
Text = "Updating "+Program.BrandName; Text = "Updating "+Program.BrandName;
labelDescription.Text = "Downloading version "+info.VersionTag+"..."; labelDescription.Text = "Downloading version "+info.VersionTag+"...";
timerDownloadCheck.Start();
this.updateInfo = info;
this.UpdateStatus = Status.Waiting;
this.webClient = new WebClient{ Proxy = null };
this.webClient.Headers[HttpRequestHeader.UserAgent] = BrowserUtils.HeaderUserAgent;
this.webClient.DownloadProgressChanged += webClient_DownloadProgressChanged;
this.webClient.DownloadFileCompleted += webClient_DownloadFileCompleted;
Disposed += (sender, args) => this.webClient.Dispose();
}
private void FormUpdateDownload_Shown(object sender, EventArgs e){
webClient.DownloadFileAsync(new Uri(updateInfo.DownloadUrl), InstallerPath);
} }
private void btnCancel_Click(object sender, EventArgs e){ private void btnCancel_Click(object sender, EventArgs e){
if (webClient.IsBusy){ Close();
webClient.CancelAsync(); }
btnCancel.Enabled = false;
} private void timerDownloadCheck_Tick(object sender, EventArgs e){
else{ if (updateInfo.DownloadStatus == UpdateDownloadStatus.Done){
UpdateStatus = Status.Cancelled; timerDownloadCheck.Stop();
DialogResult = DialogResult.OK;
Close(); Close();
} }
} else if (updateInfo.DownloadStatus == UpdateDownloadStatus.Failed){
timerDownloadCheck.Stop();
private void FormUpdateDownload_FormClosing(object sender, FormClosingEventArgs e){ if (MessageBox.Show("Could not download the update: "+(updateInfo.DownloadError?.Message ?? "unknown error")+"\r\n\r\nDo you want to open the website and try downloading the update manually?", "Update Has Failed", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1) == DialogResult.Yes){
if (UpdateStatus == Status.Waiting){ BrowserUtils.OpenExternalBrowserUnsafe(Program.Website);
UpdateStatus = e.CloseReason == CloseReason.UserClosing ? Status.Cancelled : Status.Manual; // manual will exit the app DialogResult = DialogResult.OK;
if (webClient.IsBusy){
webClient.CancelAsync();
e.Cancel = true;
} }
}
}
private void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e){
this.InvokeSafe(() => {
if (e.TotalBytesToReceive == -1){
if (progressDownload.Style != ProgressBarStyle.Marquee){
progressDownload.Style = ProgressBarStyle.Continuous;
progressDownload.SetValueInstant(1000);
}
labelStatus.Text = (long)(e.BytesReceived/BytesToKB)+" kB";
}
else{
if (progressDownload.Style != ProgressBarStyle.Continuous){
progressDownload.Style = ProgressBarStyle.Continuous;
}
progressDownload.SetValueInstant(e.ProgressPercentage*10);
labelStatus.Text = (long)(e.BytesReceived/BytesToKB)+" / "+(long)(e.TotalBytesToReceive/BytesToKB)+" kB";
}
});
}
private void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e){
this.InvokeSafe(() => {
if (e.Cancelled){
if (UpdateStatus == Status.Waiting){
UpdateStatus = Status.Cancelled;
}
}
else if (e.Error != null){
Program.Reporter.Log(e.Error.ToString());
if (MessageBox.Show("Could not download the update: "+e.Error.Message+"\r\n\r\nDo you want to open the website and try downloading the update manually?", "Update Has Failed", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1) == DialogResult.Yes){
BrowserUtils.OpenExternalBrowserUnsafe(Program.Website);
UpdateStatus = Status.Manual;
}
else{
UpdateStatus = Status.Failed;
}
}
else{
UpdateStatus = Status.Succeeded;
}
Close(); Close();
}); }
} }
} }
} }

View File

@ -117,6 +117,9 @@
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<metadata name="timerDownloadCheck.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value> <value>

View File

@ -0,0 +1,8 @@
namespace TweetDuck.Updates{
public enum UpdateDownloadStatus{
None = 0,
InProgress,
Done,
Failed
}
}

View File

@ -1,6 +1,7 @@
using CefSharp; using CefSharp;
using CefSharp.WinForms; using CefSharp.WinForms;
using System; using System;
using System.Windows.Forms;
using TweetDuck.Core; using TweetDuck.Core;
using TweetDuck.Core.Controls; using TweetDuck.Core.Controls;
using TweetDuck.Core.Utils; using TweetDuck.Core.Utils;
@ -20,6 +21,7 @@ sealed class UpdateHandler{
public event EventHandler<UpdateCheckEventArgs> CheckFinished; public event EventHandler<UpdateCheckEventArgs> CheckFinished;
private int lastEventId; private int lastEventId;
private UpdateInfo lastUpdateInfo;
public UpdateHandler(ChromiumWebBrowser browser, FormBrowser form, UpdaterSettings settings){ public UpdateHandler(ChromiumWebBrowser browser, FormBrowser form, UpdaterSettings settings){
this.browser = browser; this.browser = browser;
@ -55,6 +57,40 @@ public int Check(bool force){
return -1; return -1;
} }
public void BeginUpdateDownload(Form ownerForm, UpdateInfo updateInfo, Action<UpdateInfo> onSuccess){
if (updateInfo.DownloadStatus == UpdateDownloadStatus.Done){
onSuccess(updateInfo);
}
else{
FormUpdateDownload downloadForm = new FormUpdateDownload(updateInfo);
downloadForm.VisibleChanged += (sender, args) => {
downloadForm.MoveToCenter(ownerForm);
ownerForm.Hide();
};
downloadForm.FormClosed += (sender, args) => {
downloadForm.Dispose();
if (downloadForm.DialogResult == DialogResult.OK){ // success or manual download
onSuccess(updateInfo);
}
else{
ownerForm.Show();
}
};
downloadForm.Show();
}
}
public void CleanupDownload(){
if (lastUpdateInfo != null){
lastUpdateInfo.DeleteInstaller();
lastUpdateInfo = null;
}
}
public void DismissUpdate(string tag){ public void DismissUpdate(string tag){
settings.DismissedUpdate = tag; settings.DismissedUpdate = tag;
UpdateDismissed?.Invoke(this, new UpdateDismissedEventArgs(tag)); UpdateDismissed?.Invoke(this, new UpdateDismissedEventArgs(tag));
@ -90,16 +126,27 @@ public void TriggerUpdateCheck(){
owner.Check(false); owner.Check(false);
} }
public void OnUpdateCheckFinished(int eventId, bool isUpdateAvailable, string latestVersion){ public void OnUpdateCheckFinished(int eventId, string versionTag, string downloadUrl){
owner.TriggerCheckFinishedEvent(new UpdateCheckEventArgs(eventId, isUpdateAvailable, latestVersion)); if (versionTag != null && (owner.lastUpdateInfo == null || owner.lastUpdateInfo.VersionTag != versionTag)){
owner.CleanupDownload();
owner.lastUpdateInfo = new UpdateInfo(owner.settings, versionTag, downloadUrl);
owner.lastUpdateInfo.BeginSilentDownload();
}
owner.TriggerCheckFinishedEvent(new UpdateCheckEventArgs(eventId, owner.lastUpdateInfo));
} }
public void OnUpdateAccepted(string versionTag, string downloadUrl){ public void OnUpdateAccepted(){
owner.TriggerUpdateAcceptedEvent(new UpdateAcceptedEventArgs(new UpdateInfo(versionTag, downloadUrl))); if (owner.lastUpdateInfo != null){
owner.TriggerUpdateAcceptedEvent(new UpdateAcceptedEventArgs(owner.lastUpdateInfo));
}
} }
public void OnUpdateDismissed(string versionTag){ public void OnUpdateDismissed(){
owner.TriggerUpdateDismissedEvent(new UpdateDismissedEventArgs(versionTag)); if (owner.lastUpdateInfo != null){
owner.TriggerUpdateDismissedEvent(new UpdateDismissedEventArgs(owner.lastUpdateInfo.VersionTag));
owner.CleanupDownload();
}
} }
public void OpenBrowser(string url){ public void OpenBrowser(string url){

View File

@ -1,15 +1,70 @@
using TweetDuck.Core.Utils; using System;
using System.IO;
using System.Net;
using TweetDuck.Core.Utils;
namespace TweetDuck.Updates{ namespace TweetDuck.Updates{
class UpdateInfo{ class UpdateInfo{
public readonly string VersionTag; public string VersionTag { get; }
public readonly string DownloadUrl; public string InstallerPath { get; }
public string FileName => BrowserUtils.GetFileNameFromUrl(DownloadUrl) ?? Program.BrandName+".Update.exe"; public UpdateDownloadStatus DownloadStatus { get; private set; }
public Exception DownloadError { get; private set; }
private readonly string installerFolder;
private readonly string downloadUrl;
private WebClient currentDownload;
public UpdateInfo(UpdaterSettings settings, string versionTag, string downloadUrl){
this.installerFolder = settings.InstallerDownloadFolder;
this.downloadUrl = downloadUrl;
public UpdateInfo(string versionTag, string downloadUrl){
this.VersionTag = versionTag; this.VersionTag = versionTag;
this.DownloadUrl = downloadUrl; this.InstallerPath = Path.Combine(installerFolder, "TweetDuck."+versionTag+".exe");
}
public void BeginSilentDownload(){
if (DownloadStatus == UpdateDownloadStatus.None || DownloadStatus == UpdateDownloadStatus.Failed){
DownloadStatus = UpdateDownloadStatus.InProgress;
try{
Directory.CreateDirectory(installerFolder);
}catch(Exception e){
DownloadError = e;
DownloadStatus = UpdateDownloadStatus.Failed;
return;
}
if (string.IsNullOrEmpty(downloadUrl)){
DownloadError = new UriFormatException("Could not determine URL of the update installer");
DownloadStatus = UpdateDownloadStatus.Failed;
return;
}
currentDownload = BrowserUtils.DownloadFileAsync(downloadUrl, InstallerPath, () => {
DownloadStatus = UpdateDownloadStatus.Done;
currentDownload = null;
}, e => {
DownloadError = e;
DownloadStatus = UpdateDownloadStatus.Failed;
currentDownload = null;
});
}
}
public void DeleteInstaller(){
DownloadStatus = UpdateDownloadStatus.None;
if (currentDownload != null && currentDownload.IsBusy){
currentDownload.CancelAsync(); // deletes file when cancelled
return;
}
try{
File.Delete(InstallerPath);
}catch{
// rip
}
} }
} }
} }

View File

@ -2,5 +2,6 @@
class UpdaterSettings{ class UpdaterSettings{
public bool AllowPreReleases { get; set; } public bool AllowPreReleases { get; set; }
public string DismissedUpdate { get; set; } public string DismissedUpdate { get; set; }
public string InstallerDownloadFolder { get; set; }
} }
} }