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