diff --git a/osu.Desktop/Updater/SquirrelUpdateManager.cs b/osu.Desktop/Updater/SquirrelUpdateManager.cs
index 05c8e835ac..71f9fafe57 100644
--- a/osu.Desktop/Updater/SquirrelUpdateManager.cs
+++ b/osu.Desktop/Updater/SquirrelUpdateManager.cs
@@ -29,6 +29,11 @@ namespace osu.Desktop.Updater
private static readonly Logger logger = Logger.GetLogger("updater");
+ ///
+ /// Whether an update has been downloaded but not yet applied.
+ ///
+ private bool updatePending;
+
[BackgroundDependencyLoader]
private void load(NotificationOverlay notification)
{
@@ -37,9 +42,9 @@ namespace osu.Desktop.Updater
Splat.Locator.CurrentMutable.Register(() => new SquirrelLogger(), typeof(Splat.ILogger));
}
- protected override async Task PerformUpdateCheck() => await checkForUpdateAsync();
+ protected override async Task PerformUpdateCheck() => await checkForUpdateAsync();
- private async Task checkForUpdateAsync(bool useDeltaPatching = true, UpdateProgressNotification notification = null)
+ private async Task checkForUpdateAsync(bool useDeltaPatching = true, UpdateProgressNotification notification = null)
{
// should we schedule a retry on completion of this check?
bool scheduleRecheck = true;
@@ -49,9 +54,19 @@ namespace osu.Desktop.Updater
updateManager ??= await UpdateManager.GitHubUpdateManager(@"https://github.com/ppy/osu", @"osulazer", null, null, true);
var info = await updateManager.CheckForUpdate(!useDeltaPatching);
+
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.
- return;
+ return false;
+ }
if (notification == null)
{
@@ -72,6 +87,7 @@ namespace osu.Desktop.Updater
await updateManager.ApplyReleases(info, p => notification.Progress = p / 100f);
notification.State = ProgressNotificationState.Completed;
+ updatePending = true;
}
catch (Exception e)
{
@@ -103,6 +119,8 @@ namespace osu.Desktop.Updater
Scheduler.AddDelayed(async () => await checkForUpdateAsync(), 60000 * 30);
}
}
+
+ return true;
}
protected override void Dispose(bool isDisposing)
@@ -111,10 +129,27 @@ namespace osu.Desktop.Updater
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 readonly SquirrelUpdateManager updateManager;
- private OsuGame game;
public UpdateProgressNotification(SquirrelUpdateManager updateManager)
{
@@ -123,23 +158,12 @@ namespace osu.Desktop.Updater
protected override Notification CreateCompletionNotification()
{
- return new ProgressCompletionNotification
- {
- Text = @"Update ready to install. Click to restart!",
- Activated = () =>
- {
- updateManager.PrepareUpdateAsync()
- .ContinueWith(_ => updateManager.Schedule(() => game.GracefullyExit()));
- return true;
- }
- };
+ return new UpdateCompleteNotification(updateManager);
}
[BackgroundDependencyLoader]
- private void load(OsuColour colours, OsuGame game)
+ private void load(OsuColour colours)
{
- this.game = game;
-
IconContent.AddRange(new Drawable[]
{
new Box
diff --git a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs
index a59a6b00b9..c213313559 100644
--- a/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs
+++ b/osu.Game/Overlays/Settings/Sections/General/UpdateSettings.cs
@@ -4,9 +4,11 @@
using System.Threading.Tasks;
using osu.Framework;
using osu.Framework.Allocation;
+using osu.Framework.Graphics.Sprites;
using osu.Framework.Platform;
using osu.Framework.Screens;
using osu.Game.Configuration;
+using osu.Game.Overlays.Notifications;
using osu.Game.Overlays.Settings.Sections.Maintenance;
using osu.Game.Updater;
@@ -21,6 +23,9 @@ namespace osu.Game.Overlays.Settings.Sections.General
private SettingsButton checkForUpdatesButton;
+ [Resolved(CanBeNull = true)]
+ private NotificationOverlay notifications { get; set; }
+
[BackgroundDependencyLoader(true)]
private void load(Storage storage, OsuConfigManager config, OsuGame game)
{
@@ -38,7 +43,19 @@ namespace osu.Game.Overlays.Settings.Sections.General
Action = () =>
{
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;
+ }));
}
});
}
diff --git a/osu.Game/Updater/SimpleUpdateManager.cs b/osu.Game/Updater/SimpleUpdateManager.cs
index 48c6722bd9..b5fcb56c06 100644
--- a/osu.Game/Updater/SimpleUpdateManager.cs
+++ b/osu.Game/Updater/SimpleUpdateManager.cs
@@ -30,7 +30,7 @@ namespace osu.Game.Updater
version = game.Version;
}
- protected override async Task PerformUpdateCheck()
+ protected override async Task PerformUpdateCheck()
{
try
{
@@ -53,12 +53,17 @@ namespace osu.Game.Updater
return true;
}
});
+
+ return true;
}
}
catch
{
// we shouldn't crash on a web failure. or any failure for the matter.
+ return true;
}
+
+ return false;
}
private string getBestUrl(GitHubRelease release)
diff --git a/osu.Game/Updater/UpdateManager.cs b/osu.Game/Updater/UpdateManager.cs
index 61775a26b7..f772c6d282 100644
--- a/osu.Game/Updater/UpdateManager.cs
+++ b/osu.Game/Updater/UpdateManager.cs
@@ -57,25 +57,31 @@ namespace osu.Game.Updater
private readonly object updateTaskLock = new object();
- private Task updateCheckTask;
+ private Task updateCheckTask;
- public async Task CheckForUpdateAsync()
+ public async Task CheckForUpdateAsync()
{
if (!CanCheckForUpdate)
- return;
+ return false;
- Task waitTask;
+ Task waitTask;
lock (updateTaskLock)
waitTask = (updateCheckTask ??= PerformUpdateCheck());
- await waitTask;
+ bool hasUpdates = await waitTask;
lock (updateTaskLock)
updateCheckTask = null;
+
+ return hasUpdates;
}
- protected virtual Task PerformUpdateCheck() => Task.CompletedTask;
+ ///
+ /// Performs an asynchronous check for application updates.
+ ///
+ /// Whether any update is waiting. May return true if an error occured (there is potentially an update available).
+ protected virtual Task PerformUpdateCheck() => Task.FromResult(false);
private class UpdateCompleteNotification : SimpleNotification
{