@using System.Threading @using PlaylistShared.Shared.DTO @using PlaylistShared.Shared.Yandex @inject HttpClient Http @inject ISnackbar Snackbar @inject IJSRuntime JsRuntime Авторизация Яндекс.Музыки по QR @if (_qrUrl != null) { Отсканируйте QR-код приложением Яндекс Статус: @_statusText @if (_isWaiting) { } @if (_isError) { @_errorMessage } } else { } Отмена @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>("/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>($"/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(); } }