Add "Package" button to archive page w/ dialog
This commit is contained in:
parent
81639e9fc2
commit
52dd3f23ba
12 changed files with 443 additions and 84 deletions
|
|
@ -184,6 +184,14 @@ namespace LANCommander.SDK.PowerShell
|
|||
{
|
||||
runspace.Open();
|
||||
|
||||
// Ensure TLS 1.2 is available for web requests (GitHub, etc.)
|
||||
using (var tls = System.Management.Automation.PowerShell.Create())
|
||||
{
|
||||
tls.Runspace = runspace;
|
||||
tls.AddScript("[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12");
|
||||
tls.Invoke();
|
||||
}
|
||||
|
||||
runspace.SessionStateProxy.Path.SetLocation(WorkingDirectory);
|
||||
|
||||
foreach (var variable in Variables)
|
||||
|
|
@ -218,6 +226,12 @@ namespace LANCommander.SDK.PowerShell
|
|||
Context.AddScript("Write-Host $Logo");
|
||||
Context.AddScript(Contents);
|
||||
|
||||
Context.Streams.Information.DataAdded += Information_DataAdded;
|
||||
Context.Streams.Verbose.DataAdded += Verbose_DataAdded;
|
||||
Context.Streams.Debug.DataAdded += Debug_DataAdded;
|
||||
Context.Streams.Warning.DataAdded += Warning_DataAdded;
|
||||
Context.Streams.Error.DataAdded += Error_DataAdded;
|
||||
|
||||
if (Debug) {
|
||||
Context.AddScript("Write-Host '--------- DEBUG ---------'");
|
||||
Context.AddScript("Write-Host \"Script Type: $ScriptType\"");
|
||||
|
|
@ -231,37 +245,41 @@ namespace LANCommander.SDK.PowerShell
|
|||
|
||||
Context.AddScript("Write-Host ''");
|
||||
Context.AddScript("Write-Host 'Enter \"exit\" to continue'");
|
||||
|
||||
Context.Streams.Information.DataAdded += Information_DataAdded;
|
||||
Context.Streams.Verbose.DataAdded += Verbose_DataAdded;
|
||||
Context.Streams.Debug.DataAdded += Debug_DataAdded;
|
||||
Context.Streams.Warning.DataAdded += Warning_DataAdded;
|
||||
Context.Streams.Error.DataAdded += Error_DataAdded;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var results = await Context.InvokeAsync();
|
||||
|
||||
await DebugAsync(async dbg =>
|
||||
{
|
||||
await dbg.BreakAsync(DebugContext);
|
||||
});
|
||||
|
||||
if (Context.HadErrors)
|
||||
{
|
||||
foreach (var error in Context.Streams.Error)
|
||||
{
|
||||
Logger.LogError("Script error: {InvocationName} : {ErrorMessage}", error.InvocationInfo?.InvocationName, error.Exception?.Message);
|
||||
|
||||
await DebugAsync(async dbg =>
|
||||
{
|
||||
await dbg.OutputAsync(DebugContext, LogLevel.Error, "{InvocationName} : {ErrorMessage}", error.InvocationInfo?.InvocationName, error.Exception?.Message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
var returnValue = Context.Runspace.SessionStateProxy.PSVariable.GetValue("Return");
|
||||
|
||||
if (returnValue == null && results != null && results.Count > 0)
|
||||
returnValue = results[results.Count - 1];
|
||||
|
||||
if (returnValue != null)
|
||||
result = (T)returnValue;
|
||||
{
|
||||
result = ConvertResult<T>(returnValue);
|
||||
|
||||
if (result == null)
|
||||
Logger.LogWarning("Script returned a value but it could not be converted to {ExpectedType}", typeof(T).Name);
|
||||
}
|
||||
else
|
||||
Logger.LogWarning("Script did not set $Return variable");
|
||||
{
|
||||
Logger.LogWarning("Script did not return a value via $Return or the pipeline");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -273,7 +291,15 @@ namespace LANCommander.SDK.PowerShell
|
|||
{
|
||||
await dbg.EndAsync(DebugContext);
|
||||
});
|
||||
|
||||
|
||||
if (Debug)
|
||||
{
|
||||
await DebugAsync(async dbg =>
|
||||
{
|
||||
await dbg.BreakAsync(DebugContext);
|
||||
});
|
||||
}
|
||||
|
||||
Context.Dispose();
|
||||
}
|
||||
}
|
||||
|
|
@ -283,11 +309,58 @@ namespace LANCommander.SDK.PowerShell
|
|||
return result;
|
||||
}
|
||||
|
||||
private static T ConvertResult<T>(object value)
|
||||
{
|
||||
// Unwrap PSObject wrapper
|
||||
var psObj = value as PSObject;
|
||||
var raw = psObj?.BaseObject ?? value;
|
||||
|
||||
// Direct cast if the underlying object is already the right type
|
||||
if (raw is T typed)
|
||||
return typed;
|
||||
|
||||
// Map PSObject properties onto a new instance of T by name
|
||||
if (psObj != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var instance = Activator.CreateInstance<T>();
|
||||
var targetProps = typeof(T).GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
|
||||
|
||||
foreach (var targetProp in targetProps)
|
||||
{
|
||||
if (!targetProp.CanWrite)
|
||||
continue;
|
||||
|
||||
var psProp = psObj.Properties[targetProp.Name];
|
||||
|
||||
if (psProp == null)
|
||||
continue;
|
||||
|
||||
var psValue = psProp.Value;
|
||||
|
||||
if (psValue is PSObject psValObj)
|
||||
psValue = psValObj.BaseObject;
|
||||
|
||||
if (psValue != null && targetProp.PropertyType.IsAssignableFrom(psValue.GetType()))
|
||||
targetProp.SetValue(instance, psValue);
|
||||
else if (psValue != null)
|
||||
targetProp.SetValue(instance, Convert.ChangeType(psValue, targetProp.PropertyType));
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
private async Task DebugAsync(Func<IScriptDebugger, Task> action)
|
||||
{
|
||||
if (!Debug)
|
||||
return;
|
||||
|
||||
if (Debuggers == null)
|
||||
Debuggers = ServiceProvider.GetServices<IScriptDebugger>();
|
||||
|
||||
|
|
|
|||
|
|
@ -281,14 +281,16 @@ namespace LANCommander.Server.Services
|
|||
|
||||
if (package == null)
|
||||
{
|
||||
logger?.LogError("Could not package game {GameTitle}, the package script did not return a result", game.Title);
|
||||
continue;
|
||||
var message = $"Could not package game {game.Title}, the package script did not return a result";
|
||||
logger?.LogError(message);
|
||||
throw new Exception(message);
|
||||
}
|
||||
|
||||
if (String.IsNullOrWhiteSpace(package.Path) || !Directory.Exists(package.Path))
|
||||
{
|
||||
logger?.LogError("Could not package game {GameTitle}, the path {Path} could not be found", game.Title, package.Path);
|
||||
continue;
|
||||
var message = $"Could not package game {game.Title}, the path {package.Path} could not be found";
|
||||
logger?.LogError(message);
|
||||
throw new Exception(message);
|
||||
}
|
||||
|
||||
var archive = new Archive
|
||||
|
|
@ -305,13 +307,17 @@ namespace LANCommander.Server.Services
|
|||
var destination = await archiveService.GetArchiveFileLocationAsync(archive);
|
||||
|
||||
ZipFile.CreateFromDirectory(package.Path, destination);
|
||||
|
||||
|
||||
await archiveService.RecalculateFileSizeArchiveAsync(archive);
|
||||
|
||||
logger?.LogInformation("Successfully packaged {GameTitle} and created new archive with version number {GameVersion}", game.Title, archive.Version);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger?.LogWarning("Could not package game {GameTitle}, no packaging scripts are defined", game.Title);
|
||||
var message = $"Could not package game {game.Title}, no packaging scripts are defined";
|
||||
logger?.LogWarning(message);
|
||||
throw new Exception(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,16 +92,16 @@ namespace LANCommander.Server.Services
|
|||
|
||||
if (package == null)
|
||||
{
|
||||
logger?.LogError("Could not package redistributable {RedistributableName}, the package script did not return a result", redistributable.Name);
|
||||
continue;
|
||||
var message = $"Could not package redistributable {redistributable.Name}, the package script did not return a result";
|
||||
logger?.LogError(message);
|
||||
throw new Exception(message);
|
||||
}
|
||||
|
||||
if (String.IsNullOrWhiteSpace(package.Path) || !Directory.Exists(package.Path))
|
||||
{
|
||||
logger?.LogError(
|
||||
"Could not package redistributable {RedistributableName}, the path {Path} could not be found",
|
||||
redistributable.Name, package.Path);
|
||||
continue;
|
||||
var message = $"Could not package redistributable {redistributable.Name}, the path {package.Path} could not be found";
|
||||
logger?.LogError(message);
|
||||
throw new Exception(message);
|
||||
}
|
||||
|
||||
var archive = new Archive
|
||||
|
|
@ -118,13 +118,17 @@ namespace LANCommander.Server.Services
|
|||
var destination = await archiveService.GetArchiveFileLocationAsync(archive);
|
||||
|
||||
ZipFile.CreateFromDirectory(package.Path, destination);
|
||||
|
||||
logger?.LogInformation("Successfully packaged {RedistributableName} and create new archive with version number {RedistributableVersion}", redistributable.Name, archive.Version);
|
||||
|
||||
await archiveService.RecalculateFileSizeArchiveAsync(archive);
|
||||
|
||||
logger?.LogInformation("Successfully packaged {RedistributableName} and created new archive with version number {RedistributableVersion}", redistributable.Name, archive.Version);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger?.LogWarning("Could not package redistributable {RedistributableName}, no packaging scripts are defined", redistributable.Name);
|
||||
var message = $"Could not package redistributable {redistributable.Name}, no packaging scripts are defined";
|
||||
logger?.LogWarning(message);
|
||||
throw new Exception(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,16 +92,16 @@ namespace LANCommander.Server.Services
|
|||
|
||||
if (package == null)
|
||||
{
|
||||
logger?.LogError("Could not package tool {ToolName}, the package script did not return a result", tool.Name);
|
||||
continue;
|
||||
var message = $"Could not package tool {tool.Name}, the package script did not return a result";
|
||||
logger?.LogError(message);
|
||||
throw new Exception(message);
|
||||
}
|
||||
|
||||
if (String.IsNullOrWhiteSpace(package.Path) || !Directory.Exists(package.Path))
|
||||
{
|
||||
logger?.LogError(
|
||||
"Could not package tool {ToolName}, the path {Path} could not be found",
|
||||
tool.Name, package.Path);
|
||||
continue;
|
||||
var message = $"Could not package tool {tool.Name}, the path {package.Path} could not be found";
|
||||
logger?.LogError(message);
|
||||
throw new Exception(message);
|
||||
}
|
||||
|
||||
var archive = new Archive
|
||||
|
|
@ -118,13 +118,17 @@ namespace LANCommander.Server.Services
|
|||
var destination = await archiveService.GetArchiveFileLocationAsync(archive);
|
||||
|
||||
ZipFile.CreateFromDirectory(package.Path, destination);
|
||||
|
||||
logger?.LogInformation("Successfully packaged {ToolName} and create new archive with version number {ToolVersion}", tool.Name, archive.Version);
|
||||
|
||||
await archiveService.RecalculateFileSizeArchiveAsync(archive);
|
||||
|
||||
logger?.LogInformation("Successfully packaged {ToolName} and created new archive with version number {ToolVersion}", tool.Name, archive.Version);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logger?.LogWarning("Could not package tool {ToolName}, no packaging scripts are defined", tool.Name);
|
||||
var message = $"Could not package tool {tool.Name}, no packaging scripts are defined";
|
||||
logger?.LogWarning(message);
|
||||
throw new Exception(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
8
LANCommander.Server/Models/PackagingDialogOptions.cs
Normal file
8
LANCommander.Server/Models/PackagingDialogOptions.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
namespace LANCommander.Server.Models;
|
||||
|
||||
public class PackagingDialogOptions
|
||||
{
|
||||
public Guid GameId { get; set; }
|
||||
public Guid ToolId { get; set; }
|
||||
public Guid RedistributableId { get; set; }
|
||||
}
|
||||
16
LANCommander.Server/Styles/_packaging-dialog.scss
Normal file
16
LANCommander.Server/Styles/_packaging-dialog.scss
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
.packaging-dialog {
|
||||
.ant-result {
|
||||
padding: 24px 16px;
|
||||
}
|
||||
}
|
||||
|
||||
.packaging-terminal {
|
||||
border-radius: 4px;
|
||||
overflow: hidden;
|
||||
min-height: 300px;
|
||||
background: #1e1e1e;
|
||||
|
||||
.xterm {
|
||||
padding: 8px;
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@
|
|||
@use '_mobile';
|
||||
@use '_tree';
|
||||
@use '_file-picker';
|
||||
@use '_packaging-dialog';
|
||||
|
||||
// Fix Blazor rejoin dialog font color being white, force to black
|
||||
// see: https://github.com/dotnet/aspnetcore/issues/57453
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
@inject ArchiveService ArchiveService
|
||||
@inject ScriptService ScriptService
|
||||
@inject GameService GameService
|
||||
@inject ToolService ToolService
|
||||
@inject RedistributableService RedistributableService
|
||||
@inject HttpClient HttpClient
|
||||
@inject NavigationManager Navigator
|
||||
@inject ModalService ModalService
|
||||
|
|
@ -13,6 +17,10 @@
|
|||
Responsive
|
||||
Query="a => (GameId != Guid.Empty && a.GameId == GameId) || (RedistributableId != Guid.Empty && a.RedistributableId == RedistributableId) || (ToolId != Guid.Empty && a.ToolId == ToolId)">
|
||||
<RightToolbar>
|
||||
@if (_hasPackageScript)
|
||||
{
|
||||
<Button OnClick="Package" Loading="_packaging">Package</Button>
|
||||
}
|
||||
<Button OnClick="RecalculateFileSizes" Type="@ButtonType.Default">Recalculate File Sizes</Button>
|
||||
<Button OnClick="UploadArchive" Type="@ButtonType.Primary">Upload Archive</Button>
|
||||
</RightToolbar>
|
||||
|
|
@ -65,10 +73,74 @@
|
|||
ArchiveUploader _uploader;
|
||||
|
||||
bool _browsing;
|
||||
bool _packaging;
|
||||
bool _hasPackageScript;
|
||||
|
||||
protected override void OnInitialized()
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
HttpClient.BaseAddress = new Uri(Navigator.BaseUri);
|
||||
|
||||
if (GameId != Guid.Empty)
|
||||
_hasPackageScript = (await ScriptService.GetAsync(s => s.GameId == GameId && s.Type == SDK.Enums.ScriptType.Package)).Any();
|
||||
else if (RedistributableId != Guid.Empty)
|
||||
_hasPackageScript = (await ScriptService.GetAsync(s => s.RedistributableId == RedistributableId && s.Type == SDK.Enums.ScriptType.Package)).Any();
|
||||
else if (ToolId != Guid.Empty)
|
||||
_hasPackageScript = (await ScriptService.GetAsync(s => s.ToolId == ToolId && s.Type == SDK.Enums.ScriptType.Package)).Any();
|
||||
}
|
||||
|
||||
private async Task Package()
|
||||
{
|
||||
_packaging = true;
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
await Task.Yield();
|
||||
|
||||
string title = "Package";
|
||||
|
||||
if (GameId != Guid.Empty)
|
||||
{
|
||||
var game = await GameService.GetAsync(GameId);
|
||||
title = $"Package {game.Title}";
|
||||
}
|
||||
else if (ToolId != Guid.Empty)
|
||||
{
|
||||
var tool = await ToolService.GetAsync(ToolId);
|
||||
title = $"Package {tool.Name}";
|
||||
}
|
||||
else if (RedistributableId != Guid.Empty)
|
||||
{
|
||||
var redistributable = await RedistributableService.GetAsync(RedistributableId);
|
||||
title = $"Package {redistributable.Name}";
|
||||
}
|
||||
|
||||
var modalOptions = new ModalOptions()
|
||||
{
|
||||
Title = title,
|
||||
Maximizable = true,
|
||||
DefaultMaximized = false,
|
||||
Closable = true,
|
||||
Footer = null,
|
||||
Width = 800,
|
||||
};
|
||||
|
||||
var options = new PackagingDialogOptions
|
||||
{
|
||||
GameId = GameId,
|
||||
ToolId = ToolId,
|
||||
RedistributableId = RedistributableId,
|
||||
};
|
||||
|
||||
var modalRef = await ModalService.CreateModalAsync<PackagingDialog, PackagingDialogOptions>(modalOptions, options);
|
||||
|
||||
modalRef.OnCancel = async () =>
|
||||
{
|
||||
await _table.ReloadAsync();
|
||||
};
|
||||
|
||||
_packaging = false;
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
private async Task RecalculateFileSizes()
|
||||
|
|
|
|||
217
LANCommander.Server/UI/Components/PackagingDialog.razor
Normal file
217
LANCommander.Server/UI/Components/PackagingDialog.razor
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
@using LANCommander.SDK.PowerShell
|
||||
@using LANCommander.Server.Services.PowerShell
|
||||
@using XtermBlazor
|
||||
@using LogLevel = Microsoft.Extensions.Logging.LogLevel
|
||||
@inherits FeedbackComponent<PackagingDialogOptions>
|
||||
@inject ScriptDebugger ScriptDebugger
|
||||
@inject GameService GameService
|
||||
@inject ToolService ToolService
|
||||
@inject RedistributableService RedistributableService
|
||||
@inject ILogger<PackagingDialog> Logger
|
||||
@implements IDisposable
|
||||
|
||||
<div class="packaging-dialog">
|
||||
@if (_status == PackagingStatus.Complete)
|
||||
{
|
||||
<Result Status="ResultStatus.Success"
|
||||
Title="Packaging Complete"
|
||||
SubTitle="@($"Completed in {FormatTimeSpan(_elapsed)}")">
|
||||
</Result>
|
||||
}
|
||||
else if (_status == PackagingStatus.Failed)
|
||||
{
|
||||
<Result Status="ResultStatus.Error"
|
||||
Title="Packaging Failed"
|
||||
SubTitle="@(_errorMessage ?? "The packaging script encountered an error.")">
|
||||
</Result>
|
||||
}
|
||||
else if (_status == PackagingStatus.Stopped)
|
||||
{
|
||||
<Result Status="ResultStatus.Warning"
|
||||
Title="Packaging Stopped"
|
||||
SubTitle="The packaging script was stopped by the user.">
|
||||
</Result>
|
||||
}
|
||||
|
||||
<div class="packaging-terminal">
|
||||
@if (_status == PackagingStatus.Running)
|
||||
{
|
||||
<Flex Justify="FlexJustify.SpaceBetween">
|
||||
<span>@FormatElapsed()</span>
|
||||
|
||||
<Tooltip Title="Stop">
|
||||
<Button Type="ButtonType.Text" Icon="@IconType.Outline.Stop"/>
|
||||
</Tooltip>
|
||||
</Flex>
|
||||
}
|
||||
|
||||
<Terminal @ref="_terminal" Id="@_id.ToString()" Options="_terminalOptions" OnFirstRender="OnTerminalReady" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
enum PackagingStatus { Running, Complete, Failed, Stopped }
|
||||
|
||||
Guid _id = Guid.NewGuid();
|
||||
Terminal? _terminal;
|
||||
CancellationTokenSource? _cts;
|
||||
DateTime? _startTime;
|
||||
TimeSpan _elapsed;
|
||||
System.Threading.Timer? _elapsedTimer;
|
||||
|
||||
PackagingStatus _status = PackagingStatus.Running;
|
||||
bool _hasErrors;
|
||||
string? _errorMessage;
|
||||
|
||||
readonly TerminalOptions _terminalOptions = new()
|
||||
{
|
||||
CursorBlink = false,
|
||||
CursorStyle = CursorStyle.Bar,
|
||||
};
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
_status = PackagingStatus.Running;
|
||||
_hasErrors = false;
|
||||
_errorMessage = null;
|
||||
|
||||
ScriptDebugger.OnStart = Start;
|
||||
ScriptDebugger.OnEnd = End;
|
||||
ScriptDebugger.OnOutput = Output;
|
||||
ScriptDebugger.OnBreak = null;
|
||||
|
||||
_cts?.Dispose();
|
||||
_cts = new CancellationTokenSource();
|
||||
_startTime = DateTime.UtcNow;
|
||||
|
||||
_elapsedTimer = new System.Threading.Timer(
|
||||
_ => InvokeAsync(StateHasChanged),
|
||||
null,
|
||||
TimeSpan.Zero,
|
||||
TimeSpan.FromSeconds(1));
|
||||
}
|
||||
|
||||
async Task OnTerminalReady()
|
||||
{
|
||||
if (_terminal != null)
|
||||
await _terminal.FitAsync();
|
||||
|
||||
await RunAsync();
|
||||
}
|
||||
|
||||
async Task RunAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Options.GameId != Guid.Empty)
|
||||
await GameService.PackageAsync(Options.GameId);
|
||||
else if (Options.ToolId != Guid.Empty)
|
||||
await ToolService.PackageAsync(Options.ToolId);
|
||||
else if (Options.RedistributableId != Guid.Empty)
|
||||
await RedistributableService.PackageAsync(Options.RedistributableId);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_hasErrors = true;
|
||||
_errorMessage = ex.Message;
|
||||
Logger.LogError(ex, "Packaging failed with an exception");
|
||||
|
||||
if (_terminal != null)
|
||||
await _terminal.WriteLine(ex.Message, LogLevel.Error);
|
||||
|
||||
StopTimer();
|
||||
_elapsed = _startTime.HasValue ? DateTime.UtcNow - _startTime.Value : TimeSpan.Zero;
|
||||
_status = PackagingStatus.Failed;
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
async Task Start(IScriptDebugContext context)
|
||||
{
|
||||
if (_terminal == null)
|
||||
return;
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
async Task End(IScriptDebugContext context)
|
||||
{
|
||||
StopTimer();
|
||||
|
||||
_elapsed = _startTime.HasValue ? DateTime.UtcNow - _startTime.Value : TimeSpan.Zero;
|
||||
|
||||
if (_terminal != null)
|
||||
await _terminal.WriteLine($"\nCompleted in {FormatTimeSpan(_elapsed)}", LogLevel.Information);
|
||||
|
||||
_status = _hasErrors ? PackagingStatus.Failed : PackagingStatus.Complete;
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
async Task Output(IScriptDebugContext context, LogLevel level, string message)
|
||||
{
|
||||
if (_terminal == null)
|
||||
return;
|
||||
|
||||
if (level == LogLevel.Error)
|
||||
{
|
||||
_hasErrors = true;
|
||||
_errorMessage ??= message;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await _terminal.WriteLine(message, level);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
async Task Stop()
|
||||
{
|
||||
_cts?.Cancel();
|
||||
StopTimer();
|
||||
|
||||
_elapsed = _startTime.HasValue ? DateTime.UtcNow - _startTime.Value : TimeSpan.Zero;
|
||||
|
||||
if (_terminal != null)
|
||||
await _terminal.WriteLine("\nScript stopped by user.", LogLevel.Warning);
|
||||
|
||||
_status = PackagingStatus.Stopped;
|
||||
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
void StopTimer()
|
||||
{
|
||||
_elapsedTimer?.Dispose();
|
||||
_elapsedTimer = null;
|
||||
}
|
||||
|
||||
string FormatElapsed()
|
||||
{
|
||||
if (!_startTime.HasValue)
|
||||
return "";
|
||||
|
||||
var elapsed = DateTime.UtcNow - _startTime.Value;
|
||||
|
||||
return FormatTimeSpan(elapsed);
|
||||
}
|
||||
|
||||
static string FormatTimeSpan(TimeSpan ts)
|
||||
{
|
||||
if (ts.TotalHours >= 1)
|
||||
return ts.ToString(@"h\:mm\:ss");
|
||||
|
||||
return ts.ToString(@"m\:ss");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_cts?.Cancel();
|
||||
_cts?.Dispose();
|
||||
StopTimer();
|
||||
}
|
||||
}
|
||||
|
|
@ -27,11 +27,6 @@
|
|||
</TitleTemplate>
|
||||
<TitleExtraTemplate>
|
||||
<Flex Gap="FlexGap.Small" Justify="FlexJustify.End">
|
||||
@if (context != null && (context.Scripts?.Any(s => s.Type == ScriptType.Package) ?? false))
|
||||
{
|
||||
<Button OnClick="Package" Loading="_packaging">Package</Button>
|
||||
}
|
||||
|
||||
@if (context != null && context.Id != Guid.Empty)
|
||||
{
|
||||
<Button OnClick="OpenExportDialog" Loading="_openingExportDialog">Export</Button>
|
||||
|
|
@ -172,7 +167,6 @@
|
|||
|
||||
bool _loaded;
|
||||
bool _success;
|
||||
bool _packaging;
|
||||
bool _openingExportDialog;
|
||||
|
||||
IEnumerable<Engine> Engines = new List<Engine>();
|
||||
|
|
@ -318,12 +312,4 @@
|
|||
await Task.Yield();
|
||||
}
|
||||
|
||||
private async Task Package()
|
||||
{
|
||||
_packaging = true;
|
||||
|
||||
await GameService.PackageAsync(Id);
|
||||
|
||||
_packaging = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,11 +21,6 @@
|
|||
</TitleTemplate>
|
||||
<TitleExtraTemplate>
|
||||
<Flex Gap="FlexGap.Small" Justify="FlexJustify.End">
|
||||
@if (context != null && (context.Scripts?.Any(s => s.Type == ScriptType.Package) ?? false))
|
||||
{
|
||||
<Button OnClick="Package" Loading="_packaging">Package</Button>
|
||||
}
|
||||
|
||||
@if (context != null && context.Id != Guid.Empty)
|
||||
{
|
||||
<Button OnClick="OpenExportDialog" Loading="_openingExportDialog">Export</Button>
|
||||
|
|
@ -71,7 +66,6 @@
|
|||
ICollection<Game> Games;
|
||||
RedistributableEditView EditView;
|
||||
|
||||
bool _packaging;
|
||||
bool _openingExportDialog;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
|
|
@ -117,13 +111,5 @@
|
|||
await InvokeAsync(StateHasChanged);
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
private async Task Package()
|
||||
{
|
||||
_packaging = true;
|
||||
|
||||
await RedistributableService.PackageAsync(Id);
|
||||
|
||||
_packaging = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -21,11 +21,6 @@
|
|||
</TitleTemplate>
|
||||
<TitleExtraTemplate>
|
||||
<Flex Gap="FlexGap.Small" Justify="FlexJustify.End">
|
||||
@if (context != null && (context.Scripts?.Any(s => s.Type == ScriptType.Package) ?? false))
|
||||
{
|
||||
<Button OnClick="Package" Loading="_packaging">Package</Button>
|
||||
}
|
||||
|
||||
@if (context != null && context.Id != Guid.Empty)
|
||||
{
|
||||
<Button OnClick="OpenExportDialog" Loading="_openingExportDialog">Export</Button>
|
||||
|
|
@ -71,7 +66,6 @@
|
|||
ICollection<Game> Games;
|
||||
ToolEditView EditView;
|
||||
|
||||
bool _packaging;
|
||||
bool _openingExportDialog;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
|
|
@ -117,13 +111,5 @@
|
|||
await InvokeAsync(StateHasChanged);
|
||||
await Task.Yield();
|
||||
}
|
||||
|
||||
private async Task Package()
|
||||
{
|
||||
_packaging = true;
|
||||
|
||||
await ToolService.PackageAsync(Id);
|
||||
|
||||
_packaging = false;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue