dbd90ee52a
Player-service play-session tracker (floor + 3-bucket classify), SharePopover share tracker with debounce, sendBeacon interop, proxied rate-limited POST api/event/{play,share}, append-only event logs + incremental play_counter with server-side release resolution. Migration authored, not applied. No anonId, no read surface.
61 lines
1.9 KiB
C#
61 lines
1.9 KiB
C#
using Microsoft.JSInterop;
|
|
|
|
namespace DeepDrftPublic.Client.Services;
|
|
|
|
/// <summary>
|
|
/// Thin C# wrapper over the <c>window.DeepDrftBeacon</c> TS interop (Phase 16 §2.2). Wraps the
|
|
/// <c>navigator.sendBeacon</c> POST and the page-unload registration so the rest of the client never
|
|
/// touches <see cref="IJSRuntime"/> string identifiers directly. All calls are best-effort: a JS
|
|
/// failure (module not yet loaded, interop unavailable during prerender) is swallowed — telemetry must
|
|
/// never throw into the UI or the playback path.
|
|
/// </summary>
|
|
public sealed class BeaconInterop
|
|
{
|
|
private readonly IJSRuntime _js;
|
|
|
|
public BeaconInterop(IJSRuntime js)
|
|
{
|
|
_js = js;
|
|
}
|
|
|
|
/// <summary>Queue a fire-and-forget POST of a JSON body to the given absolute URL.</summary>
|
|
public async Task SendAsync(string url, string json)
|
|
{
|
|
try
|
|
{
|
|
await _js.InvokeAsync<bool>("DeepDrftBeacon.send", url, json);
|
|
}
|
|
catch
|
|
{
|
|
// Module not loaded / not interactive yet — drop the event silently.
|
|
}
|
|
}
|
|
|
|
/// <summary>Register a .NET unload callback (fires on pagehide / visibility→hidden) under a key.</summary>
|
|
public async Task RegisterUnloadAsync<T>(string key, DotNetObjectReference<T> dotNetRef, string methodName)
|
|
where T : class
|
|
{
|
|
try
|
|
{
|
|
await _js.InvokeVoidAsync("DeepDrftBeacon.registerUnload", key, dotNetRef, methodName);
|
|
}
|
|
catch
|
|
{
|
|
// Best-effort — without the unload handler, mid-play tab-close simply isn't recorded.
|
|
}
|
|
}
|
|
|
|
/// <summary>Detach a previously-registered unload callback.</summary>
|
|
public async Task UnregisterUnloadAsync(string key)
|
|
{
|
|
try
|
|
{
|
|
await _js.InvokeVoidAsync("DeepDrftBeacon.unregisterUnload", key);
|
|
}
|
|
catch
|
|
{
|
|
// Disposal best-effort.
|
|
}
|
|
}
|
|
}
|