mirror of
https://github.com/chylex/TweetDuck.git
synced 2025-04-11 12:15:44 +02:00
Refactor update notification into a bridge object & tweak installer pre-downloading
This commit is contained in:
parent
502ac4ebc1
commit
db9daf2714
68
Core/Bridge/UpdateBridge.cs
Normal file
68
Core/Bridge/UpdateBridge.cs
Normal file
@ -0,0 +1,68 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
using TweetDuck.Core.Controls;
|
||||
using TweetDuck.Updates;
|
||||
|
||||
namespace TweetDuck.Core.Bridge{
|
||||
class UpdateBridge{
|
||||
private readonly UpdateHandler updates;
|
||||
private readonly Control sync;
|
||||
|
||||
private UpdateInfo nextUpdate = null;
|
||||
|
||||
public event EventHandler<UpdateInfo> UpdateAccepted;
|
||||
public event EventHandler<UpdateInfo> UpdateDelayed;
|
||||
public event EventHandler<UpdateInfo> UpdateDismissed;
|
||||
|
||||
public UpdateBridge(UpdateHandler updates, Control sync){
|
||||
this.sync = sync;
|
||||
|
||||
this.updates = updates;
|
||||
this.updates.CheckFinished += updates_CheckFinished;
|
||||
}
|
||||
|
||||
internal void Cleanup(){
|
||||
updates.CheckFinished -= updates_CheckFinished;
|
||||
nextUpdate?.DeleteInstaller();
|
||||
}
|
||||
|
||||
private void updates_CheckFinished(object sender, UpdateCheckEventArgs e){
|
||||
UpdateInfo foundUpdate = e.Result.HasValue ? e.Result.Value : null;
|
||||
|
||||
if (nextUpdate != null && !nextUpdate.Equals(foundUpdate)){
|
||||
nextUpdate.DeleteInstaller();
|
||||
}
|
||||
|
||||
nextUpdate = foundUpdate;
|
||||
}
|
||||
|
||||
private void HandleInteractionEvent(EventHandler<UpdateInfo> eventHandler){
|
||||
UpdateInfo tmpInfo = nextUpdate;
|
||||
|
||||
if (tmpInfo != null){
|
||||
sync.InvokeAsyncSafe(() => eventHandler?.Invoke(this, tmpInfo));
|
||||
}
|
||||
}
|
||||
|
||||
// Bridge methods
|
||||
|
||||
public void TriggerUpdateCheck(){
|
||||
updates.Check(false);
|
||||
}
|
||||
|
||||
public void OnUpdateAccepted(){
|
||||
HandleInteractionEvent(UpdateAccepted);
|
||||
}
|
||||
|
||||
public void OnUpdateDelayed(){
|
||||
HandleInteractionEvent(UpdateDelayed);
|
||||
}
|
||||
|
||||
public void OnUpdateDismissed(){
|
||||
HandleInteractionEvent(UpdateDismissed);
|
||||
|
||||
nextUpdate?.DeleteInstaller();
|
||||
nextUpdate = null;
|
||||
}
|
||||
}
|
||||
}
|
@ -17,7 +17,6 @@
|
||||
using TweetDuck.Plugins.Enums;
|
||||
using TweetDuck.Plugins.Events;
|
||||
using TweetDuck.Updates;
|
||||
using TweetDuck.Updates.Events;
|
||||
|
||||
namespace TweetDuck.Core{
|
||||
sealed partial class FormBrowser : Form, AnalyticsFile.IProvider{
|
||||
@ -50,6 +49,7 @@ public bool IsWaiting{
|
||||
private readonly UpdateHandler updates;
|
||||
private readonly FormNotificationTweet notification;
|
||||
private readonly ContextMenu contextMenu;
|
||||
private readonly UpdateBridge updateBridge;
|
||||
|
||||
private bool isLoaded;
|
||||
private FormWindowState prevState;
|
||||
@ -62,7 +62,7 @@ public FormBrowser(){
|
||||
InitializeComponent();
|
||||
|
||||
Text = Program.BrandName;
|
||||
|
||||
|
||||
this.plugins = new PluginManager(Program.PluginPath, Program.PluginConfigFilePath);
|
||||
this.plugins.Reloaded += plugins_Reloaded;
|
||||
this.plugins.Executed += plugins_Executed;
|
||||
@ -71,7 +71,15 @@ public FormBrowser(){
|
||||
this.notification = new FormNotificationTweet(this, plugins);
|
||||
this.notification.Show();
|
||||
|
||||
this.browser = new TweetDeckBrowser(this, new TweetDeckBridge.Browser(this, notification));
|
||||
this.updates = new UpdateHandler(Program.InstallerPath);
|
||||
this.updates.CheckFinished += updates_CheckFinished;
|
||||
|
||||
this.updateBridge = new UpdateBridge(updates, this);
|
||||
this.updateBridge.UpdateAccepted += updateBridge_UpdateAccepted;
|
||||
this.updateBridge.UpdateDelayed += updateBridge_UpdateDelayed;
|
||||
this.updateBridge.UpdateDismissed += updateBridge_UpdateDismissed;
|
||||
|
||||
this.browser = new TweetDeckBrowser(this, new TweetDeckBridge.Browser(this, notification), updateBridge);
|
||||
this.contextMenu = ContextMenuBrowser.CreateMenu(this);
|
||||
|
||||
this.plugins.Register(browser, PluginEnvironment.Browser, this, true);
|
||||
@ -103,11 +111,6 @@ public FormBrowser(){
|
||||
UpdateFormIcon();
|
||||
}
|
||||
|
||||
this.updates = new UpdateHandler(browser, Program.InstallerPath);
|
||||
this.updates.CheckFinished += updates_CheckFinished;
|
||||
this.updates.UpdateAccepted += updates_UpdateAccepted;
|
||||
this.updates.UpdateDismissed += updates_UpdateDismissed;
|
||||
|
||||
if (Config.AllowDataCollection){
|
||||
analytics = new AnalyticsManager(this, plugins, Program.AnalyticsFilePath);
|
||||
}
|
||||
@ -207,7 +210,7 @@ private void FormBrowser_FormClosing(object sender, FormClosingEventArgs e){
|
||||
|
||||
private void FormBrowser_FormClosed(object sender, FormClosedEventArgs e){
|
||||
if (isLoaded && UpdateInstallerPath == null){
|
||||
updates.CleanupDownload();
|
||||
updateBridge.Cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
@ -252,7 +255,7 @@ private void updates_CheckFinished(object sender, UpdateCheckEventArgs e){
|
||||
string tag = update.VersionTag;
|
||||
|
||||
if (tag != Program.VersionTag && tag != Config.DismissedUpdate){
|
||||
updates.PrepareUpdate(update);
|
||||
update.BeginSilentDownload();
|
||||
browser.ShowUpdateNotification(tag, update.ReleaseNotes);
|
||||
}
|
||||
else{
|
||||
@ -268,38 +271,61 @@ private void updates_CheckFinished(object sender, UpdateCheckEventArgs e){
|
||||
ignoreUpdateCheckError = true;
|
||||
}
|
||||
|
||||
private void updates_UpdateAccepted(object sender, UpdateEventArgs e){
|
||||
this.InvokeAsyncSafe(() => {
|
||||
FormManager.CloseAllDialogs();
|
||||
private void updateBridge_UpdateAccepted(object sender, UpdateInfo update){
|
||||
FormManager.CloseAllDialogs();
|
||||
|
||||
if (!string.IsNullOrEmpty(Config.DismissedUpdate)){
|
||||
Config.DismissedUpdate = null;
|
||||
Config.Save();
|
||||
if (!string.IsNullOrEmpty(Config.DismissedUpdate)){
|
||||
Config.DismissedUpdate = null;
|
||||
Config.Save();
|
||||
}
|
||||
|
||||
void OnFinished(){
|
||||
UpdateDownloadStatus status = update.DownloadStatus;
|
||||
|
||||
if (status == UpdateDownloadStatus.Done){
|
||||
UpdateInstallerPath = update.InstallerPath;
|
||||
ForceClose();
|
||||
}
|
||||
else if (status != UpdateDownloadStatus.Canceled && FormMessage.Error("Update Has Failed", "Could not automatically download the update: "+(update.DownloadError?.Message ?? "unknown error")+"\n\nWould you like to open the website and try downloading the update manually?", FormMessage.Yes, FormMessage.No)){
|
||||
BrowserUtils.OpenExternalBrowser(Program.Website);
|
||||
ForceClose();
|
||||
}
|
||||
else{
|
||||
Show();
|
||||
}
|
||||
}
|
||||
|
||||
if (update.DownloadStatus.IsFinished(true)){
|
||||
OnFinished();
|
||||
}
|
||||
else{
|
||||
FormUpdateDownload downloadForm = new FormUpdateDownload(update);
|
||||
|
||||
updates.BeginUpdateDownload(this, e.UpdateInfo, update => {
|
||||
UpdateDownloadStatus status = update.DownloadStatus;
|
||||
downloadForm.VisibleChanged += (sender2, args2) => {
|
||||
downloadForm.MoveToCenter(this);
|
||||
Hide();
|
||||
};
|
||||
|
||||
if (status == UpdateDownloadStatus.Done){
|
||||
UpdateInstallerPath = update.InstallerPath;
|
||||
ForceClose();
|
||||
downloadForm.FormClosed += (sender2, args2) => {
|
||||
if (downloadForm.DialogResult != DialogResult.OK){
|
||||
update.CancelDownload();
|
||||
}
|
||||
else if (status != UpdateDownloadStatus.Canceled && FormMessage.Error("Update Has Failed", "Could not automatically download the update: "+(update.DownloadError?.Message ?? "unknown error")+"\n\nWould you like to open the website and try downloading the update manually?", FormMessage.Yes, FormMessage.No)){
|
||||
BrowserUtils.OpenExternalBrowser(Program.Website);
|
||||
ForceClose();
|
||||
}
|
||||
else{
|
||||
Show();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
downloadForm.Dispose();
|
||||
OnFinished();
|
||||
};
|
||||
|
||||
downloadForm.Show();
|
||||
}
|
||||
}
|
||||
|
||||
private void updates_UpdateDismissed(object sender, UpdateEventArgs e){
|
||||
this.InvokeAsyncSafe(() => {
|
||||
Config.DismissedUpdate = e.UpdateInfo.VersionTag;
|
||||
Config.Save();
|
||||
});
|
||||
private void updateBridge_UpdateDelayed(object sender, UpdateInfo update){
|
||||
// stops the timer
|
||||
}
|
||||
|
||||
private void updateBridge_UpdateDismissed(object sender, UpdateInfo update){
|
||||
Config.DismissedUpdate = update.VersionTag;
|
||||
Config.Save();
|
||||
}
|
||||
|
||||
protected override void WndProc(ref Message m){
|
||||
|
@ -7,7 +7,6 @@
|
||||
using TweetDuck.Core.Other.Settings.Dialogs;
|
||||
using TweetDuck.Core.Utils;
|
||||
using TweetDuck.Updates;
|
||||
using TweetDuck.Updates.Events;
|
||||
|
||||
namespace TweetDuck.Core.Other.Settings{
|
||||
sealed partial class TabSettingsGeneral : BaseTabSettings{
|
||||
@ -210,11 +209,6 @@ private void btnCheckUpdates_Click(object sender, EventArgs e){
|
||||
|
||||
btnCheckUpdates.Enabled = false;
|
||||
updateCheckEventId = updates.Check(true);
|
||||
|
||||
if (updateCheckEventId == UpdateHandler.CheckCodeNotOnTweetDeck){
|
||||
FormMessage.Error("Update Check", "Updates can only be checked once TweetDeck is fully loaded.", FormMessage.OK);
|
||||
btnCheckUpdates.Enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void updates_CheckFinished(object sender, UpdateCheckEventArgs e){
|
||||
@ -225,6 +219,8 @@ private void updates_CheckFinished(object sender, UpdateCheckEventArgs e){
|
||||
if (update.VersionTag == Program.VersionTag){
|
||||
FormMessage.Information("No Updates Available", "Your version of TweetDuck is up to date.", FormMessage.OK);
|
||||
}
|
||||
|
||||
// TODO allow outside TweetDeck
|
||||
}, ex => {
|
||||
Program.Reporter.HandleException("Update Check Error", "An error occurred while checking for updates.", true, ex);
|
||||
});
|
||||
|
@ -9,7 +9,6 @@
|
||||
using TweetDuck.Core.Controls;
|
||||
using TweetDuck.Core.Handling;
|
||||
using TweetDuck.Core.Handling.General;
|
||||
using TweetDuck.Core.Management;
|
||||
using TweetDuck.Core.Notification;
|
||||
using TweetDuck.Core.Other.Interfaces;
|
||||
using TweetDuck.Core.Utils;
|
||||
@ -40,7 +39,7 @@ public bool IsTweetDeckWebsite{
|
||||
|
||||
private string prevSoundNotificationPath = null;
|
||||
|
||||
public TweetDeckBrowser(FormBrowser owner, TweetDeckBridge bridge){
|
||||
public TweetDeckBrowser(FormBrowser owner, TweetDeckBridge tdBridge, UpdateBridge updateBridge){
|
||||
RequestHandlerBrowser requestHandler = new RequestHandlerBrowser();
|
||||
|
||||
this.browser = new ChromiumWebBrowser(TwitterUtils.TweetDeckURL){
|
||||
@ -58,7 +57,8 @@ public TweetDeckBrowser(FormBrowser owner, TweetDeckBridge bridge){
|
||||
this.browser.FrameLoadEnd += browser_FrameLoadEnd;
|
||||
this.browser.LoadError += browser_LoadError;
|
||||
|
||||
this.browser.RegisterAsyncJsObject("$TD", bridge);
|
||||
this.browser.RegisterAsyncJsObject("$TD", tdBridge);
|
||||
this.browser.RegisterAsyncJsObject("$TDU", updateBridge);
|
||||
|
||||
this.browser.BrowserSettings.BackgroundColor = (uint)TwitterUtils.BackgroundColor.ToArgb();
|
||||
this.browser.Dock = DockStyle.None;
|
||||
|
@ -58,6 +58,7 @@
|
||||
<Compile Include="Configuration\SystemConfig.cs" />
|
||||
<Compile Include="Configuration\UserConfig.cs" />
|
||||
<Compile Include="Core\Bridge\PropertyBridge.cs" />
|
||||
<Compile Include="Core\Bridge\UpdateBridge.cs" />
|
||||
<Compile Include="Core\Controls\ControlExtensions.cs" />
|
||||
<Compile Include="Core\Controls\FlatButton.cs">
|
||||
<SubType>Component</SubType>
|
||||
@ -283,7 +284,7 @@
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Reporter.cs" />
|
||||
<Compile Include="Updates\Events\UpdateCheckEventArgs.cs" />
|
||||
<Compile Include="Updates\UpdateCheckEventArgs.cs" />
|
||||
<Compile Include="Updates\FormUpdateDownload.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
@ -306,7 +307,6 @@
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Resources\ScriptLoader.cs" />
|
||||
<Compile Include="Updates\Events\UpdateEventArgs.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
|
@ -1,11 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace TweetDuck.Updates.Events{
|
||||
sealed class UpdateEventArgs : EventArgs{
|
||||
public UpdateInfo UpdateInfo { get; }
|
||||
|
||||
public UpdateEventArgs(UpdateInfo updateInfo){
|
||||
this.UpdateInfo = updateInfo;
|
||||
}
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@ private void btnCancel_Click(object sender, EventArgs e){
|
||||
}
|
||||
|
||||
private void timerDownloadCheck_Tick(object sender, EventArgs e){
|
||||
if (updateInfo.DownloadStatus.IsFinished()){
|
||||
if (updateInfo.DownloadStatus.IsFinished(false)){
|
||||
timerDownloadCheck.Stop();
|
||||
DialogResult = DialogResult.OK;
|
||||
Close();
|
||||
|
@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using TweetDuck.Data;
|
||||
|
||||
namespace TweetDuck.Updates.Events{
|
||||
namespace TweetDuck.Updates{
|
||||
sealed class UpdateCheckEventArgs : EventArgs{
|
||||
public int EventId { get; }
|
||||
public Result<UpdateInfo> Result { get; }
|
@ -9,8 +9,8 @@ public enum UpdateDownloadStatus{
|
||||
}
|
||||
|
||||
public static class UpdateDownloadStatusExtensions{
|
||||
public static bool IsFinished(this UpdateDownloadStatus status){
|
||||
return status == UpdateDownloadStatus.AssetMissing || status == UpdateDownloadStatus.Done || status == UpdateDownloadStatus.Failed;
|
||||
public static bool IsFinished(this UpdateDownloadStatus status, bool canRetry){
|
||||
return status == UpdateDownloadStatus.AssetMissing || status == UpdateDownloadStatus.Done || (status == UpdateDownloadStatus.Failed && !canRetry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,38 +1,24 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
using TweetDuck.Core.Controls;
|
||||
using TweetDuck.Core.Other.Interfaces;
|
||||
using TweetDuck.Data;
|
||||
using TweetDuck.Updates.Events;
|
||||
using Timer = System.Windows.Forms.Timer;
|
||||
|
||||
namespace TweetDuck.Updates{
|
||||
sealed class UpdateHandler : IDisposable{
|
||||
public const int CheckCodeUpdatesDisabled = -1;
|
||||
public const int CheckCodeNotOnTweetDeck = -2;
|
||||
|
||||
private readonly UpdateCheckClient client;
|
||||
private readonly TaskScheduler scheduler;
|
||||
private readonly ITweetDeckBrowser browser;
|
||||
private readonly Timer timer;
|
||||
|
||||
public event EventHandler<UpdateEventArgs> UpdateAccepted;
|
||||
public event EventHandler<UpdateEventArgs> UpdateDelayed;
|
||||
public event EventHandler<UpdateEventArgs> UpdateDismissed;
|
||||
|
||||
public event EventHandler<UpdateCheckEventArgs> CheckFinished;
|
||||
|
||||
private ushort lastEventId;
|
||||
private UpdateInfo lastUpdateInfo;
|
||||
|
||||
public UpdateHandler(ITweetDeckBrowser browser, string installerFolder){
|
||||
public UpdateHandler(string installerFolder){
|
||||
this.client = new UpdateCheckClient(installerFolder);
|
||||
this.scheduler = TaskScheduler.FromCurrentSynchronizationContext();
|
||||
|
||||
this.browser = browser;
|
||||
this.browser.RegisterBridge("$TDU", new Bridge(this));
|
||||
|
||||
this.timer = new Timer();
|
||||
this.timer.Tick += timer_Tick;
|
||||
}
|
||||
@ -68,10 +54,6 @@ public void StartTimer(){
|
||||
|
||||
public int Check(bool force){
|
||||
if (Program.UserConfig.EnableUpdateCheck || force){
|
||||
if (!browser.IsTweetDeckWebsite){
|
||||
return CheckCodeNotOnTweetDeck;
|
||||
}
|
||||
|
||||
int nextEventId = unchecked(++lastEventId);
|
||||
Task<UpdateInfo> checkTask = client.Check();
|
||||
|
||||
@ -84,46 +66,6 @@ public int Check(bool force){
|
||||
return CheckCodeUpdatesDisabled;
|
||||
}
|
||||
|
||||
public void PrepareUpdate(UpdateInfo info){
|
||||
CleanupDownload();
|
||||
lastUpdateInfo = info;
|
||||
lastUpdateInfo.BeginSilentDownload();
|
||||
}
|
||||
|
||||
public void BeginUpdateDownload(Form ownerForm, UpdateInfo updateInfo, Action<UpdateInfo> onFinished){
|
||||
UpdateDownloadStatus status = updateInfo.DownloadStatus;
|
||||
|
||||
if (status == UpdateDownloadStatus.Done || status == UpdateDownloadStatus.AssetMissing){
|
||||
onFinished(updateInfo);
|
||||
}
|
||||
else{
|
||||
FormUpdateDownload downloadForm = new FormUpdateDownload(updateInfo);
|
||||
|
||||
downloadForm.VisibleChanged += (sender, args) => {
|
||||
downloadForm.MoveToCenter(ownerForm);
|
||||
ownerForm.Hide();
|
||||
};
|
||||
|
||||
downloadForm.FormClosed += (sender, args) => {
|
||||
if (downloadForm.DialogResult != DialogResult.OK){
|
||||
updateInfo.CancelDownload();
|
||||
}
|
||||
|
||||
downloadForm.Dispose();
|
||||
onFinished(updateInfo);
|
||||
};
|
||||
|
||||
downloadForm.Show();
|
||||
}
|
||||
}
|
||||
|
||||
public void CleanupDownload(){
|
||||
if (lastUpdateInfo != null){
|
||||
lastUpdateInfo.DeleteInstaller();
|
||||
lastUpdateInfo = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleUpdateCheckSuccessful(int eventId, UpdateInfo info){
|
||||
CheckFinished?.Invoke(this, new UpdateCheckEventArgs(eventId, new Result<UpdateInfo>(info)));
|
||||
}
|
||||
@ -131,48 +73,5 @@ private void HandleUpdateCheckSuccessful(int eventId, UpdateInfo info){
|
||||
private void HandleUpdateCheckFailed(int eventId, Exception exception){
|
||||
CheckFinished?.Invoke(this, new UpdateCheckEventArgs(eventId, new Result<UpdateInfo>(exception)));
|
||||
}
|
||||
|
||||
private void TriggerUpdateAcceptedEvent(){
|
||||
if (lastUpdateInfo != null){
|
||||
UpdateAccepted?.Invoke(this, new UpdateEventArgs(lastUpdateInfo));
|
||||
}
|
||||
}
|
||||
|
||||
private void TriggerUpdateDelayedEvent(){
|
||||
if (lastUpdateInfo != null){
|
||||
UpdateDelayed?.Invoke(this, new UpdateEventArgs(lastUpdateInfo));
|
||||
}
|
||||
}
|
||||
|
||||
private void TriggerUpdateDismissedEvent(){
|
||||
if (lastUpdateInfo != null){
|
||||
UpdateDismissed?.Invoke(this, new UpdateEventArgs(lastUpdateInfo));
|
||||
CleanupDownload();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class Bridge{
|
||||
private readonly UpdateHandler owner;
|
||||
|
||||
public Bridge(UpdateHandler owner){
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public void TriggerUpdateCheck(){
|
||||
owner.Check(false);
|
||||
}
|
||||
|
||||
public void OnUpdateAccepted(){
|
||||
owner.TriggerUpdateAcceptedEvent();
|
||||
}
|
||||
|
||||
public void OnUpdateDelayed(){
|
||||
owner.TriggerUpdateDelayedEvent();
|
||||
}
|
||||
|
||||
public void OnUpdateDismissed(){
|
||||
owner.TriggerUpdateDismissedEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,11 @@ public UpdateInfo(string versionTag, string releaseNotes, string downloadUrl, st
|
||||
}
|
||||
|
||||
public void BeginSilentDownload(){
|
||||
if (File.Exists(InstallerPath)){
|
||||
DownloadStatus = UpdateDownloadStatus.Done;
|
||||
return;
|
||||
}
|
||||
|
||||
if (DownloadStatus == UpdateDownloadStatus.None || DownloadStatus == UpdateDownloadStatus.Failed){
|
||||
DownloadStatus = UpdateDownloadStatus.InProgress;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user