147 lines
4.9 KiB
Plaintext
147 lines
4.9 KiB
Plaintext
@using System.Threading
|
||
@using PlaylistShared.Shared.DTO
|
||
@using PlaylistShared.Shared.Yandex
|
||
@inject HttpClient Http
|
||
@inject ISnackbar Snackbar
|
||
@inject IJSRuntime JsRuntime
|
||
|
||
<MudDialog>
|
||
<TitleContent>
|
||
<MudText Typo="Typo.h6">Авторизация Яндекс.Музыки по QR</MudText>
|
||
</TitleContent>
|
||
<DialogContent>
|
||
@if (_qrUrl != null)
|
||
{
|
||
<div style="text-align: center;">
|
||
<MudText Typo="Typo.body2" Class="mb-2">Отсканируйте QR-код приложением Яндекс</MudText>
|
||
<MudImage Src="@_qrUrl" Style="max-width: 250px; border-radius: 12px; background-color: white;" />
|
||
<MudText Typo="Typo.body2" Class="mt-2" Color="Color.Secondary">
|
||
Статус: @_statusText
|
||
</MudText>
|
||
@if (_isWaiting)
|
||
{
|
||
<MudProgressCircular Indeterminate Class="mt-2" Size="Size.Small" />
|
||
}
|
||
@if (_isError)
|
||
{
|
||
<MudAlert Severity="Severity.Error" Class="mt-4">
|
||
@_errorMessage
|
||
</MudAlert>
|
||
}
|
||
</div>
|
||
}
|
||
else
|
||
{
|
||
<MudProgressCircular Indeterminate />
|
||
}
|
||
</DialogContent>
|
||
<DialogActions>
|
||
<MudButton Variant="Variant.Text" OnClick="Cancel">Отмена</MudButton>
|
||
</DialogActions>
|
||
</MudDialog>
|
||
|
||
@code {
|
||
[CascadingParameter] IMudDialogInstance MudDialog { get; set; }
|
||
|
||
private string _qrUrl;
|
||
private string _sessionId;
|
||
private string _statusText = "Ожидание сканирования";
|
||
private bool _isWaiting = true;
|
||
private bool _isError = false;
|
||
private string _errorMessage = "";
|
||
private CancellationTokenSource _cts;
|
||
|
||
protected override async Task OnInitializedAsync()
|
||
{
|
||
await StartQrFlow();
|
||
}
|
||
|
||
private async Task StartQrFlow()
|
||
{
|
||
try
|
||
{
|
||
// 1. Получить QR и sessionId
|
||
var response = await Http.GetFromJsonAsync<ApiResponse<YandexAuthQr>>("/api/yandexaccount/qr");
|
||
if (!response.Success || response.Data == null)
|
||
{
|
||
ShowError("Не удалось получить QR-код");
|
||
return;
|
||
}
|
||
|
||
_qrUrl = response.Data.QrLink;
|
||
_sessionId = response.Data.SessionId;
|
||
|
||
// 2. Начать опрос статуса
|
||
_cts = new CancellationTokenSource();
|
||
_ = PollStatus(_cts.Token);
|
||
StateHasChanged();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
ShowError(ex.Message);
|
||
}
|
||
}
|
||
|
||
private async Task PollStatus(CancellationToken token)
|
||
{
|
||
while (!token.IsCancellationRequested)
|
||
{
|
||
try
|
||
{
|
||
await Task.Delay(500, token);
|
||
var statusResponse = await Http.GetFromJsonAsync<ApiResponse<YandexAuthQrCheck>>($"/api/yandexaccount/qr/{_sessionId}", token);
|
||
if (statusResponse?.Data != null)
|
||
{
|
||
switch (statusResponse.Data.Status)
|
||
{
|
||
case Shared.Enums.YandexAuthQrStatus.Pending:
|
||
_statusText = "Ожидание подтверждения...";
|
||
break;
|
||
case Shared.Enums.YandexAuthQrStatus.Authorized:
|
||
_statusText = "Авторизация успешна!";
|
||
_isWaiting = false;
|
||
Snackbar.Add("Авторизация выполнена", Severity.Success);
|
||
_cts?.Cancel();
|
||
MudDialog.Close(DialogResult.Ok(true));
|
||
return;
|
||
case Shared.Enums.YandexAuthQrStatus.Expired:
|
||
_cts?.Cancel();
|
||
ShowError("Срок действия QR-кода истёк");
|
||
return;
|
||
case Shared.Enums.YandexAuthQrStatus.Error:
|
||
_cts?.Cancel();
|
||
ShowError("Ошибка авторизации");
|
||
return;
|
||
}
|
||
StateHasChanged();
|
||
}
|
||
}
|
||
catch (TaskCanceledException) { break; }
|
||
catch (Exception ex)
|
||
{
|
||
ShowError(ex.Message);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
private void ShowError(string message)
|
||
{
|
||
_isError = true;
|
||
_errorMessage = message;
|
||
_isWaiting = false;
|
||
StateHasChanged();
|
||
}
|
||
|
||
private void Cancel()
|
||
{
|
||
_cts?.Cancel();
|
||
MudDialog.Close(DialogResult.Cancel());
|
||
}
|
||
|
||
public void Dispose()
|
||
{
|
||
_cts?.Cancel();
|
||
_cts?.Dispose();
|
||
}
|
||
} |