From bcdbfdbce3cea26bc38b730a9affd51ff3a68899 Mon Sep 17 00:00:00 2001 From: Pat Hartl Date: Fri, 29 May 2026 02:19:00 -0500 Subject: [PATCH] Add HQ login process to first time setup --- .../UI/Pages/FirstTimeSetup/Metadata.razor | 320 +++++++++++++++--- 1 file changed, 279 insertions(+), 41 deletions(-) diff --git a/LANCommander.Server/UI/Pages/FirstTimeSetup/Metadata.razor b/LANCommander.Server/UI/Pages/FirstTimeSetup/Metadata.razor index 94af130a..bb4d8ad9 100644 --- a/LANCommander.Server/UI/Pages/FirstTimeSetup/Metadata.razor +++ b/LANCommander.Server/UI/Pages/FirstTimeSetup/Metadata.razor @@ -1,59 +1,192 @@ -@page "/FirstTimeSetup/Metadata" +@page "/FirstTimeSetup/Metadata" @using LANCommander.Server.Settings +@using LANCommander.HQ.SDK @using Microsoft.Extensions.Options +@implements IDisposable @layout FirstTimeSetupLayout @inject SetupService SetupService @inject SettingsProvider SettingsProvider @inject IOptions Settings +@inject HQClient HqClient @inject NavigationManager NavigationManager +@inject IMessageService MessageService +@inject IJSRuntime JS @inject ILogger Logger Metadata Connections - First Time Setup -
- - LANCommander has the ability to pull metadata and media from external sources. Required credentials can be added here, or can be set later in Settings. - +@if (_metadataChoice == MetadataChoice.None) +{ + + LANCommander can pull metadata and media from external sources. Choose how you'd like to get your metadata. - + Connect your server to LANCommander HQ for access to expanded metadata providers, faster lookups, and premium features. All through one account. -

- LANCommander HQ provides access to multiple metadata and media providers through a single connection. Connect your account in Settings > Integrations > LANCommander HQ after setup. -

+ + + + + + Access more metadata providers + + + + Faster metadata lookups + + + + One-time authentication + + + + No additional server setup + + + - + + + $5/mo + + + + + + Everything in Basic + + + + Premium metadata providers + + + + Curated & enhanced metadata + + + + Supports LANCommander development + + + + + -

- In order to use IGDB metadata, you need a Twitch developer account. Click here for more details. -

+ + + - - - - - - + - + + Or configure IGDB and SteamGridDB with your own API keys. + + -

- In order to automatically search SteamGridDB for media, you need an API key. Click here to get your key. -

- - - - - - - + - - - +
+} +else if (_metadataChoice == MetadataChoice.HQ) +{ +

+ Connect your server to LANCommander HQ. +

+ + @if (_hqConnected) + { + @if (_hqIsPremium) + { + + + + + + } + else + { + + + + + + } + + + + + + + + + + } + else + { + + + + + + + + + + + + + + + } +} +else if (_metadataChoice == MetadataChoice.OwnProviders) +{ +
+ + +

+ In order to use IGDB metadata, you need a Twitch developer account. Click here for more details. +

+ + + + + + + + + + +

+ In order to automatically search SteamGridDB for media, you need an API key. Click here to get your key. +

+ + + + + + + + + + + + + + + + +} @code { [CascadingParameter] @@ -61,6 +194,20 @@ bool Loading = false; + MetadataChoice _metadataChoice = MetadataChoice.None; + bool _hqConnected; + bool _hqIsPremium; + bool _awaitingAuth; + Timer? _pollTimer; + bool _disposed; + + enum MetadataChoice + { + None, + HQ, + OwnProviders + } + protected override async Task OnInitializedAsync() { var isSetupInitialized = await SetupService.IsSetupInitialized(); @@ -72,15 +219,84 @@ await Layout.ChangeCurrentStep(FirstTimeSetupStep.Metadata); - SettingsProvider.Update(s => - { - s.Server.IGDB.ClientId = Settings.Value.Server.IGDB.ClientId; - s.Server.IGDB.ClientSecret = Settings.Value.Server.IGDB.ClientSecret; - s.Server.Media.SteamGridDbApiKey = Settings.Value.Server.Media.SteamGridDbApiKey; - }); + await CheckHQStatus(); } - async Task ValidateMetadataConnections() + async Task CheckHQStatus() + { + try + { + if (!SettingsProvider.CurrentValue.Server.HQ.IsAuthenticated) + { + _hqConnected = false; + return; + } + + var profile = await HqClient.Auth.GetCurrentUserAsync(); + + if (profile is not null) + { + _hqConnected = true; + _hqIsPremium = profile.IsPremium; + } + else + _hqConnected = false; + } + catch + { + _hqConnected = false; + } + } + + async Task ConnectHQ() + { + var baseUrl = Settings.Value.Server.HQ.BaseUrl.TrimEnd('/'); + var callbackUrl = NavigationManager.BaseUri.TrimEnd('/') + "/api/hq/callback"; + var loginUrl = $"{baseUrl}/auth/login?returnUrl={Uri.EscapeDataString(callbackUrl)}"; + + await JS.InvokeVoidAsync("open", loginUrl, "hq_auth", "width=600,height=700,menubar=no,toolbar=no"); + + _awaitingAuth = true; + + _pollTimer = new Timer(async _ => + { + if (_disposed) + return; + + if (SettingsProvider.CurrentValue.Server.HQ.IsAuthenticated) + { + await InvokeAsync(async () => + { + if (_disposed) + return; + + _awaitingAuth = false; + _hqConnected = true; + StopPolling(); + + MessageService.Success("Successfully connected to LANCommander HQ!"); + + StateHasChanged(); + }); + } + }, null, TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(2)); + } + + async Task DisconnectHQ() + { + SettingsProvider.Update(s => + { + s.Server.HQ.AccessToken = string.Empty; + s.Server.HQ.TokenExpiresAt = null; + }); + + _hqConnected = false; + _hqIsPremium = false; + + MessageService.Success("Disconnected from LANCommander HQ."); + } + + async Task SaveOwnProviders() { SettingsProvider.Update(s => { @@ -91,4 +307,26 @@ NavigationManager.NavigateTo("/FirstTimeSetup/Administrator"); } + + void Skip() + { + NavigationManager.NavigateTo("/FirstTimeSetup/Administrator"); + } + + void Next() + { + NavigationManager.NavigateTo("/FirstTimeSetup/Administrator"); + } + + void StopPolling() + { + _pollTimer?.Dispose(); + _pollTimer = null; + } + + public void Dispose() + { + _disposed = true; + StopPolling(); + } }