Merge pull request #10382 from peppy/update-check-improvements

Improve behaviour of "check for updates" button
This commit is contained in:
Bartłomiej Dach 2020-10-08 22:03:59 +02:00 committed by GitHub
commit cc41c74aad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 77 additions and 25 deletions

View File

@ -29,6 +29,11 @@ namespace osu.Desktop.Updater
private static readonly Logger logger = Logger.GetLogger("updater"); private static readonly Logger logger = Logger.GetLogger("updater");
/// <summary>
/// Whether an update has been downloaded but not yet applied.
/// </summary>
private bool updatePending;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(NotificationOverlay notification) private void load(NotificationOverlay notification)
{ {
@ -37,9 +42,9 @@ namespace osu.Desktop.Updater
Splat.Locator.CurrentMutable.Register(() => new SquirrelLogger(), typeof(Splat.ILogger)); Splat.Locator.CurrentMutable.Register(() => new SquirrelLogger(), typeof(Splat.ILogger));
} }
protected override async Task PerformUpdateCheck() => await checkForUpdateAsync(); protected override async Task<bool> PerformUpdateCheck() => await checkForUpdateAsync();
private async Task checkForUpdateAsync(bool useDeltaPatching = true, UpdateProgressNotification notification = null) private async Task<bool> checkForUpdateAsync(bool useDeltaPatching = true, UpdateProgressNotification notification = null)
{ {
// should we schedule a retry on completion of this check? // should we schedule a retry on completion of this check?
bool scheduleRecheck = true; bool scheduleRecheck = true;
@ -49,9 +54,19 @@ namespace osu.Desktop.Updater
updateManager ??= await UpdateManager.GitHubUpdateManager(@"https://github.com/ppy/osu", @"osulazer", null, null, true); updateManager ??= await UpdateManager.GitHubUpdateManager(@"https://github.com/ppy/osu", @"osulazer", null, null, true);
var info = await updateManager.CheckForUpdate(!useDeltaPatching); var info = await updateManager.CheckForUpdate(!useDeltaPatching);
if (info.ReleasesToApply.Count == 0) if (info.ReleasesToApply.Count == 0)
{
if (updatePending)
{
// the user may have dismissed the completion notice, so show it again.
notificationOverlay.Post(new UpdateCompleteNotification(this));
return true;
}
// no updates available. bail and retry later. // no updates available. bail and retry later.
return; return false;
}
if (notification == null) if (notification == null)
{ {
@ -72,6 +87,7 @@ namespace osu.Desktop.Updater
await updateManager.ApplyReleases(info, p => notification.Progress = p / 100f); await updateManager.ApplyReleases(info, p => notification.Progress = p / 100f);
notification.State = ProgressNotificationState.Completed; notification.State = ProgressNotificationState.Completed;
updatePending = true;
} }
catch (Exception e) catch (Exception e)
{ {
@ -103,6 +119,8 @@ namespace osu.Desktop.Updater
Scheduler.AddDelayed(async () => await checkForUpdateAsync(), 60000 * 30); Scheduler.AddDelayed(async () => await checkForUpdateAsync(), 60000 * 30);
} }
} }
return true;
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
@ -111,10 +129,27 @@ namespace osu.Desktop.Updater
updateManager?.Dispose(); updateManager?.Dispose();
} }
private class UpdateCompleteNotification : ProgressCompletionNotification
{
[Resolved]
private OsuGame game { get; set; }
public UpdateCompleteNotification(SquirrelUpdateManager updateManager)
{
Text = @"Update ready to install. Click to restart!";
Activated = () =>
{
updateManager.PrepareUpdateAsync()
.ContinueWith(_ => updateManager.Schedule(() => game.GracefullyExit()));
return true;
};
}
}
private class UpdateProgressNotification : ProgressNotification private class UpdateProgressNotification : ProgressNotification
{ {
private readonly SquirrelUpdateManager updateManager; private readonly SquirrelUpdateManager updateManager;
private OsuGame game;
public UpdateProgressNotification(SquirrelUpdateManager updateManager) public UpdateProgressNotification(SquirrelUpdateManager updateManager)
{ {
@ -123,23 +158,12 @@ namespace osu.Desktop.Updater
protected override Notification CreateCompletionNotification() protected override Notification CreateCompletionNotification()
{ {
return new ProgressCompletionNotification return new UpdateCompleteNotification(updateManager);
{
Text = @"Update ready to install. Click to restart!",
Activated = () =>
{
updateManager.PrepareUpdateAsync()
.ContinueWith(_ => updateManager.Schedule(() => game.GracefullyExit()));
return true;
}
};
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(OsuColour colours, OsuGame game) private void load(OsuColour colours)
{ {
this.game = game;
IconContent.AddRange(new Drawable[] IconContent.AddRange(new Drawable[]
{ {
new Box new Box

View File

@ -4,9 +4,11 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Framework; using osu.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Platform; using osu.Framework.Platform;
using osu.Framework.Screens; using osu.Framework.Screens;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Overlays.Notifications;
using osu.Game.Overlays.Settings.Sections.Maintenance; using osu.Game.Overlays.Settings.Sections.Maintenance;
using osu.Game.Updater; using osu.Game.Updater;
@ -21,6 +23,9 @@ namespace osu.Game.Overlays.Settings.Sections.General
private SettingsButton checkForUpdatesButton; private SettingsButton checkForUpdatesButton;
[Resolved(CanBeNull = true)]
private NotificationOverlay notifications { get; set; }
[BackgroundDependencyLoader(true)] [BackgroundDependencyLoader(true)]
private void load(Storage storage, OsuConfigManager config, OsuGame game) private void load(Storage storage, OsuConfigManager config, OsuGame game)
{ {
@ -38,7 +43,19 @@ namespace osu.Game.Overlays.Settings.Sections.General
Action = () => Action = () =>
{ {
checkForUpdatesButton.Enabled.Value = false; checkForUpdatesButton.Enabled.Value = false;
Task.Run(updateManager.CheckForUpdateAsync).ContinueWith(t => Schedule(() => checkForUpdatesButton.Enabled.Value = true)); Task.Run(updateManager.CheckForUpdateAsync).ContinueWith(t => Schedule(() =>
{
if (!t.Result)
{
notifications?.Post(new SimpleNotification
{
Text = $"You are running the latest release ({game.Version})",
Icon = FontAwesome.Solid.CheckCircle,
});
}
checkForUpdatesButton.Enabled.Value = true;
}));
} }
}); });
} }

View File

@ -30,7 +30,7 @@ namespace osu.Game.Updater
version = game.Version; version = game.Version;
} }
protected override async Task PerformUpdateCheck() protected override async Task<bool> PerformUpdateCheck()
{ {
try try
{ {
@ -53,12 +53,17 @@ namespace osu.Game.Updater
return true; return true;
} }
}); });
return true;
} }
} }
catch catch
{ {
// we shouldn't crash on a web failure. or any failure for the matter. // we shouldn't crash on a web failure. or any failure for the matter.
return true;
} }
return false;
} }
private string getBestUrl(GitHubRelease release) private string getBestUrl(GitHubRelease release)

