diff --git a/PlaylistShared.Pwa/Components/Common/TrackCoverWithPlay.razor b/PlaylistShared.Pwa/Components/Common/TrackCoverWithPlay.razor index 24ffde5..a199b5b 100644 --- a/PlaylistShared.Pwa/Components/Common/TrackCoverWithPlay.razor +++ b/PlaylistShared.Pwa/Components/Common/TrackCoverWithPlay.razor @@ -1,11 +1,12 @@ @using Microsoft.AspNetCore.Components.Web +@using PlaylistShared.Shared.DTO @inject IAudioPlayerService AudioPlayerService - + @if (CanPlay && (_isHovered || IsCurrentTrackPlaying)) { @@ -20,8 +21,7 @@ @code { - [Parameter] public string CoverUrl { get; set; } = string.Empty; - [Parameter] public string TrackTitle { get; set; } = string.Empty; + [Parameter] public YandexTrack? Track { get; set; } = null; [Parameter] public string TrackId { get; set; } = string.Empty; [Parameter] public int Height { get; set; } = 50; [Parameter] public int Width { get; set; } = 50; @@ -53,8 +53,7 @@ await AudioPlayerService.LoadAndPlayAsync( trackId: TrackId, playlistShareToken: playlistShareToken, - title: TrackTitle, - coverUrl: CoverUrl); + track: Track); } } diff --git a/PlaylistShared.Pwa/Components/Common/TrackItem.razor b/PlaylistShared.Pwa/Components/Common/TrackItem.razor index eaacc8e..3d2bd04 100644 --- a/PlaylistShared.Pwa/Components/Common/TrackItem.razor +++ b/PlaylistShared.Pwa/Components/Common/TrackItem.razor @@ -5,9 +5,8 @@ - diff --git a/PlaylistShared.Pwa/Components/Global/AudioPlayer.razor b/PlaylistShared.Pwa/Components/Global/AudioPlayer.razor index ca27fd4..5c66296 100644 --- a/PlaylistShared.Pwa/Components/Global/AudioPlayer.razor +++ b/PlaylistShared.Pwa/Components/Global/AudioPlayer.razor @@ -7,20 +7,21 @@ @inject ISnackbar Snackbar @inject HttpClient Http - + + Class="relative d-inline-block rounded-sm overflow-hidden" + style="cursor: pointer; width: 50px; height: 50px;"> - @if (!string.IsNullOrEmpty(AudioPlayerService.CurrentTrackCoverUrl)) + @if (!string.IsNullOrEmpty(AudioPlayerService.CurrentTrack?.CoverUri)) { - + } - + - - + - - - @AudioPlayerService.CurrentTrackTitle - + + + + @AudioPlayerService.CurrentTrack?.Title + + + + @if (AudioPlayerService.CurrentTrack != null) @string.Join(", ", AudioPlayerService.CurrentTrack.Artists) + + + + @AudioPlayerService.CurrentTimeString / @AudioPlayerService.TotalTimeString @@ -93,7 +102,7 @@ // Громкость private bool _volumeIsOpen; private double _volumeBeforeMute; - private double _bufferValue; + private double _bufferSecond; private bool _isPlayHovered; @@ -123,6 +132,7 @@ _audioElement = await _audioModule.InvokeAsync("init", _audioId, DotNetObjectReference.Create(this)); } + #region Обработка JS [JSInvokable] public async Task OnAudioEnded() { @@ -141,19 +151,9 @@ [JSInvokable] public async Task OnDownloadProgress(double second) { - _bufferValue = second / AudioPlayerService.TotalTime * 100; - } - - private async Task CheckAuthAsync() - { - var authState = await AuthProvider.GetAuthenticationStateAsync(); - if (!authState.User.Identity?.IsAuthenticated == true) - { - Snackbar.Add("Воспроизведение доступно только авторизованным пользователям", Severity.Warning); - return false; - } - return true; + _bufferSecond = second; } + #endregion #region Обработка сервиса private async Task OnServiceLoadAndPlay(string trackId, string? accessToken, string? sharedPlaylistId) @@ -222,6 +222,17 @@ } #endregion + private async Task CheckAuthAsync() + { + var authState = await AuthProvider.GetAuthenticationStateAsync(); + if (!authState.User.Identity?.IsAuthenticated == true) + { + Snackbar.Add("Воспроизведение доступно только авторизованным пользователям", Severity.Warning); + return false; + } + return true; + } + private async Task OnVolumeHandleWheel(WheelEventArgs e) { // Изменяем громкость на 5 единиц за один тик колесика diff --git a/PlaylistShared.Pwa/Services/AudioPlayerService.cs b/PlaylistShared.Pwa/Services/AudioPlayerService.cs index d8fb637..0cb3f0d 100644 --- a/PlaylistShared.Pwa/Services/AudioPlayerService.cs +++ b/PlaylistShared.Pwa/Services/AudioPlayerService.cs @@ -13,8 +13,7 @@ public class AudioPlayerService : IAudioPlayerService private readonly PlayerStorage _playerStorage; private string? _currentTrackId; - private string? _currentTrackTitle; - private string? _currentTrackCoverUrl; + private YandexTrack? _currentTrack; private bool _isPlaying; private double _currentVolume = 50; private double _currentProgress; @@ -24,8 +23,7 @@ public class AudioPlayerService : IAudioPlayerService private string _totalTimeString = "0:00"; public string? CurrentTrackId => _currentTrackId; - public string? CurrentTrackTitle => _currentTrackTitle; - public string? CurrentTrackCoverUrl => _currentTrackCoverUrl; + public YandexTrack? CurrentTrack => _currentTrack; public bool IsPlaying => _isPlaying; public double CurrentVolume { @@ -65,7 +63,7 @@ public class AudioPlayerService : IAudioPlayerService } // Внешние команды (вызываются из компонентов) - public async Task LoadAndPlayAsync(string trackId, string? accessToken = null, string? playlistShareToken = null, string? title = null, string? coverUrl = null) + public async Task LoadAndPlayAsync(string trackId, string? accessToken = null, string? playlistShareToken = null, YandexTrack? track = null) { if (_currentTrackId == trackId) { @@ -88,13 +86,11 @@ public class AudioPlayerService : IAudioPlayerService } // Если title и coverUrl не переданы, нужно запросить через API - if (string.IsNullOrEmpty(title) || string.IsNullOrEmpty(coverUrl)) + if (track is null) { try { - var trackInfo = await GetTrackInfo(trackId, accessToken, playlistShareToken); - title = trackInfo?.Title; - coverUrl = trackInfo?.CoverUri; + track = await GetTrackInfo(trackId, accessToken, playlistShareToken); } catch (Exception ex) { @@ -103,9 +99,7 @@ public class AudioPlayerService : IAudioPlayerService } } - _currentTrackId = trackId; - _currentTrackTitle = title ?? "Неизвестный трек"; - _currentTrackCoverUrl = coverUrl; + _currentTrack = track; _isPlaying = true; OnStateChanged?.Invoke(); OnLoadAndPlayRequested?.Invoke(trackId, accessToken, playlistShareToken); @@ -125,10 +119,9 @@ public class AudioPlayerService : IAudioPlayerService OnPauseRequested?.Invoke(); } - public async Task SeekToAsync(double percent) + public async Task SeekToAsync(double second) { - var newTime = (percent / 100) * _totalTime; - OnSeekRequested?.Invoke(newTime); + OnSeekRequested?.Invoke(second); } public async Task SetVolumeAsync(double volume) @@ -189,7 +182,7 @@ public class AudioPlayerService : IAudioPlayerService /// /// /// - private async Task<(string? Title, string? CoverUri)?> GetTrackInfo(string trackId, string? accessToken, string? sharedPlaylistId) + private async Task GetTrackInfo(string trackId, string? accessToken, string? sharedPlaylistId) { var url = $"/api/audio/track-info/{trackId}"; if (!string.IsNullOrEmpty(accessToken)) @@ -200,7 +193,7 @@ public class AudioPlayerService : IAudioPlayerService var response = await _http.GetFromJsonAsync>(url); if (response?.Success == true) { - return (response.Data.Title, response.Data.CoverUri); + return response.Data; } return null; } diff --git a/PlaylistShared.Pwa/Services/IAudioPlayerService.cs b/PlaylistShared.Pwa/Services/IAudioPlayerService.cs index da83a65..eb39ee7 100644 --- a/PlaylistShared.Pwa/Services/IAudioPlayerService.cs +++ b/PlaylistShared.Pwa/Services/IAudioPlayerService.cs @@ -1,4 +1,6 @@ -namespace PlaylistShared.Pwa.Services; +using PlaylistShared.Shared.DTO; + +namespace PlaylistShared.Pwa.Services; /// /// Глобальный сервис управления аудиоплеером. @@ -31,11 +33,8 @@ public interface IAudioPlayerService /// Отформатированная общая длительность (мм:сс). string TotalTimeString { get; } - /// Отформатированное название текущего трека. - string? CurrentTrackTitle { get; } - - /// URL обложки текущего трека. - string? CurrentTrackCoverUrl { get; } + /// Текущий трек. + YandexTrack? CurrentTrack { get; } #endregion #region Команды управления (вызываются из компонентов) @@ -45,7 +44,7 @@ public interface IAudioPlayerService /// ID расшаренного плейлиста (для неавторизованного доступа). /// Название трека. (Если не передано, вызывает api для получения) /// URL обложки трека. (Если не передано, вызывает api для получения) - Task LoadAndPlayAsync(string trackId, string? accessToken = null, string? playlistShareToken = null, string? title = null, string? coverUrl = null); + Task LoadAndPlayAsync(string trackId, string? accessToken = null, string? playlistShareToken = null, YandexTrack? track = null); /// Воспроизвести (если трек загружен и на паузе). Task PlayAsync(); @@ -53,8 +52,8 @@ public interface IAudioPlayerService /// Поставить на паузу. Task PauseAsync(); - /// Перемотать на указанный процент (0–100). - Task SeekToAsync(double percent); + /// Перемотать на секунды. + Task SeekToAsync(double second); /// Установить громкость (0–100). Task SetVolumeAsync(double volume);