1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-15 15:12:57 +08:00

initial implementation

This commit is contained in:
smallketchup82 2024-06-26 15:25:41 -04:00
parent 87f2a23263
commit 0ee89183cc
No known key found for this signature in database
GPG Key ID: 7345B7C561243F1E
4 changed files with 38 additions and 123 deletions

View File

@ -19,7 +19,6 @@ using osu.Desktop.Windows;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Game.IO; using osu.Game.IO;
using osu.Game.IPC; using osu.Game.IPC;
using osu.Game.Online.Multiplayer;
using osu.Game.Performance; using osu.Game.Performance;
using osu.Game.Utils; using osu.Game.Utils;
using SDL; using SDL;
@ -103,35 +102,22 @@ namespace osu.Desktop
if (!string.IsNullOrEmpty(packageManaged)) if (!string.IsNullOrEmpty(packageManaged))
return new NoActionUpdateManager(); return new NoActionUpdateManager();
switch (RuntimeInfo.OS) return new VeloUpdateManager();
{
case RuntimeInfo.Platform.Windows:
Debug.Assert(OperatingSystem.IsWindows());
return new SquirrelUpdateManager();
default:
return new SimpleUpdateManager();
}
} }
public override bool RestartAppWhenExited() public override bool RestartAppWhenExited()
{ {
switch (RuntimeInfo.OS) try
{ {
case RuntimeInfo.Platform.Windows: Process.Start(Process.GetCurrentProcess().MainModule?.FileName ?? throw new InvalidOperationException());
Debug.Assert(OperatingSystem.IsWindows()); Environment.Exit(0);
return true;
// Of note, this is an async method in squirrel that adds an arbitrary delay before returning }
// likely to ensure the external process is in a good state. catch (Exception e)
// {
// We're not waiting on that here, but the outro playing before the actual exit should be enough Logger.Error(e, "Failed to restart application");
// to cover this. return base.RestartAppWhenExited();
Squirrel.UpdateManager.RestartAppWhenExited().FireAndForget();
return true;
} }
return base.RestartAppWhenExited();
} }
protected override void LoadComplete() protected override void LoadComplete()

View File

@ -3,7 +3,6 @@
using System; using System;
using System.IO; using System.IO;
using System.Runtime.Versioning;
using osu.Desktop.LegacyIpc; using osu.Desktop.LegacyIpc;
using osu.Desktop.Windows; using osu.Desktop.Windows;
using osu.Framework; using osu.Framework;
@ -14,7 +13,7 @@ using osu.Game;
using osu.Game.IPC; using osu.Game.IPC;
using osu.Game.Tournament; using osu.Game.Tournament;
using SDL; using SDL;
using Squirrel; using Velopack;
namespace osu.Desktop namespace osu.Desktop
{ {
@ -66,10 +65,10 @@ namespace osu.Desktop
return; return;
} }
} }
setupSquirrel();
} }
setupVelo();
// NVIDIA profiles are based on the executable name of a process. // NVIDIA profiles are based on the executable name of a process.
// Lazer and stable share the same executable name. // Lazer and stable share the same executable name.
// Stable sets this setting to "Off", which may not be what we want, so let's force it back to the default "Auto" on startup. // Stable sets this setting to "Off", which may not be what we want, so let's force it back to the default "Auto" on startup.
@ -177,32 +176,14 @@ namespace osu.Desktop
return false; return false;
} }
[SupportedOSPlatform("windows")] private static void setupVelo()
private static void setupSquirrel()
{ {
SquirrelAwareApp.HandleEvents(onInitialInstall: (_, tools) => VelopackApp
{ .Build()
tools.CreateShortcutForThisExe(); .WithFirstRun(v =>
tools.CreateUninstallerRegistryEntry(); {
WindowsAssociationManager.InstallAssociations(); if (OperatingSystem.IsWindows()) WindowsAssociationManager.InstallAssociations();
}, onAppUpdate: (_, tools) => }).Run();
{
tools.CreateUninstallerRegistryEntry();
WindowsAssociationManager.UpdateAssociations();
}, onAppUninstall: (_, tools) =>
{
tools.RemoveShortcutForThisExe();
tools.RemoveUninstallerRegistryEntry();
WindowsAssociationManager.UninstallAssociations();
}, onEveryRun: (_, _, _) =>
{
// While setting the `ProcessAppUserModelId` fixes duplicate icons/shortcuts on the taskbar, it currently
// causes the right-click context menu to function incorrectly.
//
// This may turn out to be non-required after an alternative solution is implemented.
// see https://github.com/clowd/Clowd.Squirrel/issues/24
// tools.SetProcessAppUserModelId();
});
} }
} }
} }

View File

