1
0
mirror of https://github.com/chylex/TweetDuck.git synced 2024-10-17 09:42:45 +02:00
TweetDuck/Updates/UpdateHandler.cs

179 lines
6.0 KiB
C#

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){
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;
}
public void Dispose(){
timer.Dispose();
}
private void timer_Tick(object sender, EventArgs e){
timer.Stop();
Check(false);
}
public void StartTimer(){
if (timer.Enabled){
return;
}
timer.Stop();
if (Program.UserConfig.EnableUpdateCheck){
DateTime now = DateTime.Now;
TimeSpan nextHour = now.AddSeconds(60*(60-now.Minute)-now.Second)-now;
if (nextHour.TotalMinutes < 15){
nextHour = nextHour.Add(TimeSpan.FromHours(1));
}
timer.Interval = (int)Math.Ceiling(nextHour.TotalMilliseconds);
timer.Start();
}
}
public int Check(bool force){
if (Program.UserConfig.EnableUpdateCheck || force){
if (!browser.IsTweetDeckWebsite){
return CheckCodeNotOnTweetDeck;
}
int nextEventId = unchecked(++lastEventId);
Task<UpdateInfo> checkTask = client.Check();
checkTask.ContinueWith(task => HandleUpdateCheckSuccessful(nextEventId, task.Result), CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, scheduler);
checkTask.ContinueWith(task => HandleUpdateCheckFailed(nextEventId, task.Exception.InnerException), CancellationToken.None, TaskContinuationOptions.OnlyOnFaulted, scheduler);
return nextEventId;
}
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)));
}
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();
}
}
}
}