1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-30 08:42:55 +08:00
osu-lazer/osu.Desktop/Updater/SquirrelUpdateManager.cs

181 lines
6.2 KiB
C#
Raw Normal View History

// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
2018-04-13 17:19:50 +08:00
using System;
using System.Runtime.Versioning;
2018-07-06 15:39:27 +08:00
using System.Threading.Tasks;
2018-04-13 17:19:50 +08:00
using osu.Framework.Allocation;
using osu.Framework.Logging;
using osu.Game;
using osu.Game.Overlays;
using osu.Game.Overlays.Notifications;
using osu.Game.Screens.Play;
2018-04-13 17:19:50 +08:00
using Squirrel;
using Squirrel.SimpleSplat;
using LogLevel = Squirrel.SimpleSplat.LogLevel;
using UpdateManager = osu.Game.Updater.UpdateManager;
2018-04-13 17:19:50 +08:00
2018-07-06 15:39:27 +08:00
namespace osu.Desktop.Updater
2018-04-13 17:19:50 +08:00
{
[SupportedOSPlatform("windows")]
2022-11-24 13:32:20 +08:00
public partial class SquirrelUpdateManager : UpdateManager
2018-04-13 17:19:50 +08:00
{
private Squirrel.UpdateManager? updateManager;
private INotificationOverlay notificationOverlay = null!;
2018-04-13 17:19:50 +08:00
public Task PrepareUpdateAsync() => Squirrel.UpdateManager.RestartAppWhenExited();
2018-04-13 17:19:50 +08:00
private static readonly Logger logger = Logger.GetLogger("updater");
/// <summary>
/// Whether an update has been downloaded but not yet applied.
/// </summary>
private bool updatePending;
private readonly SquirrelLogger squirrelLogger = new SquirrelLogger();
[Resolved]
private OsuGameBase game { get; set; } = null!;
[Resolved]
private ILocalUserPlayInfo? localUserInfo { get; set; }
2018-04-13 17:19:50 +08:00
[BackgroundDependencyLoader]
private void load(INotificationOverlay notifications)
2018-04-13 17:19:50 +08:00
{
notificationOverlay = notifications;
2018-04-13 17:19:50 +08:00
SquirrelLocator.CurrentMutable.Register(() => squirrelLogger, typeof(ILogger));
2018-04-13 17:19:50 +08:00
}
protected override async Task<bool> PerformUpdateCheck() => await checkForUpdateAsync().ConfigureAwait(false);
2020-05-07 14:07:22 +08:00
private async Task<bool> checkForUpdateAsync(bool useDeltaPatching = true, UpdateProgressNotification? notification = null)
2018-04-13 17:19:50 +08:00
{
2020-05-05 09:31:11 +08:00
// should we schedule a retry on completion of this check?
bool scheduleRecheck = true;
2018-04-13 17:19:50 +08:00
const string? github_token = null; // TODO: populate.
2018-04-13 17:19:50 +08:00
try
{
// Avoid any kind of update checking while gameplay is running.
if (localUserInfo?.IsPlaying.Value == true)
return false;
updateManager ??= new GithubUpdateManager(@"https://github.com/ppy/osu", false, github_token, @"osulazer");
2018-04-13 17:19:50 +08:00
var info = await updateManager.CheckForUpdate(!useDeltaPatching).ConfigureAwait(false);
2018-04-13 17:19:50 +08:00
if (info.ReleasesToApply.Count == 0)
{
if (updatePending)
{
// the user may have dismissed the completion notice, so show it again.
notificationOverlay.Post(new UpdateApplicationCompleteNotification
{
Activated = () =>
{
restartToApplyUpdate();
return true;
},
});
return true;
}
2020-05-05 09:31:11 +08:00
// no updates available. bail and retry later.
return false;
}
2018-04-13 17:19:50 +08:00
scheduleRecheck = false;
2018-04-13 17:19:50 +08:00
if (notification == null)
{
notification = new UpdateProgressNotification
{
CompletionClickAction = restartToApplyUpdate,
};
2018-04-13 17:19:50 +08:00
Schedule(() => notificationOverlay.Post(notification));
}
notification.StartDownload();
2018-04-13 17:19:50 +08:00
try
{
await updateManager.DownloadReleases(info.ReleasesToApply, p => notification.Progress = p / 100f).ConfigureAwait(false);
2018-04-13 17:19:50 +08:00
notification.StartInstall();
2018-04-13 17:19:50 +08:00
await updateManager.ApplyReleases(info, p => notification.Progress = p / 100f).ConfigureAwait(false);
2018-04-13 17:19:50 +08:00
notification.State = ProgressNotificationState.Completed;
updatePending = true;
2018-04-13 17:19:50 +08:00
}
catch (Exception e)
{
if (useDeltaPatching)
{
logger.Add(@"delta patching failed; will attempt full download!");
2018-04-13 17:19:50 +08:00
2020-05-05 09:31:11 +08:00
// could fail if deltas are unavailable for full update path (https://github.com/Squirrel/Squirrel.Windows/issues/959)
// try again without deltas.
await checkForUpdateAsync(false, notification).ConfigureAwait(false);
2018-04-13 17:19:50 +08:00
}
else
{
// In the case of an error, a separate notification will be displayed.
notification.FailDownload();
2018-04-13 17:19:50 +08:00
Logger.Error(e, @"update failed!");
}
}
}
catch (Exception)
{
// we'll ignore this and retry later. can be triggered by no internet connection or thread abortion.
scheduleRecheck = true;
2018-04-13 17:19:50 +08:00
}
finally
{
if (scheduleRecheck)
2018-04-13 17:19:50 +08:00
{
2020-05-05 09:31:11 +08:00
// check again in 30 minutes.
Scheduler.AddDelayed(() => Task.Run(async () => await checkForUpdateAsync().ConfigureAwait(false)), 60000 * 30);
2018-04-13 17:19:50 +08:00
}
}
return true;
2018-04-13 17:19:50 +08:00
}
private bool restartToApplyUpdate()
{
PrepareUpdateAsync()
.ContinueWith(_ => Schedule(() => game.AttemptExit()));
return true;
}
protected override void Dispose(bool isDisposing)
2018-04-13 17:19:50 +08:00
{
base.Dispose(isDisposing);
updateManager?.Dispose();
2018-04-13 17:19:50 +08:00
}
private class SquirrelLogger : ILogger, IDisposable
{
public LogLevel Level { get; set; } = LogLevel.Info;
public void Write(string message, LogLevel logLevel)
{
if (logLevel < Level)
return;
2019-05-15 13:12:59 +08:00
logger.Add(message);
}
public void Dispose()
{
}
}
2018-04-13 17:19:50 +08:00
}
}