@ -2,7 +2,6 @@
// See the LICENCE file in the repository root for full licence text. // See the LICENCE file in the repository root for full licence text.
using System; using System;
using System.Runtime.Versioning;
using System.Threading.Tasks; using System.Threading.Tasks;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Logging; using osu.Framework.Logging;
@ -10,30 +9,15 @@ using osu.Game;
using osu.Game.Overlays; using osu.Game.Overlays;
using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Notifications;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
using Squirrel.SimpleSplat; using osu.Game.Updater;
using Squirrel.Sources;
using LogLevel = Squirrel.SimpleSplat.LogLevel;
using UpdateManager = osu.Game.Updater.UpdateManager;
namespace osu.Desktop.Updater namespace osu.Desktop.Updater
{ {
[SupportedOSPlatform("windows")] public partial class VeloUpdateManager : UpdateManager
public partial class SquirrelUpdateManager : UpdateManager
{ {
private Squirrel.UpdateManager? updateManager; private Velopack.UpdateManager? updateManager;
private INotificationOverlay notificationOverlay = null!; private INotificationOverlay notificationOverlay = null!;
public Task PrepareUpdateAsync() => Squirrel.UpdateManager.RestartAppWhenExited();
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] [Resolved]
private OsuGameBase game { get; set; } = null!; private OsuGameBase game { get; set; } = null!;
@ -44,13 +28,11 @@ namespace osu.Desktop.Updater
private void load(INotificationOverlay notifications) private void load(INotificationOverlay notifications)
{ {
notificationOverlay = notifications; notificationOverlay = notifications;
SquirrelLocator.CurrentMutable.Register(() => squirrelLogger, typeof(ILogger));
} }
protected override async Task<bool> PerformUpdateCheck() => await checkForUpdateAsync().ConfigureAwait(false); protected override async Task<bool> PerformUpdateCheck() => await checkForUpdateAsync().ConfigureAwait(false);
private async Task<bool> checkForUpdateAsync(bool useDeltaPatching = true, UpdateProgressNotification? notification = null) private async Task<bool> checkForUpdateAsync(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;
@ -63,27 +45,27 @@ namespace osu.Desktop.Updater
if (localUserInfo?.IsPlaying.Value == true) if (localUserInfo?.IsPlaying.Value == true)
return false; return false;
updateManager ??= new Squirrel.UpdateManager(new GithubSource(@"https://github.com/ppy/osu", github_token, false), @"osulazer"); updateManager ??= new Velopack.UpdateManager(new Velopack.Sources.GithubSource(@"https://github.com/ppy/osu", github_token, false));
var info = await updateManager.CheckForUpdate(!useDeltaPatching).ConfigureAwait(false); var info = await updateManager.CheckForUpdatesAsync().ConfigureAwait(false);
if (info.ReleasesToApply.Count == 0) if (info == null)
{ {
if (updatePending) // If there is an update pending restart, show the notification again.
if (updateManager.IsUpdatePendingRestart)
{ {
// the user may have dismissed the completion notice, so show it again.
notificationOverlay.Post(new UpdateApplicationCompleteNotification notificationOverlay.Post(new UpdateApplicationCompleteNotification
{ {
Activated = () => Activated = () =>
{ {
restartToApplyUpdate(); restartToApplyUpdate();
return true; return true;
}, }
}); });
return true; return true;
} }
// no updates available. bail and retry later. // Otherwise there's no updates available. Bail and retry later.
return false; return false;
} }
@ -103,31 +85,17 @@ namespace osu.Desktop.Updater
try try
{ {
await updateManager.DownloadReleases(info.ReleasesToApply, p => notification.Progress = p / 100f).ConfigureAwait(false); await updateManager.DownloadUpdatesAsync(info, p => notification.Progress = p / 100f).ConfigureAwait(false);
notification.StartInstall(); notification.StartInstall();
await updateManager.ApplyReleases(info, p => notification.Progress = p / 100f).ConfigureAwait(false);
notification.State = ProgressNotificationState.Completed; notification.State = ProgressNotificationState.Completed;
updatePending = true;
} }
catch (Exception e) catch (Exception e)
{ {
if (useDeltaPatching)
{
logger.Add(@"delta patching failed; will attempt full download!");
// 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);
}
else
{
// In the case of an error, a separate notification will be displayed. // In the case of an error, a separate notification will be displayed.
notification.FailDownload(); notification.FailDownload();
Logger.Error(e, @"update failed!"); Logger.Error(e, @"update failed!");
}
} }
} }
catch (Exception) catch (Exception)
@ -149,32 +117,12 @@ namespace osu.Desktop.Updater
private bool restartToApplyUpdate() private bool restartToApplyUpdate()
{ {
PrepareUpdateAsync() if (updateManager == null)
.ContinueWith(_ => Schedule(() => game.AttemptExit())); return false;
updateManager.WaitExitThenApplyUpdates(null);
Schedule(() => game.AttemptExit());
return true; return true;
} }
protected override void Dispose(bool isDisposing)
{
base.Dispose(isDisposing);
updateManager?.Dispose();
}
private class SquirrelLogger : ILogger, IDisposable
{
public LogLevel Level { get; set; } = LogLevel.Info;
public void Write(string message, LogLevel logLevel)
{
if (logLevel < Level)
return;
logger.Add(message);
}
public void Dispose()
{
}
}
} }
} }

View File

@ -23,10 +23,10 @@
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" /> <ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Package References"> <ItemGroup Label="Package References">
<PackageReference Include="Clowd.Squirrel" Version="2.11.1" />
<PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" /> <PackageReference Include="Mono.Posix.NETStandard" Version="1.0.0" />
<PackageReference Include="System.IO.Packaging" Version="8.0.0" /> <PackageReference Include="System.IO.Packaging" Version="8.0.0" />
<PackageReference Include="DiscordRichPresence" Version="1.2.1.24" /> <PackageReference Include="DiscordRichPresence" Version="1.2.1.24" />
<PackageReference Include="Velopack" Version="0.0.359" />
</ItemGroup> </ItemGroup>
<ItemGroup Label="Resources"> <ItemGroup Label="Resources">
<EmbeddedResource Include="lazer.ico" /> <EmbeddedResource Include="lazer.ico" />