View File

@ -57,25 +57,31 @@ namespace osu.Game.Updater
private readonly object updateTaskLock = new object(); private readonly object updateTaskLock = new object();
private Task updateCheckTask; private Task<bool> updateCheckTask;
public async Task CheckForUpdateAsync() public async Task<bool> CheckForUpdateAsync()
{ {
if (!CanCheckForUpdate) if (!CanCheckForUpdate)
return; return false;
Task waitTask; Task<bool> waitTask;
lock (updateTaskLock) lock (updateTaskLock)
waitTask = (updateCheckTask ??= PerformUpdateCheck()); waitTask = (updateCheckTask ??= PerformUpdateCheck());
await waitTask; bool hasUpdates = await waitTask;
lock (updateTaskLock) lock (updateTaskLock)
updateCheckTask = null; updateCheckTask = null;
return hasUpdates;
} }
protected virtual Task PerformUpdateCheck() => Task.CompletedTask; /// <summary>
/// Performs an asynchronous check for application updates.
/// </summary>
/// <returns>Whether any update is waiting. May return true if an error occured (there is potentially an update available).</returns>
protected virtual Task<bool> PerformUpdateCheck() => Task.FromResult(false);
private class UpdateCompleteNotification : SimpleNotification private class UpdateCompleteNotification : SimpleNotification
{ {