LANCommander/LANCommander.Server/UI/Pages/Games/Components/GameMetadataLookup.razor

261 lines
No EOL
8.3 KiB
Text

@using AntDesign.TableModels;
@using LANCommander.PCGamingWiki
@using LANCommander.SDK.Enums
@inject IGDBService IGDBService
@inject NavigationManager NavigationManager
@inject IMessageService MessageService
@inject ILogger<GameMetadataLookup> Logger
@{
RenderFragment Footer =
@<Template>
<Button OnClick="SelectGame" Disabled="@(Loading || (SelectedResults != null && SelectedResults.Count() == 0) || Results.Count() == 0)" Type="ButtonType.Primary">Select</Button>
<Button OnClick="() => ModalVisible = false">Cancel</Button>
</Template>;
}
<Modal Visible="ModalVisible" Title="Game Metadata Lookup" Footer="@Footer" Class="game-metadata-lookup-modal" OnCancel="Close">
<Table
@ref="ResultsTable"
TItem="Game"
DataSource="Results"
HidePagination="true"
Loading="Loading"
OnRowClick="OnRowClicked"
@bind-SelectedRows="SelectedResults"
Responsive>
<Selection Key="@context.IGDBId.ToString()" Type="SelectionType.Radio" />
<PropertyColumn Property="g => g.Title" Title="Title" />
<PropertyColumn Property="g => g.ReleasedOn" Format="MM/dd/yyyy" Title="Released" />
<PropertyColumn Property="g => g.Developers">
@String.Join(", ", context.Developers?.Select(d => d.Name))
</PropertyColumn>
</Table>
@if (MoreResults && IGDBService.Authenticated)
{
<Button Type="ButtonType.Primary" OnClick="ShowMore" Block>Show More</Button>
}
</Modal>
@if (IGDBService.Authenticated)
{
<Flex Gap="FlexGap.Small">
<Input @bind-Value="Value" BindOnInput="true" OnkeyDown="SearchFieldOnKeyDown" OnChange="ValueChanged" />
<Button OnClick="() => SearchForGame(Value)" Type="ButtonType.Primary" Disabled="@(String.IsNullOrWhiteSpace(Value))">@ButtonText</Button>
</Flex>
}
else
{
<Flex Gap="FlexGap.Small">
<Input @bind-Value="Value" BindOnInput="true" OnChange="ValueChanged" />
<Popconfirm OnConfirm="() => NavigateToSettings()" Title="Invalid IGDB credentials. Setup now?">
<Button Type="ButtonType.Primary">@ButtonText</Button>
</Popconfirm>
</Flex>
}
@code {
[Parameter] public EventCallback<GameLookupResult> OnResultSelected { get; set; }
[Parameter] public string ButtonText { get; set; }
[Parameter] public string Value { get; set; }
[Parameter] public EventCallback<string> ValueChanged { get; set; }
ITable? ResultsTable;
List<Game> Results { get; set; } = new List<Game>();
IEnumerable<Game> SelectedResults { get; set; }
PCGamingWikiClient PCGamingWikiClient { get; set; }
bool ModalVisible { get; set; } = false;
bool Loading = true;
bool MoreResults = false;
int Offset = 0;
protected override void OnInitialized()
{
PCGamingWikiClient = new PCGamingWikiClient();
}
private void OnRowClicked(RowData<Game> row)
{
ResultsTable.SetSelection(new string[] { row.Data.IGDBId.ToString() });
}
private async Task SearchFieldOnKeyDown(KeyboardEventArgs e)
{
if ((e.Code == "Enter" || e.Code == "NumpadEnter") && !String.IsNullOrWhiteSpace(Value))
await SearchForGame(Value);
}
private async Task SearchForGame(string title, bool newSearch = true)
{
try
{
Loading = true;
ModalVisible = true;
if (newSearch)
{
Results = new List<Game>();
Offset = 0;
}
int limit = 10;
string[] fields = new string[]
{
"involved_companies.developer",
"involved_companies.publisher",
"involved_companies.company.name"
};
var results = await IGDBService.SearchAsync(title, limit, Offset, fields);
MoreResults = results.Count() == limit;
Loading = false;
if (results == null)
Results = new List<Game>();
else
{
Results.AddRange(results.Select(r =>
{
var result = new Game()
{
IGDBId = r.Id.GetValueOrDefault(),
Title = r.Name,
ReleasedOn = r.FirstReleaseDate.GetValueOrDefault().UtcDateTime,
Developers = new List<Company>(),
Publishers = new List<Company>()
};
if (r.InvolvedCompanies != null && r.InvolvedCompanies.Values != null)
{
result.Developers = r.InvolvedCompanies.Values.Where(c => c.Developer.HasValue && c.Developer.GetValueOrDefault() && c.Company != null && c.Company.Value != null).Select(c => new Company()
{
Name = c.Company.Value.Name
}).ToList();
result.Publishers = r.InvolvedCompanies.Values.Where(c => c.Publisher.HasValue && c.Publisher.GetValueOrDefault() && c.Company != null && c.Company.Value != null).Select(c => new Company()
{
Name = c.Company.Value.Name
}).ToList();
}
return result;
}));
}
}
catch (Exception ex)
{
MessageService.Error("An unknown error occurred when retrieving IGDB metadata");
Logger.LogError(ex, "An unknown error occurred when retrieving IGDB metadata");
Loading = false;
ModalVisible = false;
}
}
private async Task SelectGame()
{
Loading = true;
var result = new GameLookupResult();
string[] fields = new string[]
{
"genres.*",
"game_modes.*",
"multiplayer_modes.*",
"release_dates.*",
"platforms.*",
"keywords.*",
"involved_companies.developer",
"involved_companies.publisher",
"involved_companies.company.name",
"cover.*",
"game_engines.*"
};
result.IGDBMetadata = await IGDBService.GetAsync(SelectedResults.First().IGDBId.GetValueOrDefault(), fields);
result.MultiplayerModes = await GetMultiplayerModes(result.IGDBMetadata.Name);
await OnResultSelected.InvokeAsync(result);
Close();
}
private void Close()
{
Results = new List<Game>();
MoreResults = false;
Offset = 0;
ModalVisible = false;
}
private async Task ShowMore()
{
MoreResults = false;
Offset += Results.Count;
await SearchForGame(Value, false);
}
private async Task<ICollection<MultiplayerMode>> GetMultiplayerModes(string gameTitle)
{
var multiplayerModes = new List<MultiplayerMode>();
try
{
var playerCounts = await PCGamingWikiClient.GetMultiplayerPlayerCounts(gameTitle);
if (playerCounts != null)
{
foreach (var playerCount in playerCounts)
{
MultiplayerType type;
switch (playerCount.Key)
{
case "Local Play":
type = MultiplayerType.Local;
break;
case "LAN Play":
type = MultiplayerType.LAN;
break;
case "Online Play":
type = MultiplayerType.Online;
break;
default:
continue;
}
multiplayerModes.Add(new MultiplayerMode()
{
Type = type,
MaxPlayers = playerCount.Value,
MinPlayers = 2
});
}
}
}
catch (Exception ex)
{
Logger?.LogError(ex, "Could not retrieve multiplayer modes from PCGamingWiki");
}
return multiplayerModes;
}
private void NavigateToSettings()
{
NavigationManager.NavigateTo("/Settings/General", true);
}
}