LANCommander/LANCommander.Launcher/UI/Components/LibraryItemContextMenu.razor
Pat Hartl f3708b4f3c Refactor redistributable installation
- Install now extracts the redistributable archive to the game's `.lancommander` directory, under a directory matching the redist's ID
- Scripts are downloaded and saved to the same location
- BeforeStart, AfterStop, and NameChange scripts are now available for redistributables
- Change manifest reading/writing to use async
2025-01-30 23:57:12 -06:00

336 lines
No EOL
9.2 KiB
Text

@using LANCommander.Launcher.Data.Models
@using LANCommander.Launcher.Models
@using System.Diagnostics
@using LANCommander.SDK
@using LANCommander.SDK.Helpers
@inject GameService GameService
@inject UserService UserService
@inject LibraryService LibraryService
@inject InstallService InstallService
@inject ModalService ModalService
@inject MessageBusService MessageBusService
@inject SDK.Client Client
@if (GameActions != null && GameActions.Count() > 0)
{
@foreach (var action in GameActions.OrderBy(a => a.SortOrder))
{
<MenuItem OnClick="() => Run(Game, action)">
@action.Name
</MenuItem>
}
<MenuDivider />
}
@if (Game.Installed)
{
if (Game.Media != null && Game.Media.Any(m => m.Type == SDK.Enums.MediaType.Manual))
{
foreach (var manual in Game.Media.Where(m => m.Type == SDK.Enums.MediaType.Manual))
{
<MenuItem OnClick="() => OpenManual(manual)">
@(String.IsNullOrWhiteSpace(manual.Name) ? "Manual" : manual.Name)
</MenuItem>
}
<MenuDivider />
}
<MenuItem OnClick="() => OpenSaveManager()">
Manage Saves
</MenuItem>
if (Settings.Games.InstallDirectories.Length > 1 || Game.DependentGames.Any(g => g.Type == Data.Enums.GameType.Expansion || g.Type == Data.Enums.GameType.Mod))
{
<MenuItem OnClick="() => Modify()">
Modify
</MenuItem>
}
<MenuItem OnClick="() => BrowseFiles()">
Browse Files
</MenuItem>
<MenuItem OnClick="() => ValidateFiles()">
Validate Files
</MenuItem>
<MenuItem OnClick="() => RemoveFromLibrary()">
Remove
</MenuItem>
<MenuItem OnClick="() => Uninstall()">
Uninstall
</MenuItem>
}
else
{
<MenuItem OnClick="() => Install()">
Install
</MenuItem>
<MenuItem OnClick="() => RemoveFromLibrary()">
Remove
</MenuItem>
}
@if (Settings.Debug.EnableScriptDebugging)
{
<MenuDivider />
<MenuItem OnClick="() => RunInstallScripts()">
Run Install Scripts
</MenuItem>
<MenuItem OnClick="() => RunUninstallScripts()">
Run Uninstall Scripts
</MenuItem>
<MenuItem OnClick="() => RunNameChangeScripts()">
Run Name Change Scripts
</MenuItem>
<MenuItem OnClick="() => RunKeyChangeScripts()">
Run Key Change Scripts
</MenuItem>
}
<MenuDivider />
<MenuItem OnClick="() => ReportIssue()">
Report Issue
</MenuItem>
@MenuExtra
@code {
[Parameter] public Models.ListItem Model { get; set; }
[Parameter] public RenderFragment MenuExtra { get; set; }
Data.Models.Game Game { get; set; }
IEnumerable<SDK.Models.Action> GameActions { get; set; }
Settings Settings;
protected override async Task OnInitializedAsync()
{
Settings = SettingService.GetSettings();
}
protected override async Task OnParametersSetAsync()
{
if (Model.DataItem is Game)
{
Game = Model.DataItem as Game;
GameActions = new List<SDK.Models.Action>();
if (Game.Installed)
{
var manifest = await ManifestHelper.ReadAsync<GameManifest>(Game.InstallDirectory, Game.Id);
if (manifest != null)
GameActions = manifest.Actions.Where(a => !a.IsPrimaryAction).ToList();
}
}
}
async Task Run(Game game, SDK.Models.Action action)
{
var task = GameService.Run(game, action);
await InvokeAsync(StateHasChanged);
await task;
}
async Task BrowseFiles()
{
Process.Start("explorer", Game.InstallDirectory);
}
async Task Install()
{
if (Settings.Games.InstallDirectories.Length > 1 || (Model.DataItem as Game).DependentGames.Any(g => g.Type == Data.Enums.GameType.Expansion || g.Type == Data.Enums.GameType.Mod))
{
var modalOptions = new ModalOptions()
{
Title = $"Install {Model.Name}",
Maximizable = false,
DefaultMaximized = false,
Closable = true,
Draggable = true,
Centered = true,
WrapClassName = "ant-modal-wrap-no-padding",
Footer = null,
};
var modalRef = ModalService.CreateModal<InstallDialog, Models.ListItem, string>(modalOptions, Model);
}
else
{
var game = Model.DataItem as Game;
await InstallService.Add(game);
}
}
async Task Modify()
{
var modalOptions = new ModalOptions()
{
Title = $"Modify {Model.Name}",
Maximizable = false,
DefaultMaximized = false,
Closable = true,
Draggable = true,
Centered = true,
WrapClassName = "ant-modal-wrap-no-padding",
Footer = null,
};
var modalRef = ModalService.CreateModal<InstallDialog, Models.ListItem, string>(modalOptions, Model);
}
async Task ValidateFiles()
{
var modalOptions = new ModalOptions()
{
Title = $"File Conflicts",
Maximizable = false,
DefaultMaximized = true,
Closable = true,
Draggable = true,
Centered = true,
OkText = "Replace Selected",
};
var modalRef = ModalService.CreateModal<ValidateFilesDialog, Game>(modalOptions, Model.DataItem as Game);
}
async Task Uninstall()
{
var manifest = await ManifestHelper.ReadAsync<GameManifest>(Game.InstallDirectory, Game.Id);
var message = $"Would you like to uninstall {Game.Title}?";
if (manifest.SavePaths != null && manifest.SavePaths.Any())
message += " Your save files have been uploaded to the server.";
else
message += " Your save files may be unrecoverable if they are contained within the game's install directory.";
var confirmed = await ModalService.ConfirmAsync(new ConfirmOptions
{
OkText = "Uninstall",
CancelText = "Cancel",
Title = "Uninstall",
Content = message,
OkButtonProps = new ButtonProps()
{
Danger = true
},
Centered = true,
Icon = @<Icon Type="@IconType.Outline.Delete" />
});
if (confirmed)
await GameService.UninstallAsync(Game);
InstallService.Remove(Game.Id);
await LibraryService.LibraryChanged();
}
async Task RemoveFromLibrary()
{
await LibraryService.RemoveFromLibraryAsync(Game.Id);
}
async Task RunInstallScripts()
{
var manifests = await Client.Games.GetManifestsAsync(Game.InstallDirectory, Game.Id);
foreach (var manifest in manifests)
{
await Client.Scripts.RunInstallScriptAsync(Game.InstallDirectory, manifest.Id);
}
}
async Task RunUninstallScripts()
{
var manifests = await Client.Games.GetManifestsAsync(Game.InstallDirectory, Game.Id);
foreach (var manifest in manifests)
{
await Client.Scripts.RunUninstallScriptAsync(Game.InstallDirectory, manifest.Id);
}
}
async Task RunNameChangeScripts()
{
var user = await UserService.GetCurrentUser();
var manifests = await Client.Games.GetManifestsAsync(Game.InstallDirectory, Game.Id);
foreach (var manifest in manifests)
{
await Client.Scripts.RunNameChangeScriptAsync(Game.InstallDirectory, Game.Id, user.Alias);
}
}
async Task RunKeyChangeScripts()
{
var manifests = await Client.Games.GetManifestsAsync(Game.InstallDirectory, Game.Id);
foreach (var manifest in manifests)
{
var key = Client.Games.GetAllocatedKey(manifest.Id);
await Client.Scripts.RunKeyChangeScriptAsync(Game.InstallDirectory, Game.Id, key);
}
}
async Task OpenManual(Media media)
{
var modalOptions = new ModalOptions()
{
Title = media.Name,
Maximizable = true,
DefaultMaximized = true,
Closable = true,
Footer = null,
Draggable = true,
Resizable = true,
WrapClassName = "pdf-reader-dialog",
};
var modalRef = await ModalService.CreateModalAsync<PdfReaderDialog, Media>(modalOptions, media);
}
async Task OpenSaveManager()
{
var modalOptions = new ModalOptions()
{
Title = "Manage Saves",
Maximizable = false,
DefaultMaximized = false,
Closable = true,
Draggable = true,
Resizable = true,
WrapClassName = "ant-modal-wrap-no-padding",
Footer = null,
};
var modalRef = await ModalService.CreateModalAsync<SavesDialog, Game>(modalOptions, Game);
}
async Task ReportIssue()
{
var modalOptions = new ModalOptions()
{
Title = "Report Issue",
Maximizable = false,
DefaultMaximized = false,
Closable = true,
OkText = "Submit",
Draggable = true
};
var modalRef = ModalService.CreateModal<ReportIssueDialog, Game, SDK.Models.Issue>(modalOptions, Game);
}
}