LANCommander/LANCommander.Launcher/UI/Library/Index.razor

407 lines
17 KiB
Text
Raw Permalink Normal View History

@page "/"
2024-06-01 22:47:56 -05:00
@page "/{id:guid}"
@using LANCommander.Launcher.Data.Models
@using LANCommander.Launcher.Models.Enums
@using LANCommander.Launcher.Models
2024-05-25 22:21:04 -05:00
@using System.Diagnostics
@using LANCommander.Launcher.UI.Library.Components
2024-05-29 02:02:40 -05:00
@using LANCommander.SDK.Helpers
@inject SDK.Client Client
@inject NavigationManager NavigationManager
2024-05-23 23:41:38 -05:00
@inject LibraryService LibraryService
@inject InstallService InstallService
2024-05-25 22:21:04 -05:00
@inject GameService GameService
@inject ModalService ModalService
@inject ConfirmService ConfirmService
@inject ImportService ImportService
@inject LocalizationService LocalizationService
2024-06-07 23:49:11 -05:00
<Layout>
<Content Class="library">
<LibraryList SelectedItem="@(SelectedGame?.Id)" OnItemSelected="@((key) => SelectLibraryItem(key))" />
2024-06-07 23:49:11 -05:00
<div class="game-details no-scrollbar">
2024-06-07 23:49:11 -05:00
@if (SelectedGame != null)
{
<div class="game-hero">
2024-06-19 19:36:04 -05:00
@if (SelectedGame.Media.Any(m => m.Type == SDK.Enums.MediaType.Logo))
2024-06-19 17:20:34 -05:00
{
<MediaImage Id="@(SelectedGame.Media.First(m => m.Type == SDK.Enums.MediaType.Logo).Id)" Key="GameDetailsLogo" Class="game-details-logo" />
2024-06-19 17:20:34 -05:00
}
else
{
<h1>@SelectedGame.Title</h1>
}
2024-06-19 19:36:04 -05:00
@if (SelectedGame.Media.Any(m => m.Type == SDK.Enums.MediaType.Background))
2024-06-07 23:49:11 -05:00
{
<MediaImage Id="@(SelectedGame.Media.First(m => m.Type == SDK.Enums.MediaType.Background).Id)" Key="GameDetailsBackground" Class="game-details-background" />
2024-06-07 23:49:11 -05:00
}
</div>
2024-06-08 16:03:41 -05:00
<GridRow Gutter="32" Class="game-info" Wrap="false">
<GridCol Flex="@("auto")">
<div class="game-action-bar">
2024-12-31 18:21:41 -06:00
<Space Direction="SpaceDirection.Horizontal" Size="SpaceSize.Large">
2024-06-08 16:03:41 -05:00
<SpaceItem>
2024-11-09 17:15:04 -06:00
@if (SelectedItem.State == ListItemState.Installed)
2024-06-08 18:37:52 -05:00
{
<PlayButton LibraryItem="SelectedItem" />
2024-06-08 18:37:52 -05:00
}
2024-11-09 17:15:04 -06:00
else if (SelectedItem.State == ListItemState.NotInstalled)
2024-06-08 16:03:41 -05:00
{
<ConnectionStateView>
<Online>
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Icon="@IconType.Outline.Download" OnClick="() => Install(SelectedItem)">@LocalizationService.GetString("Install")</Button>
</Online>
<Offline>
<Tooltip Title="@LocalizationService.GetString("YouAreCurrentlyOffline")">
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Icon="@IconType.Outline.Download" Disabled>@LocalizationService.GetString("Install")</Button>
</Tooltip>
</Offline>
</ConnectionStateView>
2024-06-08 16:03:41 -05:00
}
2024-11-09 17:15:04 -06:00
else if (SelectedItem.State == ListItemState.Queued)
2024-06-08 16:03:41 -05:00
{
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Icon="@IconType.Outline.Bars" Disabled="true">@LocalizationService.GetString("Queued")</Button>
2024-06-08 16:03:41 -05:00
}
2024-11-09 17:15:04 -06:00
else if (SelectedItem.State == ListItemState.UpdateAvailable)
2024-06-08 16:03:41 -05:00
{
<ConnectionStateView>
<Online>
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Icon="@IconType.Outline.Download" OnClick="() => Update(SelectedItem)">@LocalizationService.GetString("Update")</Button>
</Online>
<Offline>
<Tooltip Title="@LocalizationService.GetString("YouAreCurrentlyOffline")">
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Icon="@IconType.Outline.Download" Disabled>@LocalizationService.GetString("Update")</Button>
</Tooltip>
</Offline>
</ConnectionStateView>
2024-06-08 16:03:41 -05:00
}
2024-11-09 17:15:04 -06:00
else if (SelectedItem.State == ListItemState.Installing)
2024-06-08 16:03:41 -05:00
{
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Loading Disabled="true">@LocalizationService.GetString("Installing")</Button>
2025-01-27 00:04:42 -06:00
}
else if (SelectedItem.State == ListItemState.Uninstalling)
{
<Button Type="ButtonType.Primary" Size="ButtonSize.Large" Loading Disabled="true">@LocalizationService.GetString("Uninstalling")</Button>
2024-06-08 16:03:41 -05:00
}
</SpaceItem>
@if (SelectedItem.State == ListItemState.NotInstalled && Connected)
{
<ConnectionStateView>
<Online>
<SpaceItem>
<Statistic Title="@LocalizationService.GetString("DownloadSize")" Value="@ByteSizeLib.ByteSize.FromBytes(GetDownloadSize()).ToString()"/>
</SpaceItem>
</Online>
</ConnectionStateView>
}
2024-06-08 16:03:41 -05:00
<SpaceItem>
<Statistic Title="@LocalizationService.GetString("PlayTime")" Value="@GetPlayTime(SelectedGame)" />
2024-06-08 16:03:41 -05:00
</SpaceItem>
<SpaceItem>
<Statistic Title="@LocalizationService.GetString("LastPlayed")" Value="@GetLastPlayed(SelectedGame)" />
2024-06-08 16:03:41 -05:00
</SpaceItem>
</Space>
</div>
<div class="game-metadata">
2024-07-04 16:43:26 -05:00
@if (!String.IsNullOrWhiteSpace(SelectedGame.Description))
{
<div class="game-metadata-description">@SelectedGame.Description</div>
}
@if (SelectedGame.ReleasedOn.HasValue)
{
<div class="game-metadata-released-on">
<h3>@LocalizationService.GetString("ReleasedOn")</h3>
2024-07-04 16:43:26 -05:00
<span>@SelectedGame.ReleasedOn.Value.ToString("MMMM d, yyyy")</span>
</div>
}
@if (SelectedGame.Developers != null && SelectedGame.Developers.Any())
{
<div class="game-metadata-developers">
<h3>@LocalizationService.GetString("Developers")</h3>
2024-07-04 16:43:26 -05:00
<span>@(String.Join(", ", SelectedGame.Developers.Select(c => c.Name)))</span>
</div>
}
2024-07-04 16:43:26 -05:00
@if (SelectedGame.Publishers != null && SelectedGame.Publishers.Any())
{
<div class="game-metadata-publishers">
<h3>@LocalizationService.GetString("Publishers")</h3>
2024-07-04 16:43:26 -05:00
<span>@(String.Join(", ", SelectedGame.Publishers.Select(c => c.Name)))</span>
</div>
}
2024-07-04 16:43:26 -05:00
@if (SelectedGame.Genres != null && SelectedGame.Genres.Any())
{
<div class="game-metadata-genres">
<h3>@LocalizationService.GetString("Genres")</h3>
2024-07-04 16:43:26 -05:00
<span>@(String.Join(", ", SelectedGame.Genres.Select(g => g.Name)))</span>
</div>
}
@if (SelectedGame.Tags != null && SelectedGame.Tags.Any())
{
<div class="game-metadata-tags">
<h3>@LocalizationService.GetString("Tags")</h3>
2024-07-04 16:43:26 -05:00
<span>@(String.Join(", ", SelectedGame.Tags.Select(t => t.Name)))</span>
</div>
}
2024-06-08 16:03:41 -05:00
</div>
</GridCol>
<GridCol Flex="@("256px")" Class="game-cover">
2024-06-19 19:36:04 -05:00
@if (SelectedGame.Media.Any(m => m.Type == SDK.Enums.MediaType.Cover))
2024-06-08 16:03:41 -05:00
{
<MediaImage Key="GameDetailsCover" Id="@(SelectedGame.Media.First(m => m.Type == SDK.Enums.MediaType.Cover).Id)" />
2024-06-08 16:03:41 -05:00
}
</GridCol>
</GridRow>
2024-06-07 23:49:11 -05:00
}
</div>
</Content>
</Layout>
2024-06-07 23:49:11 -05:00
<div class="logo">
<img src="assets/logo-cut.svg" />
</div>
<LANCommander.Launcher.UI.Components.Footer />
2024-06-07 23:49:11 -05:00
@code {
2024-06-01 22:47:56 -05:00
[Parameter] public Guid Id { get; set; }
[CascadingParameter] public bool Connected { get; set; }
[CascadingParameter] public bool OfflineMode { get; set; }
2024-06-11 00:26:17 -05:00
2024-11-15 02:24:30 -06:00
Models.ListItem SelectedItem { get; set; }
2024-05-23 23:41:38 -05:00
2024-06-01 22:47:56 -05:00
Data.Models.Game SelectedGame { get; set; }
SDK.Models.Game RemoteGame { get; set; }
2024-06-01 22:47:56 -05:00
Settings Settings = SettingService.GetSettings();
protected override async Task OnInitializedAsync()
2024-05-29 02:02:40 -05:00
{
InstallService.OnQueueChanged += OnQueueChanged;
InstallService.OnInstallFail += OnInstallFail;
InstallService.OnInstallComplete += OnInstallComplete;
2025-01-27 00:04:42 -06:00
GameService.OnUninstall += OnUninstall;
GameService.OnUninstallComplete += OnUninstallComplete;
2024-08-09 01:55:39 -05:00
await LoadData();
2024-05-29 02:02:40 -05:00
}
2024-06-01 22:47:56 -05:00
protected override async Task OnParametersSetAsync()
{
if (Id != Guid.Empty)
{
await OnLibraryItemSelected(await LibraryService.GetItemAsync(Id));
2024-06-01 22:47:56 -05:00
if (SelectedGame != null && (Connected && !OfflineMode))
RemoteGame = await Client.Games.GetAsync(SelectedGame.Id);
}
2024-06-01 22:47:56 -05:00
await InvokeAsync(StateHasChanged);
}
2024-08-09 01:55:39 -05:00
async Task LoadData()
{
2024-11-09 17:15:04 -06:00
await LibraryService.RefreshItemsAsync();
2024-05-29 02:02:40 -05:00
2024-08-09 01:55:39 -05:00
await InvokeAsync(StateHasChanged);
}
async Task SelectLibraryItem(Guid id)
{
NavigationManager.NavigateTo($"/{id}");
}
2024-11-09 17:15:04 -06:00
async Task OnLibraryItemSelected(Models.ListItem item)
2024-05-23 23:41:38 -05:00
{
2024-06-24 18:44:32 -05:00
if (item != null && item.DataItem is Data.Models.Game)
{
2024-06-01 22:47:56 -05:00
SelectedItem = item;
SelectedGame = item.DataItem as Data.Models.Game;
2024-05-29 02:02:40 -05:00
2024-08-09 01:55:39 -05:00
await InvokeAsync(StateHasChanged);
}
}
2024-11-09 17:15:04 -06:00
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 != null && addons.Any()))
{
var modalOptions = new ModalOptions()
{
Title = LocalizationService.GetString("InstallGame", item.Name),
Maximizable = false,
DefaultMaximized = false,
Closable = true,
OkText = LocalizationService.GetString("Install"),
Draggable = true,
Centered = true,
WrapClassName = "ant-modal-wrap-no-padding",
Footer = null,
};
2024-11-09 17:15:04 -06:00
var modalRef = ModalService.CreateModal<InstallDialog, Models.ListItem, string>(modalOptions, item);
}
else
{
await InstallService.Add(game);
}
}
2024-05-25 22:21:04 -05:00
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)
{
2024-11-09 17:15:04 -06:00
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:
2024-11-09 17:15:04 -06:00
SelectedItem.State = ListItemState.Installing;
break;
case SDK.Enums.InstallStatus.Queued:
2024-11-09 17:15:04 -06:00
SelectedItem.State = ListItemState.Queued;
break;
case SDK.Enums.InstallStatus.Failed:
case SDK.Enums.InstallStatus.Canceled:
2024-11-09 17:15:04 -06:00
SelectedItem.State = ListItemState.NotInstalled;
break;
case SDK.Enums.InstallStatus.Complete:
2024-11-09 17:15:04 -06:00
SelectedItem.State = ListItemState.Installed;
break;
}
await OnLibraryItemSelected(SelectedItem);
await InvokeAsync(StateHasChanged);
}
}
async Task OnInstallComplete(Data.Models.Game game)
{
2024-08-09 01:55:39 -05:00
await LoadData();
if (SelectedItem.DataItem is Game selectedGame)
{
if (selectedGame.Id == game.Id)
2024-11-09 17:15:04 -06:00
await OnLibraryItemSelected(LibraryService.Items.FirstOrDefault(i => i.Key == selectedGame.Id));
}
}
async Task OnInstallFail(Data.Models.Game game)
{
var result = await ConfirmService.Show(
LocalizationService.GetString("InstallationFailedMessage", game.Title),
LocalizationService.GetString("InstallationFailed"),
ConfirmButtons.RetryCancel,
ConfirmIcon.Error
);
await LibraryService.LibraryChanged();
if (result == ConfirmResult.Retry)
{
2024-11-09 17:15:04 -06:00
var libraryItem = LibraryService.GetItem(game.Id);
Install(libraryItem);
}
}
2025-01-27 00:04:42 -06:00
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)
{
2024-08-09 01:55:39 -05:00
await LoadData();
2025-01-27 00:04:42 -06:00
if (SelectedItem.Key == game.Id)
{
2025-01-27 00:04:42 -06:00
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));
2024-06-08 00:04:12 -05:00
if (totalTime.TotalMinutes < 1)
return LocalizationService.GetString("None");
2024-06-08 00:04:12 -05:00
else if (totalTime.TotalHours < 1)
return LocalizationService.GetString("PlayTimeMinutes", totalTime.TotalMinutes.ToString("0"));
2024-06-08 00:04:12 -05:00
else
return LocalizationService.GetString("PlayTimeHours", totalTime.TotalHours.ToString("0.##"));
}
string GetLastPlayed(Data.Models.Game game)
{
var lastSession = game.PlaySessions.Where(ps => ps.End != null && ps.Start != null).OrderByDescending(ps => ps.End).FirstOrDefault();
2024-06-07 23:58:38 -05:00
if (lastSession == null)
return LocalizationService.GetString("Never");
2024-06-07 23:58:38 -05:00
else
return lastSession.End.Value.ToRelativeDate();
}
public void Dispose()
{
InstallService.OnQueueChanged -= OnQueueChanged;
InstallService.OnInstallFail -= OnInstallFail;
InstallService.OnInstallComplete -= OnInstallComplete;
GameService.OnUninstall -= OnUninstall;
GameService.OnUninstallComplete -= OnUninstallComplete;
}
}