Add the ability to cancel installs in Playnite

media
Pat Hartl 2023-09-16 15:13:55 -05:00
parent e00aa069fa
commit b32451d216
3 changed files with 74 additions and 21 deletions

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LANCommander.PlaynitePlugin
{
internal class ExtractionResult
{
public bool Success { get; set; }
public bool Canceled { get; set; }
public string Directory { get; set; }
}
}

View File

@ -47,21 +47,23 @@ namespace LANCommander.PlaynitePlugin
Logger.Trace($"Installing game {game.Title} ({game.Id})..."); Logger.Trace($"Installing game {game.Title} ({game.Id})...");
var installDirectory = RetryHelper.RetryOnException(10, TimeSpan.FromMilliseconds(500), "", () => var result = RetryHelper.RetryOnException<ExtractionResult>(10, TimeSpan.FromMilliseconds(500), new ExtractionResult(), () =>
{ {
Logger.Trace("Attempting to download and extract game..."); Logger.Trace("Attempting to download and extract game...");
return DownloadAndExtract(game); return DownloadAndExtract(game);
}); });
if (installDirectory == "") if (!result.Success && !result.Canceled)
throw new Exception("Could not extract the install archive. Retry the install or check your connection."); throw new Exception("Could not extract the install archive. Retry the install or check your connection.");
else if (result.Canceled)
throw new Exception("Install was canceled");
var installInfo = new GameInstallationData() var installInfo = new GameInstallationData()
{ {
InstallDirectory = installDirectory InstallDirectory = result.Directory
}; };
PlayniteGame.InstallDirectory = installDirectory; PlayniteGame.InstallDirectory = result.Directory;
SDK.GameManifest manifest = null; SDK.GameManifest manifest = null;
@ -71,7 +73,7 @@ namespace LANCommander.PlaynitePlugin
manifest = Plugin.LANCommander.GetGameManifest(gameId); manifest = Plugin.LANCommander.GetGameManifest(gameId);
WriteManifest(manifest, installDirectory); WriteManifest(manifest, result.Directory);
return true; return true;
}); });
@ -81,10 +83,10 @@ namespace LANCommander.PlaynitePlugin
Logger.Trace("Saving scripts..."); Logger.Trace("Saving scripts...");
SaveScript(game, installDirectory, ScriptType.Install); SaveScript(game, result.Directory, ScriptType.Install);
SaveScript(game, installDirectory, ScriptType.Uninstall); SaveScript(game, result.Directory, ScriptType.Uninstall);
SaveScript(game, installDirectory, ScriptType.NameChange); SaveScript(game, result.Directory, ScriptType.NameChange);
SaveScript(game, installDirectory, ScriptType.KeyChange); SaveScript(game, result.Directory, ScriptType.KeyChange);
try try
{ {
@ -104,7 +106,7 @@ namespace LANCommander.PlaynitePlugin
InvokeOnInstalled(new GameInstalledEventArgs(installInfo)); InvokeOnInstalled(new GameInstalledEventArgs(installInfo));
} }
private string DownloadAndExtract(LANCommander.SDK.Models.Game game) private ExtractionResult DownloadAndExtract(LANCommander.SDK.Models.Game game)
{ {
if (game == null) if (game == null)
{ {
@ -116,8 +118,7 @@ namespace LANCommander.PlaynitePlugin
var destination = Path.Combine(Plugin.Settings.InstallDirectory, game.Title.SanitizeFilename()); var destination = Path.Combine(Plugin.Settings.InstallDirectory, game.Title.SanitizeFilename());
Logger.Trace($"Downloading and extracting \"{game.Title}\" to path {destination}"); Logger.Trace($"Downloading and extracting \"{game.Title}\" to path {destination}");
var result = Plugin.PlayniteApi.Dialogs.ActivateGlobalProgress(progress =>
Plugin.PlayniteApi.Dialogs.ActivateGlobalProgress(progress =>
{ {
try try
{ {
@ -135,6 +136,18 @@ namespace LANCommander.PlaynitePlugin
progress.CurrentProgressValue = pos; progress.CurrentProgressValue = pos;
}; };
reader.EntryExtractionProgress += (object sender, ReaderExtractionEventArgs<IEntry> e) =>
{
if (progress.CancelToken != null && progress.CancelToken.IsCancellationRequested)
{
reader.Cancel();
progress.IsIndeterminate = true;
reader.Dispose();
gameStream.Dispose();
}
};
reader.WriteAllToDirectory(destination, new ExtractionOptions() reader.WriteAllToDirectory(destination, new ExtractionOptions()
{ {
ExtractFullPath = true, ExtractFullPath = true,
@ -143,6 +156,19 @@ namespace LANCommander.PlaynitePlugin
} }
} }
catch (Exception ex) catch (Exception ex)
{
if (progress.CancelToken != null && progress.CancelToken.IsCancellationRequested)
{
Logger.Trace("User cancelled the download");
if (Directory.Exists(destination))
{
Logger.Trace("Cleaning up orphaned install files after cancelled install...");
Directory.Delete(destination, true);
}
}
else
{ {
Logger.Error(ex, $"Could not extract to path {destination}"); Logger.Error(ex, $"Could not extract to path {destination}");
@ -155,16 +181,27 @@ namespace LANCommander.PlaynitePlugin
throw new Exception("The game archive could not be extracted. Please try again or fix the archive!"); throw new Exception("The game archive could not be extracted. Please try again or fix the archive!");
} }
}
}, },
new GlobalProgressOptions($"Downloading {game.Title}...") new GlobalProgressOptions($"Downloading {game.Title}...")
{ {
IsIndeterminate = false, IsIndeterminate = false,
Cancelable = false, Cancelable = true,
}); });
Logger.Trace($"Game successfully downloaded and extracted to {destination}"); var extractionResult = new ExtractionResult
{
Canceled = result.Canceled
};
return destination; if (!result.Canceled)
{
extractionResult.Success = true;
extractionResult.Directory = destination;
Logger.Trace($"Game successfully downloaded and extracted to {destination}");
}
return extractionResult;
} }
private string Download(LANCommander.SDK.Models.Game game) private string Download(LANCommander.SDK.Models.Game game)

View File

@ -96,6 +96,7 @@
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ExtractionResult.cs" />
<Compile Include="TrackableStream.cs" /> <Compile Include="TrackableStream.cs" />
<Compile Include="Extensions\MultiplayerInfoExtensions.cs" /> <Compile Include="Extensions\MultiplayerInfoExtensions.cs" />
<Compile Include="Helpers\RetryHelper.cs" /> <Compile Include="Helpers\RetryHelper.cs" />