LANCommander/LANCommander.Launcher/UI/Components/PlayButton.razor
Pat Hartl 6dfc0906ac Refactor launcher library importing, manifests
Switched the library importing in the launcher to work based on a queue. As a new game is added to the queue, it should find any related data and also add it to the queue. This should result in an easier to maintain importer while reducing the load on the launcher's DAL. This may result in more RAM usage while importing. Local manifests have also been refactored to match manifests in import/export LCX files, removing the old manifest format. This is a large breaking change that will probably break existing game installations. A migration will probably have to be created.
2025-11-29 18:24:27 -06:00

174 lines
No EOL
5.2 KiB
Text

@implements IDisposable
@using LANCommander.Launcher.Data.Models
@using LANCommander.Launcher.Models
@using System.Diagnostics
@using LANCommander.SDK
@using LANCommander.SDK.Services
@inject GameService GameService
@inject LibraryService LibraryService
@inject GameClient GameClient
@inject LobbyClient LobbyClient
@inject ModalService ModalService
@inject MessageService MessageService
@inject LocalizationService LocalizationService
@if (State == PlayButtonState.Running)
{
<Popconfirm Title="@LocalizationService.GetString("DoYouWantToStopGame")" OkText="@LocalizationService.GetString("Yes")" OnConfirm="() => Stop()">
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Icon="@IconType.Outline.CaretRight">@LocalizationService.GetString("Running")</Button>
</Popconfirm>
}
else if (State == PlayButtonState.Starting)
{
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Loading="true">@LocalizationService.GetString("Starting")</Button>
}
else if (State == PlayButtonState.Stopping)
{
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Loading="true">@LocalizationService.GetString("Stopping")</Button>
}
else
{
<Space Direction="SpaceDirection.Horizontal">
<SpaceItem>
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Icon="@IconType.Outline.CaretRight" OnClick="() => Run()">@LocalizationService.GetString("Play")</Button>
</SpaceItem>
<SpaceItem>
<Dropdown>
<Overlay>
<Menu>
<LibraryItemContextMenu Model="LibraryItem" MenuExtra="MenuExtra" />
</Menu>
</Overlay>
<ChildContent>
<Button Type="@ButtonType.Default" Size="ButtonSize.Large" Icon="@IconType.Outline.Ellipsis" />
</ChildContent>
</Dropdown>
</SpaceItem>
</Space>
}
@code {
[Parameter] public Guid LibraryItemId { get; set; }
[Parameter] public Models.ListItem LibraryItem { get; set; }
[Parameter] public RenderFragment MenuExtra { get; set; }
Timer StateTimer;
PlayButtonState State = PlayButtonState.Idle;
public enum PlayButtonState
{
Idle,
Starting,
Running,
Stopping
}
protected override async Task OnInitializedAsync()
{
StateTimer = new Timer(state => { InvokeAsync(UpdateState); }, null, 0, 250);
}
protected override async Task OnParametersSetAsync()
{
if (LibraryItem == null && LibraryItemId != Guid.Empty)
LibraryItem = await LibraryService.GetItemAsync(LibraryItemId);
}
async Task UpdateState()
{
if (GameClient.IsRunning(LibraryItem.Key))
{
await ChangeState(PlayButtonState.Running);
}
else if (State == PlayButtonState.Running && !GameClient.IsRunning(LibraryItem.Key))
{
await ChangeState(PlayButtonState.Idle);
}
}
async Task ChangeState(PlayButtonState state)
{
State = state;
await InvokeAsync(StateHasChanged);
}
async Task Run()
{
var game = LibraryItem.DataItem as Game;
var actions = await GameClient.GetActionsAsync(game.InstallDirectory, game.Id);
await ChangeState(PlayButtonState.Starting);
if (actions == null || actions.Count() == 0)
{
MessageService.Error(LocalizationService.GetString("NoActionsFound"));
await ChangeState(PlayButtonState.Idle);
return;
}
var primaryActions = actions.Where(a => a.IsPrimaryAction && LibraryService.IsInstalled(game.Id));
if (primaryActions.Count() == 0)
{
MessageService.Error(LocalizationService.GetString("NoPrimaryActionFound"));
await ChangeState(PlayButtonState.Idle);
return;
}
if (primaryActions.Count() == 1)
{
var task = GameService.Run(game, primaryActions.First());
await InvokeAsync(StateHasChanged);
await task;
}
else
{
var modalOptions = new ModalOptions()
{
Title = LocalizationService.GetString("PlayGame", game.Title),
Maximizable = false,
DefaultMaximized = false,
Closable = true,
MaskClosable = true,
Footer = null,
Centered = true,
WrapClassName = "game-actions-dialog",
AfterClose = async () =>
{
LobbyClient.ReleaseSteam();
await ChangeState(PlayButtonState.Idle);
}
};
var model = new ActionSelectorDialogOptions
{
Actions = actions.Where(a => a.IsPrimaryAction),
Game = game
};
var modalRef = ModalService.CreateModal<ActionSelectorDialog, ActionSelectorDialogOptions, Process>(modalOptions, model);
}
}
async Task Stop()
{
await ChangeState(PlayButtonState.Stopping);
await GameClient.Stop(LibraryItem.Key);
await ChangeState(PlayButtonState.Idle);
}
public void Dispose()
{
StateTimer.Dispose();
}
}