Добавлен стандартный "поделиться ПЛ"
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 AuthenticationStateProvider AuthProvider
|
||||||
@inject IDialogService DialogService
|
@inject IDialogService DialogService
|
||||||
@inject IAudioPlayerService AudioPlayerService
|
@inject IAudioPlayerService AudioPlayerService
|
||||||
|
@inject IJSRuntime JS
|
||||||
|
@inject IDialogService DialogService
|
||||||
@implements IDisposable
|
@implements IDisposable
|
||||||
|
|
||||||
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="py-1 px-1" Style="height: 100%;">
|
<MudContainer MaxWidth="MaxWidth.ExtraLarge" Class="py-1 px-1" Style="height: 100%;">
|
||||||
@@ -32,6 +34,7 @@
|
|||||||
<CardHeaderContent>
|
<CardHeaderContent>
|
||||||
@PlaylistCardHeaderContent
|
@PlaylistCardHeaderContent
|
||||||
</CardHeaderContent>
|
</CardHeaderContent>
|
||||||
|
|
||||||
<CardHeaderActions>
|
<CardHeaderActions>
|
||||||
<MudIconButton Icon="@(_isFavorite? Icons.Material.Filled.Star : Icons.Material.Outlined.StarBorder)"
|
<MudIconButton Icon="@(_isFavorite? Icons.Material.Filled.Star : Icons.Material.Outlined.StarBorder)"
|
||||||
Color="Color.Warning"
|
Color="Color.Warning"
|
||||||
@@ -39,11 +42,15 @@
|
|||||||
Disabled="_favoriteLoading"
|
Disabled="_favoriteLoading"
|
||||||
Size="Size.Medium" />
|
Size="Size.Medium" />
|
||||||
|
|
||||||
|
<MudIconButton Icon="@Icons.Material.Filled.Share"
|
||||||
|
OnClick="SharePlaylist"
|
||||||
|
Size="Size.Medium" />
|
||||||
|
|
||||||
@if (_isCreator && _isAuthenticated)
|
@if (_isCreator && _isAuthenticated)
|
||||||
{
|
{
|
||||||
<MudIconButton Icon="@Icons.Material.Filled.Settings" OnClick="OpenPermissionsDialog" Size="Size.Medium" />
|
<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>
|
</CardHeaderActions>
|
||||||
</MudCardHeader>
|
</MudCardHeader>
|
||||||
|
|
||||||
@@ -117,6 +124,9 @@
|
|||||||
Disabled="@_favoriteLoading"
|
Disabled="@_favoriteLoading"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<MudMenuItem Icon="@Icons.Material.Filled.Share"
|
||||||
|
OnClick="SharePlaylist"
|
||||||
|
Label="Поделиться" />
|
||||||
@if (_isCreator && _isAuthenticated)
|
@if (_isCreator && _isAuthenticated)
|
||||||
{
|
{
|
||||||
<MudMenuItem Icon="@Icons.Material.Filled.Settings"
|
<MudMenuItem Icon="@Icons.Material.Filled.Settings"
|
||||||
@@ -406,6 +416,12 @@
|
|||||||
/// <summary>Загрузка признака "фаворит".</summary>
|
/// <summary>Загрузка признака "фаворит".</summary>
|
||||||
private bool _favoriteLoading;
|
private bool _favoriteLoading;
|
||||||
|
|
||||||
|
/********************************
|
||||||
|
* Поделиться ссылкой
|
||||||
|
*********************************/
|
||||||
|
private IJSObjectReference? _shareModule;
|
||||||
|
private bool _isWebShareSupported = false;
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
var authState = await AuthProvider.GetAuthenticationStateAsync();
|
var authState = await AuthProvider.GetAuthenticationStateAsync();
|
||||||
@@ -417,6 +433,18 @@
|
|||||||
AudioPlayerService.OnEndedTrack += OnPlayerStateChanged;
|
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()
|
private void OnPlayerStateChanged()
|
||||||
{
|
{
|
||||||
InvokeAsync(StateHasChanged);
|
InvokeAsync(StateHasChanged);
|
||||||
@@ -803,9 +831,58 @@
|
|||||||
}
|
}
|
||||||
#endregion
|
#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()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
AudioPlayerService.OnStartedTrack -= OnPlayerStateChanged;
|
AudioPlayerService.OnStartedTrack -= OnPlayerStateChanged;
|
||||||
AudioPlayerService.OnEndedTrack -= OnPlayerStateChanged;
|
AudioPlayerService.OnEndedTrack -= OnPlayerStateChanged;
|
||||||
|
|
||||||
|
_shareModule?.DisposeAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -28,6 +28,9 @@
|
|||||||
<Content Update="wwwroot\js\AudioPlayer.js">
|
<Content Update="wwwroot\js\AudioPlayer.js">
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
|
<Content Update="wwwroot\js\shareUtils.js">
|
||||||
|
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||||
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</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