diff --git a/PlaylistShared.Pwa/Components/AudioPlayer.razor b/PlaylistShared.Pwa/Components/AudioPlayer.razor index d2be21d..20ed141 100644 --- a/PlaylistShared.Pwa/Components/AudioPlayer.razor +++ b/PlaylistShared.Pwa/Components/AudioPlayer.razor @@ -59,6 +59,7 @@ [Inject] protected IJSRuntime JS { get; set; } = null!; [Inject] private TokenStorage TokenStorage { get; set; } = null!; + [Inject] private PlayerStorage PlayerStorage { get; set; } = null!; [Inject] private AuthenticationStateProvider AuthProvider { get; set; } = null!; [Inject] private ISnackbar Snackbar { get; set; } = null!; @@ -76,6 +77,8 @@ if (firstRender) { await EnsureAudioModuleAsync(); + await ChangeVolume(await PlayerStorage.GetVolumeAsync()); + StateHasChanged(); } } @@ -97,7 +100,7 @@ if (double.IsNaN(currentTime) || double.IsNaN(duration) || double.IsInfinity(currentTime) || double.IsInfinity(duration)) return; if (duration <= 0) return; - + _currentProgress = (currentTime / duration) * 100; _currentTime = FormatTime(currentTime); // Длительность не обновляем здесь @@ -123,10 +126,10 @@ private async Task CheckAuthAsync() { if (!RequireAuth) return true; - + var authState = await AuthProvider.GetAuthenticationStateAsync(); var isAuthenticated = authState.User.Identity?.IsAuthenticated == true; - + if (!isAuthenticated) { Snackbar.Add("Воспроизведение доступно только авторизованным пользователям", Severity.Warning); @@ -141,13 +144,13 @@ var tokens = await TokenStorage.GetTokensAsync(); var accessToken = tokens.token; - + if (string.IsNullOrWhiteSpace(accessToken) && string.IsNullOrWhiteSpace(SharedPlaylistId)) { Snackbar.Add("Токен авторизации не найден. Пожалуйста, войдите заново.", Severity.Error); return; } - + var streamUrl = new Uri(Http.BaseAddress!, $"/api/audio/track/{trackId}").ToString(); await EnsureAudioModuleAsync(); @@ -160,7 +163,7 @@ public async Task PlayAsync() { if (!await CheckAuthAsync()) return; - + if (_audioElement == null) return; await _audioElement.InvokeVoidAsync("play"); _isPlaying = true; @@ -226,6 +229,8 @@ var volume = value / 100; await _audioElement.InvokeVoidAsync("setVolume", volume); _isMuted = false; + _currentVolume = value; + await PlayerStorage.SetVolumeAsync(value); StateHasChanged(); } catch (Exception ex) diff --git a/PlaylistShared.Pwa/Program.cs b/PlaylistShared.Pwa/Program.cs index 8c7764a..dcfaa94 100644 --- a/PlaylistShared.Pwa/Program.cs +++ b/PlaylistShared.Pwa/Program.cs @@ -21,6 +21,7 @@ internal class Program }); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(sp => sp.GetRequiredService()); builder.Services.AddScoped(); diff --git a/PlaylistShared.Pwa/Services/PlayerStorage.cs b/PlaylistShared.Pwa/Services/PlayerStorage.cs new file mode 100644 index 0000000..e5db875 --- /dev/null +++ b/PlaylistShared.Pwa/Services/PlayerStorage.cs @@ -0,0 +1,30 @@ +using Microsoft.JSInterop; + +namespace PlaylistShared.Pwa.Services; + +public class PlayerStorage +{ + private readonly IJSRuntime _js; + private const string VolumeKey = "audio_player_volume"; + + public PlayerStorage(IJSRuntime js) => _js = js; + + public async Task SetVolumeAsync(double volume) + { + await _js.InvokeVoidAsync("localStorage.setItem", VolumeKey, volume); + } + + public async Task GetVolumeAsync() + { + var volume = await _js.InvokeAsync("localStorage.getItem", VolumeKey); + + if (double.TryParse(volume, out var result)) + { + result = Math.Clamp(result, 0, 100); + + return result; + } + + return 0; + } +} \ No newline at end of file diff --git a/PlaylistShared.Pwa/Services/TokenStorage.cs b/PlaylistShared.Pwa/Services/TokenStorage.cs index e7de939..5e5cd4d 100644 --- a/PlaylistShared.Pwa/Services/TokenStorage.cs +++ b/PlaylistShared.Pwa/Services/TokenStorage.cs @@ -28,4 +28,4 @@ public class TokenStorage await _js.InvokeVoidAsync("localStorage.removeItem", TokenKey); await _js.InvokeVoidAsync("localStorage.removeItem", RefreshTokenKey); } -} \ No newline at end of file +}