Some checks failed
Publish SDK NuGet Package / publish (push) Failing after 1m42s
LANCommander Release / prep (push) Has been cancelled
LANCommander Release / build_server_win-x64 (push) Has been cancelled
LANCommander Release / build_launcher_linux-arm64 (push) Has been cancelled
LANCommander Release / build_launcher_linux-x64 (push) Has been cancelled
LANCommander Release / build_launcher_osx-arm64 (push) Has been cancelled
LANCommander Release / build_launcher_osx-x64 (push) Has been cancelled
LANCommander Release / build_launcher_win-arm64 (push) Has been cancelled
LANCommander Release / build_launcher_win-x64 (push) Has been cancelled
LANCommander Release / build_server_linux-arm64 (push) Has been cancelled
LANCommander Release / build_server_linux-x64 (push) Has been cancelled
LANCommander Release / build_server_osx-arm64 (push) Has been cancelled
LANCommander Release / build_server_osx-x64 (push) Has been cancelled
LANCommander Release / build_server_win-arm64 (push) Has been cancelled
LANCommander Release / build_release (push) Has been cancelled
394 lines
16 KiB
Text
394 lines
16 KiB
Text
@page "/"
|
|
@page "/{id:guid}"
|
|
@using LANCommander.Launcher.Data.Models
|
|
@using LANCommander.Launcher.Models.Enums
|
|
@using LANCommander.Launcher.Models
|
|
@using System.Diagnostics
|
|
@using LANCommander.Launcher.UI.Library.Components
|
|
@using LANCommander.SDK.Helpers
|
|
@inject SDK.Client Client
|
|
@inject NavigationManager NavigationManager
|
|
@inject LibraryService LibraryService
|
|
@inject InstallService InstallService
|
|
@inject GameService GameService
|
|
@inject ModalService ModalService
|
|
@inject ConfirmService ConfirmService
|
|
@inject ImportService ImportService
|
|
|
|
<Layout>
|
|
<Content Class="library">
|
|
<LibraryList SelectedItem="@(SelectedGame?.Id)" OnItemSelected="@((key) => SelectLibraryItem(key))" />
|
|
|
|
<div class="game-details no-scrollbar">
|
|
@if (SelectedGame != null)
|
|
{
|
|
<div class="game-hero">
|
|
@if (SelectedGame.Media.Any(m => m.Type == SDK.Enums.MediaType.Logo))
|
|
{
|
|
<MediaImage Id="@(SelectedGame.Media.First(m => m.Type == SDK.Enums.MediaType.Logo).Id)" Key="GameDetailsLogo" Class="game-details-logo" />
|
|
}
|
|
else
|
|
{
|
|
<h1>@SelectedGame.Title</h1>
|
|
}
|
|
|
|
@if (SelectedGame.Media.Any(m => m.Type == SDK.Enums.MediaType.Background))
|
|
{
|
|
<MediaImage Id="@(SelectedGame.Media.First(m => m.Type == SDK.Enums.MediaType.Background).Id)" Key="GameDetailsBackground" Class="game-details-background" />
|
|
}
|
|
</div>
|
|
<GridRow Gutter="32" Class="game-info" Wrap="false">
|
|
<GridCol Flex="@("auto")">
|
|
<div class="game-action-bar">
|
|
<Space Direction="SpaceDirection.Horizontal" Size="SpaceSize.Large">
|
|
<SpaceItem>
|
|
@if (SelectedItem.State == ListItemState.Installed)
|
|
{
|
|
<PlayButton LibraryItem="SelectedItem" />
|
|
}
|
|
else if (SelectedItem.State == ListItemState.NotInstalled)
|
|
{
|
|
<ConnectionStateView>
|
|
<Online>
|
|
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Icon="@IconType.Outline.Download" OnClick="() => Install(SelectedItem)">Install</Button>
|
|
</Online>
|
|
<Offline>
|
|
<Tooltip Title="You are currently offline">
|
|
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Icon="@IconType.Outline.Download" Disabled>Install</Button>
|
|
</Tooltip>
|
|
</Offline>
|
|
</ConnectionStateView>
|
|
}
|
|
else if (SelectedItem.State == ListItemState.Queued)
|
|
{
|
|
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Icon="@IconType.Outline.Bars" Disabled="true">Queued</Button>
|
|
}
|
|
else if (SelectedItem.State == ListItemState.UpdateAvailable)
|
|
{
|
|
<ConnectionStateView>
|
|
<Online>
|
|
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Icon="@IconType.Outline.Download" OnClick="() => Update(SelectedItem)">Update</Button>
|
|
</Online>
|
|
<Offline>
|
|
<Tooltip Title="You are currently offline">
|
|
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Icon="@IconType.Outline.Download" Disabled>Update</Button>
|
|
</Tooltip>
|
|
</Offline>
|
|
</ConnectionStateView>
|
|
}
|
|
else if (SelectedItem.State == ListItemState.Installing)
|
|
{
|
|
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Loading Disabled="true">Installing</Button>
|
|
}
|
|
else if (SelectedItem.State == ListItemState.Uninstalling)
|
|
{
|
|
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Loading Disabled="true">Uninstalling</Button>
|
|
}
|
|
</SpaceItem>
|
|
|
|
@if (SelectedItem.State == ListItemState.NotInstalled && Connected)
|
|
{
|
|
<ConnectionStateView>
|
|
<Online>
|
|
<SpaceItem>
|
|
<Statistic Title="Download Size" Value="@ByteSizeLib.ByteSize.FromBytes(GetDownloadSize()).ToString()"/>
|
|
</SpaceItem>
|
|
</Online>
|
|
</ConnectionStateView>
|
|
}
|
|
|
|
<SpaceItem>
|
|
<Statistic Title="Play Time" Value="@GetPlayTime(SelectedGame)" />
|
|
</SpaceItem>
|
|
<SpaceItem>
|
|
<Statistic Title="Last Played" Value="@GetLastPlayed(SelectedGame)" />
|
|
</SpaceItem>
|
|
</Space>
|
|
</div>
|
|
|
|
<div class="game-metadata">
|
|
@if (!String.IsNullOrWhiteSpace(SelectedGame.Description))
|
|
{
|
|
<div class="game-metadata-description">@SelectedGame.Description</div>
|
|
}
|
|
|
|
@if (SelectedGame.ReleasedOn.HasValue)
|
|
{
|
|
<div class="game-metadata-released-on">
|
|
<h3>Released On</h3>
|
|
<span>@SelectedGame.ReleasedOn.Value.ToString("MMMM d, yyyy")</span>
|
|
</div>
|
|
}
|
|
|
|
@if (SelectedGame.Developers != null && SelectedGame.Developers.Any())
|
|
{
|
|
<div class="game-metadata-developers">
|
|
<h3>Developers</h3>
|
|
<span>@(String.Join(", ", SelectedGame.Developers.Select(c => c.Name)))</span>
|
|
</div>
|
|
}
|
|
|
|
@if (SelectedGame.Publishers != null && SelectedGame.Publishers.Any())
|
|
{
|
|
<div class="game-metadata-publishers">
|
|
<h3>Publishers</h3>
|
|
<span>@(String.Join(", ", SelectedGame.Publishers.Select(c => c.Name)))</span>
|
|
</div>
|
|
}
|
|
|
|
@if (SelectedGame.Genres != null && SelectedGame.Genres.Any())
|
|
{
|
|
<div class="game-metadata-genres">
|
|
<h3>Genres</h3>
|
|
<span>@(String.Join(", ", SelectedGame.Genres.Select(g => g.Name)))</span>
|
|
</div>
|
|
}
|
|
|
|
@if (SelectedGame.Tags != null && SelectedGame.Tags.Any())
|
|
{
|
|
<div class="game-metadata-tags">
|
|
<h3>Tags</h3>
|
|
<span>@(String.Join(", ", SelectedGame.Tags.Select(t => t.Name)))</span>
|
|
</div>
|
|
}
|
|
</div>
|
|
</GridCol>
|
|
|
|
<GridCol Flex="@("256px")" Class="game-cover">
|
|
@if (SelectedGame.Media.Any(m => m.Type == SDK.Enums.MediaType.Cover))
|
|
{
|
|
<MediaImage Key="GameDetailsCover" Id="@(SelectedGame.Media.First(m => m.Type == SDK.Enums.MediaType.Cover).Id)" />
|
|
}
|
|
</GridCol>
|
|
</GridRow>
|
|
}
|
|
</div>
|
|
</Content>
|
|
</Layout>
|
|
|
|
<div class="logo">
|
|
<img src="assets/logo-cut.svg" />
|
|
</div>
|
|
|
|
<LANCommander.Launcher.UI.Components.Footer />
|
|
|
|
@code {
|
|
[Parameter] public Guid Id { get; set; }
|
|
[CascadingParameter] public bool Connected { get; set; }
|
|
[CascadingParameter] public bool OfflineMode { get; set; }
|
|
|
|
Models.ListItem SelectedItem { get; set; }
|
|
|
|
Data.Models.Game SelectedGame { get; set; }
|
|
SDK.Models.Game RemoteGame { get; set; }
|
|
|
|
Settings Settings = SettingService.GetSettings();
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
{
|
|
InstallService.OnQueueChanged += OnQueueChanged;
|
|
InstallService.OnInstallFail += OnInstallFail;
|
|
InstallService.OnInstallComplete += OnInstallComplete;
|
|
GameService.OnUninstall += OnUninstall;
|
|
GameService.OnUninstallComplete += OnUninstallComplete;
|
|
|
|
await LoadData();
|
|
}
|
|
|
|
protected override async Task OnParametersSetAsync()
|
|
{
|
|
if (Id != Guid.Empty)
|
|
{
|
|
await OnLibraryItemSelected(await LibraryService.GetItemAsync(Id));
|
|
|
|
if (SelectedGame != null && (Connected && !OfflineMode))
|
|
RemoteGame = await Client.Games.GetAsync(SelectedGame.Id);
|
|
}
|
|
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
|
|
async Task LoadData()
|
|
{
|
|
await LibraryService.RefreshItemsAsync();
|
|
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
|
|
async Task SelectLibraryItem(Guid id)
|
|
{
|
|
NavigationManager.NavigateTo($"/{id}");
|
|
}
|
|
|
|
async Task OnLibraryItemSelected(Models.ListItem item)
|
|
{
|
|
if (item != null && item.DataItem is Data.Models.Game)
|
|
{
|
|
SelectedItem = item;
|
|
SelectedGame = item.DataItem as Data.Models.Game;
|
|
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
}
|
|
|
|
async Task Install(Models.ListItem item)
|
|
{
|
|
var game = item.DataItem as Game;
|
|
|
|
var addons = await Client.Games.GetAddonsAsync(game.Id);
|
|
|
|
if (Settings.Games.InstallDirectories.Length > 1 || addons.Any())
|
|
{
|
|
var modalOptions = new ModalOptions()
|
|
{
|
|
Title = $"Install {item.Name}",
|
|
Maximizable = false,
|
|
DefaultMaximized = false,
|
|
Closable = true,
|
|
OkText = "Install",
|
|
Draggable = true,
|
|
Centered = true,
|
|
WrapClassName = "ant-modal-wrap-no-padding",
|
|
Footer = null,
|
|
};
|
|
|
|
var modalRef = ModalService.CreateModal<InstallDialog, Models.ListItem, string>(modalOptions, item);
|
|
}
|
|
else
|
|
{
|
|
await InstallService.Add(game);
|
|
}
|
|
}
|
|
|
|
async Task Update(Models.ListItem item)
|
|
{
|
|
var game = item.DataItem as Game;
|
|
|
|
await InstallService.Add(game);
|
|
}
|
|
|
|
async Task OnQueueChanged()
|
|
{
|
|
var queueItem = InstallService.Queue.FirstOrDefault(i => SelectedItem != null && i.Id == SelectedItem.Key);
|
|
|
|
if (queueItem != null)
|
|
{
|
|
SelectedItem = await LibraryService.GetItemAsync(SelectedItem);
|
|
|
|
switch (queueItem.Status)
|
|
{
|
|
case SDK.Enums.InstallStatus.Downloading:
|
|
case SDK.Enums.InstallStatus.InstallingRedistributables:
|
|
case SDK.Enums.InstallStatus.InstallingMods:
|
|
case SDK.Enums.InstallStatus.InstallingExpansions:
|
|
case SDK.Enums.InstallStatus.RunningScripts:
|
|
case SDK.Enums.InstallStatus.DownloadingSaves:
|
|
SelectedItem.State = ListItemState.Installing;
|
|
break;
|
|
|
|
case SDK.Enums.InstallStatus.Queued:
|
|
SelectedItem.State = ListItemState.Queued;
|
|
break;
|
|
|
|
case SDK.Enums.InstallStatus.Failed:
|
|
case SDK.Enums.InstallStatus.Canceled:
|
|
SelectedItem.State = ListItemState.NotInstalled;
|
|
break;
|
|
|
|
case SDK.Enums.InstallStatus.Complete:
|
|
SelectedItem.State = ListItemState.Installed;
|
|
break;
|
|
}
|
|
|
|
await OnLibraryItemSelected(SelectedItem);
|
|
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
}
|
|
|
|
async Task OnInstallComplete(Data.Models.Game game)
|
|
{
|
|
await LoadData();
|
|
|
|
if (SelectedItem.DataItem is Game selectedGame)
|
|
{
|
|
if (selectedGame.Id == game.Id)
|
|
await OnLibraryItemSelected(LibraryService.Items.FirstOrDefault(i => i.Key == selectedGame.Id));
|
|
}
|
|
}
|
|
|
|
async Task OnInstallFail(Data.Models.Game game)
|
|
{
|
|
var result = await ConfirmService.Show(
|
|
$"The installation for {game.Title} has failed. Retry download?",
|
|
"Installation Failed",
|
|
ConfirmButtons.RetryCancel,
|
|
ConfirmIcon.Error
|
|
);
|
|
|
|
await LibraryService.LibraryChanged();
|
|
|
|
if (result == ConfirmResult.Retry)
|
|
{
|
|
var libraryItem = LibraryService.GetItem(game.Id);
|
|
|
|
Install(libraryItem);
|
|
}
|
|
}
|
|
|
|
async Task OnUninstall(Data.Models.Game game)
|
|
{
|
|
if (SelectedItem.Key == game.Id)
|
|
{
|
|
SelectedItem.State = ListItemState.Uninstalling;
|
|
|
|
await Task.Yield();
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
}
|
|
|
|
async Task OnUninstallComplete(Data.Models.Game game)
|
|
{
|
|
await LoadData();
|
|
|
|
if (SelectedItem.Key == game.Id)
|
|
{
|
|
SelectedItem.State = ListItemState.NotInstalled;
|
|
await OnLibraryItemSelected(LibraryService.Items.FirstOrDefault(i => i.Key == SelectedGame.Id));
|
|
}
|
|
}
|
|
|
|
long GetDownloadSize()
|
|
{
|
|
long size = 0;
|
|
|
|
if (RemoteGame != null && RemoteGame.Archives.Any())
|
|
size = RemoteGame.Archives.OrderByDescending(a => a.CreatedOn).First().CompressedSize;
|
|
|
|
return size;
|
|
}
|
|
|
|
string GetPlayTime(Data.Models.Game game)
|
|
{
|
|
var totalTime = new TimeSpan(game.PlaySessions
|
|
.Where(ps => ps.End != null && ps.Start != null)
|
|
.Select(ps => ps.End.Value.Subtract(ps.Start.Value))
|
|
.Sum(ts => ts.Ticks));
|
|
if (totalTime.TotalMinutes < 1)
|
|
return "None";
|
|
else if (totalTime.TotalHours < 1)
|
|
return totalTime.TotalMinutes.ToString("0") + " minutes";
|
|
else
|
|
return totalTime.TotalHours.ToString("0.##") + " hours";
|
|
}
|
|
|
|
string GetLastPlayed(Data.Models.Game game)
|
|
{
|
|
var lastSession = game.PlaySessions.Where(ps => ps.End != null && ps.Start != null).OrderByDescending(ps => ps.End).FirstOrDefault();
|
|
|
|
if (lastSession == null)
|
|
return "Never";
|
|
else
|
|
return lastSession.End.Value.ToRelativeDate();
|
|
}
|
|
}
|