367 lines
14 KiB
Text
367 lines
14 KiB
Text
@using LANCommander.Launcher.Data.Models
|
|
@using LANCommander.Launcher.Models
|
|
@using LANCommander.SDK.Extensions
|
|
@inject DepotService DepotService
|
|
@inject LibraryService LibraryService
|
|
@inject GameService GameService
|
|
@inject InstallService InstallService
|
|
@inject ImportService ImportService
|
|
@inject SDK.Client Client
|
|
@inject ILogger<DepotGameDetails> Logger
|
|
@inject NavigationManager NavigationManager
|
|
@inject ModalService ModalService
|
|
@inject IMessageService MessageService
|
|
@inject LocalizationService LocalizationService
|
|
|
|
<Drawer Placement="DrawerPlacement.Bottom" Class="depot-game-details" @bind-Visible="@Visible" OnClose="Hide">
|
|
@if (SelectedGame != null)
|
|
{
|
|
<div @key="SelectedGame.Id" class="game-details no-scrollbar">
|
|
<Button Class="game-details-close-btn" Type="@ButtonType.Text" Icon="@IconType.Outline.Close" OnClick="Hide" />
|
|
|
|
@if (SelectedGame != null)
|
|
{
|
|
<div class="game-hero">
|
|
<SafeImage Media="@(SelectedGame.Media.FirstOrDefault(m => m.Type == SDK.Enums.MediaType.Logo))" Class="game-details-logo">
|
|
<h1>@SelectedGame.Title</h1>
|
|
</SafeImage>
|
|
|
|
<SafeImage Media="@(SelectedGame.Media.FirstOrDefault(m => m.Type == SDK.Enums.MediaType.Background))" Fit="ImageFit.Cover" Class="game-details-background">
|
|
<div class="game-details-background-fallback"></div>
|
|
</SafeImage>
|
|
</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 (IsInstalled)
|
|
{
|
|
if (IsInLibrary)
|
|
{
|
|
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" OnClick="ViewInLibrary">@LocalizationService.GetString("ViewInLibrary")</Button>
|
|
}
|
|
else
|
|
{
|
|
<Button Type="ButtonType.Dashed" Size="ButtonSize.Large" Style="pointer-events: none;">@LocalizationService.GetString("Installed")</Button>
|
|
}
|
|
}
|
|
else
|
|
{
|
|
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Icon="@IconType.Outline.Download" OnClick="Install" Loading="Installing">@LocalizationService.GetString("Install")</Button>
|
|
}
|
|
|
|
@if (IsInLibrary || SelectedGame.InLibrary)
|
|
{
|
|
<Tooltip Title="@LocalizationService.GetString("RemoveFromLibrary")">
|
|
<Button Size="ButtonSize.Large" Type="@ButtonType.Text" Icon="@IconType.Outline.Close" Danger OnClick="RemoveFromLibrary" Loading="RemovingFromLibrary" />
|
|
</Tooltip>
|
|
}
|
|
else
|
|
{
|
|
<Tooltip Title="@LocalizationService.GetString("AddToLibrary")">
|
|
<Button Size="ButtonSize.Large" Type="@ButtonType.Text" Icon="@IconType.Outline.Plus" OnClick="AddToLibrary" Loading="AddingToLibrary" />
|
|
</Tooltip>
|
|
}
|
|
</SpaceItem>
|
|
|
|
@if (!IsInstalled && Client.IsConnected())
|
|
{
|
|
<SpaceItem>
|
|
<Statistic Title="@LocalizationService.GetString("DownloadSize")" Value="@ByteSizeLib.ByteSize.FromBytes(GetDownloadSize()).ToString()" />
|
|
</SpaceItem>
|
|
}
|
|
|
|
@if (SelectedGame.PlaySessions.HasAny())
|
|
{
|
|
<SpaceItem>
|
|
<Statistic Title="@LocalizationService.GetString("PlayTime")" Value="@GetPlayTime(SelectedGame)" />
|
|
</SpaceItem>
|
|
<SpaceItem>
|
|
<Statistic Title="@LocalizationService.GetString("LastPlayed")" 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 > DateTime.MinValue)
|
|
{
|
|
<div class="game-metadata-released-on">
|
|
<h3>@LocalizationService.GetString("ReleasedOn")</h3>
|
|
<span>@SelectedGame.ReleasedOn.ToString("MMMM d, yyyy")</span>
|
|
</div>
|
|
}
|
|
|
|
@if (SelectedGame.Developers.HasAny())
|
|
{
|
|
<div class="game-metadata-developers">
|
|
<h3>@LocalizationService.GetString("Developers")</h3>
|
|
<span>@(String.Join(", ", SelectedGame.Developers.Select(c => c.Name)))</span>
|
|
</div>
|
|
}
|
|
|
|
@if (SelectedGame.Publishers.HasAny())
|
|
{
|
|
<div class="game-metadata-publishers">
|
|
<h3>@LocalizationService.GetString("Publishers")</h3>
|
|
<span>@(String.Join(", ", SelectedGame.Publishers.Select(c => c.Name)))</span>
|
|
</div>
|
|
}
|
|
|
|
@if (SelectedGame.Genres.HasAny())
|
|
{
|
|
<div class="game-metadata-genres">
|
|
<h3>@LocalizationService.GetString("Genres")</h3>
|
|
<span>@(String.Join(", ", SelectedGame.Genres.Select(g => g.Name)))</span>
|
|
</div>
|
|
}
|
|
|
|
@if (SelectedGame.Tags.HasAny())
|
|
{
|
|
<div class="game-metadata-tags">
|
|
<h3>@LocalizationService.GetString("Tags")</h3>
|
|
<span>@(String.Join(", ", SelectedGame.Tags.Select(t => t.Name)))</span>
|
|
</div>
|
|
}
|
|
</div>
|
|
</GridCol>
|
|
|
|
<GridCol Flex="@("256px")" Class="game-cover">
|
|
@if (SelectedGame.Media.HasAny(m => m.Type == SDK.Enums.MediaType.Cover))
|
|
{
|
|
<SafeImage Media="@(SelectedGame.Media.First(m => m.Type == SDK.Enums.MediaType.Cover))">
|
|
<div class="depot-game-default-cover">
|
|
<span>@SelectedGame.Title</span>
|
|
</div>
|
|
</SafeImage>
|
|
}
|
|
</GridCol>
|
|
</GridRow>
|
|
}
|
|
</div>
|
|
}
|
|
</Drawer>
|
|
|
|
@code {
|
|
[Parameter] public Guid ItemId { get; set; }
|
|
[Parameter] public EventCallback OnClose { get; set; }
|
|
|
|
SDK.Models.Game? SelectedGame { get; set; }
|
|
bool Visible { get; set; } = false;
|
|
bool IsInstalled { get; set; } = false;
|
|
bool IsInLibrary { get; set; } = false;
|
|
|
|
bool Installing { get; set; } = false;
|
|
bool AddingToLibrary { get; set; } = false;
|
|
bool RemovingFromLibrary { get; set; } = false;
|
|
|
|
Settings Settings = SettingService.GetSettings();
|
|
|
|
protected override async Task OnParametersSetAsync()
|
|
{
|
|
Installing = false;
|
|
AddingToLibrary = false;
|
|
RemovingFromLibrary = false;
|
|
|
|
try
|
|
{
|
|
if (ItemId != Guid.Empty)
|
|
{
|
|
SelectedGame = await Client.Games.GetAsync(ItemId);
|
|
|
|
var game = await GameService.GetAsync(ItemId);
|
|
|
|
IsInstalled = game?.Installed ?? false;
|
|
IsInLibrary = LibraryService.IsInLibrary(ItemId);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
SelectedGame = null;
|
|
|
|
Logger?.LogError(ex, "Could not load game with ID {GameId}", ItemId);
|
|
}
|
|
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
|
|
public async Task Show()
|
|
{
|
|
Visible = true;
|
|
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
|
|
public async Task Hide()
|
|
{
|
|
Visible = false;
|
|
|
|
if (OnClose.HasDelegate)
|
|
await OnClose.InvokeAsync();
|
|
|
|
await InvokeAsync(StateHasChanged);
|
|
}
|
|
|
|
async Task Install()
|
|
{
|
|
if (SelectedGame == null)
|
|
{
|
|
MessageService.Success($"No game selected. Aborting installation!");
|
|
return;
|
|
}
|
|
|
|
Installing = true;
|
|
StateHasChanged();
|
|
await Task.Yield();
|
|
|
|
if (!SelectedGame.InLibrary)
|
|
await AddToLibrary();
|
|
|
|
var libraryItem = LibraryService.GetItem(SelectedGame.Id);
|
|
var game = libraryItem.DataItem as Game;
|
|
if (game == null)
|
|
{
|
|
MessageService.Success($"No game added to library. Unable to proceed!");
|
|
return;
|
|
}
|
|
|
|
await Hide();
|
|
|
|
if (Settings.Games.InstallDirectories.Length > 1 || (game?.DependentGames?.Any(g => g.Type.IsIn(Data.Enums.GameType.Expansion, Data.Enums.GameType.Mod)) ?? false))
|
|
{
|
|
var modalOptions = new ModalOptions()
|
|
{
|
|
Title = $"Install {SelectedGame.Title}",
|
|
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, libraryItem);
|
|
}
|
|
else
|
|
{
|
|
await InstallService.Add(game!);
|
|
}
|
|
}
|
|
|
|
async Task AddToLibrary()
|
|
{
|
|
if (!Installing)
|
|
{
|
|
AddingToLibrary = true;
|
|
StateHasChanged();
|
|
await Task.Yield();
|
|
}
|
|
|
|
if (SelectedGame == null)
|
|
{
|
|
MessageService.Success($"No game selected. Aborting adding to library!");
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
await ImportService.ImportGameAsync(SelectedGame.Id);
|
|
await LibraryService.AddToLibraryAsync(SelectedGame.Id);
|
|
await LibraryService.RefreshItemsAsync();
|
|
|
|
MessageService.Success($"{SelectedGame.Title} was added to your library!");
|
|
|
|
SelectedGame.InLibrary = IsInLibrary = LibraryService.IsInLibrary(SelectedGame.Id);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger?.LogError(ex, $"{SelectedGame.Title} ({SelectedGame.Id}) could not be added to your library!");
|
|
MessageService.Error($"{SelectedGame.Title} could not be added to your library!");
|
|
}
|
|
|
|
AddingToLibrary = false;
|
|
StateHasChanged();
|
|
await Task.Yield();
|
|
}
|
|
|
|
async Task RemoveFromLibrary()
|
|
{
|
|
if (!Installing)
|
|
{
|
|
RemovingFromLibrary = true;
|
|
StateHasChanged();
|
|
await Task.Yield();
|
|
}
|
|
|
|
if (SelectedGame == null)
|
|
{
|
|
MessageService.Success($"No game selected. Aborting removing from library!");
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
await LibraryService.RemoveFromLibraryAsync(SelectedGame.Id);
|
|
await LibraryService.RefreshItemsAsync();
|
|
|
|
MessageService.Success($"{SelectedGame.Title} was removed from your library!");
|
|
|
|
SelectedGame.InLibrary = IsInLibrary = LibraryService.IsInLibrary(SelectedGame.Id);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger?.LogError(ex, $"{SelectedGame.Title} ({SelectedGame.Id}) could not be removed from your library!");
|
|
MessageService.Error($"{SelectedGame.Title} could not be removed from your library!");
|
|
}
|
|
|
|
RemovingFromLibrary = false;
|
|
StateHasChanged();
|
|
await Task.Yield();
|
|
}
|
|
|
|
long GetDownloadSize()
|
|
{
|
|
long size = 0;
|
|
|
|
if (SelectedGame != null && SelectedGame.Archives.Any())
|
|
size = SelectedGame.Archives.OrderByDescending(a => a.CreatedOn).First().CompressedSize;
|
|
|
|
return size;
|
|
}
|
|
|
|
string GetPlayTime(SDK.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(SDK.Models.Game game)
|
|
{
|
|
var lastSession = game.PlaySessions.Where(ps => ps.End != null && ps.Start != null).OrderByDescending(ps => ps.End).FirstOrDefault();
|
|
|
|
return lastSession?.End?.ToRelativeDate() ?? "Never";
|
|
}
|
|
|
|
async Task ViewInLibrary()
|
|
{
|
|
await Hide();
|
|
NavigationManager.NavigateTo($"/{SelectedGame.Id}", false);
|
|
}
|
|
}
|