LANCommander/LANCommander.Launcher/UI/Authenticate/Components/ServerSelector.razor
Pat Hartl 5a32bbf890 Add localization support to launcher
Adds localization across the launcher and includes English, German, Spanish, French, Italian, Japanese, Korean, Dutch, Portuguese, Ukranian, and Chinese. These localizations were generated by Claude 3.5 and need to be reviewed by a human for accuracy.
2025-08-18 21:29:38 -05:00

171 lines
No EOL
5.1 KiB
Text

@using LANCommander.Launcher.Models
@using LANCommander.SDK.Models
@using ListItem = AntDesign.ListItem
@inject NavigationManager NavigationManager
@inject SDK.Client Client
@inject AuthenticationService AuthenticationService
@inject LocalizationService LocalizationService
<PageHeader>
<TitleTemplate>
@LocalizationService.GetString("Connect")
</TitleTemplate>
</PageHeader>
<Form Model="Model" OnFinish="() => SelectServer(ServerAddress)">
@if (OfflineModeAvailable)
{
<Alert Message="@LocalizationService.GetString("ServerOfflineMessage")" Type="AlertType.Warning" ShowIcon="true" Style="margin-bottom: 16px;" />
}
<FormItem>
<Flex Gap="FlexGap.Small">
<Input @bind-Value="ServerAddress" Placeholder="@LocalizationService.GetString("ServerAddressPlaceholder")" AutoFocus Disabled="Connecting" />
<Button Type="ButtonType.Primary" HtmlType="submit" Disabled="Connecting" Loading="Connecting">@LocalizationService.GetString("Connect")</Button>
@if (OfflineModeAvailable)
{
<Button OnClick="() => OfflineMode()">@LocalizationService.GetString("Offline")</Button>
}
</Flex>
</FormItem>
</Form>
<Divider Text="@LocalizationService.GetString("Discovered")" Orientation="DividerOrientation.Center" />
<AntList DataSource="DiscoveredServers">
<ChildContent>
<ListItem OnClick="() => SelectServer(context.Address.ToString())">
<ListItemMeta Title="@context.Name" Description="@context.Address.ToString()"/>
</ListItem>
</ChildContent>
<LoadMore>
<Flex Justify="FlexJustify.Center" Class="load-more">
@if (BeaconActive)
{
<Dropdown Trigger="@(new [] { Trigger.Hover })">
<Overlay>
<Menu>
<MenuItem Key="Cancel" OnClick="CancelBeacon">@LocalizationService.GetString("Cancel")</MenuItem>
</Menu>
</Overlay>
<ChildContent>
<Button Type="ButtonType.Primary" Loading="true" Disabled>@LocalizationService.GetString("Scanning")</Button>
</ChildContent>
</Dropdown>
}
else
{
<Button Type="ButtonType.Primary" OnClick="() => ActivateBeacon()">@LocalizationService.GetString("Rescan")</Button>
}
</Flex>
</LoadMore>
</AntList>
@code {
[Parameter] public EventCallback<string> OnSelected { get; set; }
[Parameter] public bool Connecting { get; set; } = false;
bool IsInitializing = false;
bool BeaconActive = false;
bool OfflineModeAvailable = false;
string ServerAddress = String.Empty;
AuthRequest Model = new();
List<DiscoveredServer> DiscoveredServers = new();
private CancellationTokenSource DiscoveryToken = new CancellationTokenSource();
Models.Settings Settings = SettingService.GetSettings();
protected override async Task OnInitializedAsync()
{
IsInitializing = true;
if (Client.IsConfigured())
{
ServerAddress = Client.GetServerAddress() ?? string.Empty;
}
Connecting = true;
OfflineModeAvailable = await AuthenticationService.OfflineModeAvailableAsync();
Client.Beacon.OnBeaconResponse += OnBeaconResponse;
if (!OfflineModeAvailable)
{
ActivateBeacon();
}
Connecting = false;
IsInitializing = false;
}
private void OnBeaconResponse(object sender, BeaconResponseArgs e)
{
var discoveredServer = new DiscoveredServer(e.Message, e.EndPoint);
if (DiscoveredServers.All(s => s.Address != discoveredServer.Address))
DiscoveredServers.Add(discoveredServer);
}
async Task SelectServer(string serverAddress)
{
await Client.Beacon.StopProbeAsync();
BeaconActive = false;
if (OnSelected.HasDelegate)
await OnSelected.InvokeAsync(serverAddress);
}
void OfflineMode()
{
AuthenticationService.LoginOffline();
NavigationManager.NavigateTo("/", forceLoad: true);
}
void CancelBeacon()
{
DiscoveryToken?.Cancel();
}
async Task ActivateBeacon()
{
try
{
BeaconActive = true;
await InvokeAsync(StateHasChanged);
// give the UI a chance to render:
await Task.Yield();
if ((DiscoveryToken?.TryReset() ?? false) == false)
{
DiscoveryToken = new();
}
await Client.Beacon.StartProbeAsync(cancellationToken: DiscoveryToken.Token);
await Task.Delay(10000, DiscoveryToken.Token);
await Client.Beacon.StopProbeAsync();
}
catch (OperationCanceledException)
{
// ignore, handled in finally
}
finally
{
Client.Beacon.CleanupProbe();
BeaconActive = false;
await InvokeAsync(StateHasChanged);
}
}
public void Dispose()
{
DiscoveryToken?.Cancel();
DiscoveryToken?.Dispose();
}
}