Добавлен стандартный "поделиться ПЛ"
This commit is contained in:
45
PlaylistShared.Pwa/Components/Common/ShareDialog.razor
Normal file
45
PlaylistShared.Pwa/Components/Common/ShareDialog.razor
Normal file
@@ -0,0 +1,45 @@
|
||||
@inject IJSRuntime JS
|
||||
@inject ISnackbar Snackbar
|
||||
|
||||
<MudDialog>
|
||||
<TitleContent>
|
||||
<MudText Typo="Typo.h6">Поделиться плейлистом</MudText>
|
||||
</TitleContent>
|
||||
<DialogContent>
|
||||
<MudStack Spacing="2">
|
||||
<MudText>Скопируйте ссылку и отправьте её друзьям:</MudText>
|
||||
<MudTextField @bind-Value="ShareUrl"
|
||||
Variant="Variant.Outlined"
|
||||
ReadOnly="true"
|
||||
Margin="Margin.Dense"
|
||||
Class="mt-2" />
|
||||
</MudStack>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Primary"
|
||||
OnClick="CopyToClipboard">
|
||||
Скопировать ссылку
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Text" Color="Color.Default"
|
||||
OnClick="Close">
|
||||
Закрыть
|
||||
</MudButton>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
|
||||
@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();
|
||||
}
|
||||
@@ -16,6 +16,8 @@
|
||||
@inject AuthenticationStateProvider AuthProvider
|
||||
@inject IDialogService DialogService
|
||||
@inject IAudioPlayerService AudioPlayerService
|
||||
@inject IJSRuntime JS
|
||||
@inject IDialogService DialogService
|
||||
@implements IDisposable
|
||||
|
||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="py-1 px-1" Style="height: 100%;">
|
||||
@@ -32,18 +34,23 @@
|
||||
<CardHeaderContent>
|
||||
@PlaylistCardHeaderContent
|
||||
</CardHeaderContent>
|
||||
|
||||
<CardHeaderActions>
|
||||
<MudIconButton Icon="@(_isFavorite? Icons.Material.Filled.Star : Icons.Material.Outlined.StarBorder)"
|
||||
Color="Color.Warning"
|
||||
OnClick="ToggleFavorite"
|
||||
Disabled="_favoriteLoading"
|
||||
Size="Size.Medium" />
|
||||
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Share"
|
||||
OnClick="SharePlaylist"
|
||||
Size="Size.Medium" />
|
||||
|
||||
@if (_isCreator && _isAuthenticated)
|
||||
{
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Settings" OnClick="OpenPermissionsDialog" Size="Size.Medium" />
|
||||
}
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Refresh" OnClick="LoadTracks" Disabled="@_tracksLoading" />
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Refresh" OnClick="LoadTracks" Disabled="@_tracksLoading" Size="Size.Medium" />
|
||||
</CardHeaderActions>
|
||||
</MudCardHeader>
|
||||
|
||||
@@ -116,7 +123,10 @@
|
||||
OnClick="ToggleFavorite"
|
||||
Disabled="@_favoriteLoading"
|
||||
/>
|
||||
|
||||
|
||||
<MudMenuItem Icon="@Icons.Material.Filled.Share"
|
||||
OnClick="SharePlaylist"
|
||||
Label="Поделиться" />
|
||||
@if (_isCreator && _isAuthenticated)
|
||||
{
|
||||
<MudMenuItem Icon="@Icons.Material.Filled.Settings"
|
||||
@@ -405,6 +415,12 @@
|
||||
private bool _isFavorite;
|
||||
/// <summary>Загрузка признака "фаворит".</summary>
|
||||
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<IJSObjectReference>("import", "/js/shareUtils.js");
|
||||
// Проверяем поддержку Web Share API
|
||||
_isWebShareSupported = await _shareModule.InvokeAsync<bool>("isSupported");
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerStateChanged()
|
||||
{
|
||||
InvokeAsync(StateHasChanged);
|
||||
@@ -803,9 +831,58 @@
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Поделитьсы ссылкой
|
||||
/// <summary> Поделиться ссылкой </summary>
|
||||
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<ShareResult>("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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary> Модальное окно, чтобы поделиться ссылкой </summary>
|
||||
private async Task ShowShareDialog(string url)
|
||||
{
|
||||
var parameters = new DialogParameters<ShareDialog>
|
||||
{
|
||||
{ x => x.ShareUrl, url }
|
||||
};
|
||||
var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.Small, FullWidth = true };
|
||||
await DialogService.ShowAsync<ShareDialog>("Поделиться", 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();
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,9 @@
|
||||
<Content Update="wwwroot\js\AudioPlayer.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Update="wwwroot\js\shareUtils.js">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
19
PlaylistShared.Pwa/wwwroot/js/shareUtils.js
Normal file
19
PlaylistShared.Pwa/wwwroot/js/shareUtils.js
Normal file
@@ -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 };
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user