LANCommander/LANCommander.Launcher/UI/Authenticate/Components/ServerSelector.razor

171 lines
5.1 KiB
Text
Raw Permalink Normal View History

@using LANCommander.Launcher.Models
@using LANCommander.SDK.Models
@using ListItem = AntDesign.ListItem
@inject NavigationManager NavigationManager
2025-01-15 02:28:11 -06:00
@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;
2025-01-15 02:28:11 -06:00
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;
2025-01-15 02:28:11 -06:00
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);
2025-01-15 02:28:11 -06:00
}
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();
}
}