From 362762a813687f0cbaafb19108637db1542d7d35 Mon Sep 17 00:00:00 2001 From: FrigaT Date: Thu, 23 Apr 2026 10:14:59 +0300 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20=D1=81=D1=82=D0=B0=D0=BD=D0=B4=D0=B0=D1=80=D1=82=D0=BD?= =?UTF-8?q?=D1=8B=D0=B9=20"=D0=BF=D0=BE=D0=B4=D0=B5=D0=BB=D0=B8=D1=82?= =?UTF-8?q?=D1=8C=D1=81=D1=8F=20=D0=9F=D0=9B"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Common/ShareDialog.razor | 45 +++++++++++ .../Pages/SharedPlaylistView.razor | 81 ++++++++++++++++++- PlaylistShared.Pwa/PlaylistShared.Pwa.csproj | 3 + PlaylistShared.Pwa/wwwroot/js/shareUtils.js | 19 +++++ 4 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 PlaylistShared.Pwa/Components/Common/ShareDialog.razor create mode 100644 PlaylistShared.Pwa/wwwroot/js/shareUtils.js diff --git a/PlaylistShared.Pwa/Components/Common/ShareDialog.razor b/PlaylistShared.Pwa/Components/Common/ShareDialog.razor new file mode 100644 index 0000000..6e82422 --- /dev/null +++ b/PlaylistShared.Pwa/Components/Common/ShareDialog.razor @@ -0,0 +1,45 @@ +@inject IJSRuntime JS +@inject ISnackbar Snackbar + + + + Поделиться плейлистом + + + + Скопируйте ссылку и отправьте её друзьям: + + + + + + Скопировать ссылку + + + Закрыть + + + + +@code { + [CascadingParameter] + private IMudDialogInstance MudDialog { get; set; } = default!; + + [Parameter] + public string ShareUrl { get; set; } = string.Empty; + + private async Task CopyToClipboard() + { + await JS.InvokeVoidAsync("navigator.clipboard.writeText", ShareUrl); + Snackbar.Add("Ссылка скопирована в буфер обмена!", Severity.Success); + MudDialog.Close(DialogResult.Ok(true)); + } + + private void Close() => MudDialog.Cancel(); +} \ No newline at end of file diff --git a/PlaylistShared.Pwa/Pages/SharedPlaylistView.razor b/PlaylistShared.Pwa/Pages/SharedPlaylistView.razor index 426e7df..169c4e4 100644 --- a/PlaylistShared.Pwa/Pages/SharedPlaylistView.razor +++ b/PlaylistShared.Pwa/Pages/SharedPlaylistView.razor @@ -16,6 +16,8 @@ @inject AuthenticationStateProvider AuthProvider @inject IDialogService DialogService @inject IAudioPlayerService AudioPlayerService +@inject IJSRuntime JS +@inject IDialogService DialogService @implements IDisposable @@ -32,18 +34,23 @@ @PlaylistCardHeaderContent + + + @if (_isCreator && _isAuthenticated) { } - + @@ -116,7 +123,10 @@ OnClick="ToggleFavorite" Disabled="@_favoriteLoading" /> - + + @if (_isCreator && _isAuthenticated) { Загрузка признака "фаворит". private bool _favoriteLoading; + + /******************************** + * Поделиться ссылкой + *********************************/ + private IJSObjectReference? _shareModule; + private bool _isWebShareSupported = false; protected override async Task OnInitializedAsync() { @@ -417,6 +433,18 @@ AudioPlayerService.OnEndedTrack += OnPlayerStateChanged; } + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + // Загружаем JS-модуль + _shareModule = await JS.InvokeAsync("import", "/js/shareUtils.js"); + // Проверяем поддержку Web Share API + _isWebShareSupported = await _shareModule.InvokeAsync("isSupported"); + StateHasChanged(); + } + } + private void OnPlayerStateChanged() { InvokeAsync(StateHasChanged); @@ -803,9 +831,58 @@ } #endregion + #region Поделитьсы ссылкой + /// Поделиться ссылкой + private async Task SharePlaylist() + { + if (_shareModule == null) return; + + var shareUrl = Navigation.Uri; + var shareTitle = "🎵 Поделиться плейлистом"; + var shareText = _playlist?.Title != null + ? $"Послушайте плейлист '{_playlist.Title}'!" + : "Послушайте этот плейлист!"; + + if (_isWebShareSupported) + { + var result = await _shareModule.InvokeAsync("shareLink", shareTitle, shareText, shareUrl); + if (result?.Success == false && !string.IsNullOrEmpty(result.Error) && !result.Cancelled) + { + Snackbar.Add($"Не удалось поделиться: {result.Error}", Severity.Warning); + await ShowShareDialog(shareUrl); + } + } + else + { + await ShowShareDialog(shareUrl); + } + } + + /// Модальное окно, чтобы поделиться ссылкой + private async Task ShowShareDialog(string url) + { + var parameters = new DialogParameters + { + { x => x.ShareUrl, url } + }; + var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small, FullWidth = true }; + await DialogService.ShowAsync("Поделиться", parameters, options); + } + + // Вспомогательный класс для результата + private class ShareResult + { + public bool Success { get; set; } + public string? Error { get; set; } + public bool Cancelled { get; set; } + } + #endregion + public void Dispose() { AudioPlayerService.OnStartedTrack -= OnPlayerStateChanged; AudioPlayerService.OnEndedTrack -= OnPlayerStateChanged; + + _shareModule?.DisposeAsync(); } } \ No newline at end of file diff --git a/PlaylistShared.Pwa/PlaylistShared.Pwa.csproj b/PlaylistShared.Pwa/PlaylistShared.Pwa.csproj index 4fb904a..d600199 100644 --- a/PlaylistShared.Pwa/PlaylistShared.Pwa.csproj +++ b/PlaylistShared.Pwa/PlaylistShared.Pwa.csproj @@ -28,6 +28,9 @@ Always + + Always + diff --git a/PlaylistShared.Pwa/wwwroot/js/shareUtils.js b/PlaylistShared.Pwa/wwwroot/js/shareUtils.js new file mode 100644 index 0000000..b99272d --- /dev/null +++ b/PlaylistShared.Pwa/wwwroot/js/shareUtils.js @@ -0,0 +1,19 @@ +export function isSupported() { + return !!navigator.share; +} + +export async function shareLink(title, text, url) { + if (!navigator.share) { + return { success: false, error: 'Web Share API не поддерживается' }; + } + try { + await navigator.share({ title, text, url }); + return { success: true }; + } catch (error) { + if (error.name === 'AbortError') { + return { success: false, cancelled: true }; + } + console.error('Ошибка при шеринге:', error); + return { success: false, error: error.message }; + } +} \ No newline at end of file