92 lines
2.3 KiB
C#
92 lines
2.3 KiB
C#
using Microsoft.AspNetCore.Components;
|
|
using Microsoft.JSInterop;
|
|
|
|
namespace DeepDrftPublic.Client.Controls;
|
|
|
|
/// <summary>
|
|
/// Share affordance for the track detail page: a popover offering a canonical-link copy
|
|
/// and an optional iframe embed snippet. Clipboard writes go through navigator.clipboard;
|
|
/// each copy shows a transient "Copied!" confirmation that resets after a short delay.
|
|
/// </summary>
|
|
public partial class SharePopover : ComponentBase, IDisposable
|
|
{
|
|
[Parameter] public string? EntryKey { get; set; }
|
|
|
|
[Inject] public required NavigationManager Navigation { get; set; }
|
|
[Inject] public required IJSRuntime JS { get; set; }
|
|
|
|
private bool _open;
|
|
private bool _embed;
|
|
private bool _linkCopied;
|
|
private bool _embedCopied;
|
|
|
|
private readonly CancellationTokenSource _cts = new();
|
|
|
|
private bool Embed
|
|
{
|
|
get => _embed;
|
|
set
|
|
{
|
|
_embed = value;
|
|
if (!value) _embedCopied = false;
|
|
}
|
|
}
|
|
|
|
private string TrackUrl => $"{Navigation.BaseUri}track/{EntryKey}";
|
|
|
|
private string EmbedSnippet =>
|
|
$"""<iframe src="{Navigation.BaseUri}FramePlayer?TrackEntryKey={EntryKey}" width="640" height="96" frameborder="0" style="border-radius:8px;" allow="autoplay"></iframe>""";
|
|
|
|
private void Toggle() => _open = !_open;
|
|
|
|
private void Close() => _open = false;
|
|
|
|
private async Task CopyLink()
|
|
{
|
|
if (await CopyToClipboard(TrackUrl))
|
|
{
|
|
_linkCopied = true;
|
|
await ResetAfterDelay(() => _linkCopied = false);
|
|
}
|
|
}
|
|
|
|
private async Task CopyEmbed()
|
|
{
|
|
if (await CopyToClipboard(EmbedSnippet))
|
|
{
|
|
_embedCopied = true;
|
|
await ResetAfterDelay(() => _embedCopied = false);
|
|
}
|
|
}
|
|
|
|
private async Task<bool> CopyToClipboard(string text)
|
|
{
|
|
try
|
|
{
|
|
await JS.InvokeVoidAsync("navigator.clipboard.writeText", text);
|
|
return true;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private async Task ResetAfterDelay(Action reset)
|
|
{
|
|
try
|
|
{
|
|
await Task.Delay(1500, _cts.Token);
|
|
}
|
|
catch (TaskCanceledException)
|
|
{
|
|
return;
|
|
}
|
|
|
|
reset();
|
|
StateHasChanged();
|
|
}
|
|
|
|
public void Dispose() => _cts.Cancel();
|
|
}
|