2026-10-05 01:23:18 +02:00
|
|
|
using Blazored.LocalStorage;
|
|
|
|
|
|
|
|
|
|
using decePubClient.Models;
|
|
|
|
|
|
|
|
|
|
namespace decePubClient.Services
|
|
|
|
|
{
|
|
|
|
|
/// <summary>
|
2026-10-05 15:19:07 +02:00
|
|
|
/// Asks a persona, once, before its first reaction or poll vote, and once before it first joins an event, to accept
|
2026-10-18 09:50:46 +02:00
|
|
|
/// that these are public and visible as that persona (an owner decision); and this device, once, before its first Web
|
|
|
|
|
/// Push subscription, to accept that the browser's push service learns when notifications arrive (PublicAct.Push, told
|
|
|
|
|
/// once for the device whichever persona asks). PublicNoticeHost shows the question; Confirm returns true at once for
|
|
|
|
|
/// what was accepted already, and false when the reader declines.
|
2026-10-05 01:23:18 +02:00
|
|
|
/// </summary>
|
|
|
|
|
public class PublicNoticeService(ILocalStorageService localStorage)
|
|
|
|
|
{
|
|
|
|
|
TaskCompletionSource<bool> pending;
|
|
|
|
|
|
|
|
|
|
public event Action Changed;
|
|
|
|
|
|
|
|
|
|
public bool IsAsking => pending is not null;
|
|
|
|
|
|
2026-10-05 15:19:07 +02:00
|
|
|
/// <summary>What the persona is being told about.</summary>
|
|
|
|
|
public PublicAct Act { get; private set; } = PublicAct.Reaction;
|
|
|
|
|
|
|
|
|
|
public async Task<bool> Confirm(string personaId, PublicAct act = PublicAct.Reaction, CancellationToken cancellationToken = default)
|
2026-10-05 01:23:18 +02:00
|
|
|
{
|
2026-10-18 09:50:46 +02:00
|
|
|
if (string.IsNullOrEmpty(personaId) && act != PublicAct.Push)
|
2026-10-05 01:23:18 +02:00
|
|
|
return false;
|
|
|
|
|
var seen = await localStorage.GetItemAsync<PublicActionNotices>(nameof(PublicActionNotices), cancellationToken) ?? new();
|
2026-10-05 15:19:07 +02:00
|
|
|
var told = act == PublicAct.Participation ? seen.EventPersonaIds : seen.PersonaIds;
|
2026-10-18 09:50:46 +02:00
|
|
|
if (act == PublicAct.Push ? seen.PushTold : told.Contains(personaId))
|
2026-10-05 01:23:18 +02:00
|
|
|
return true;
|
|
|
|
|
|
2026-10-05 15:19:07 +02:00
|
|
|
Act = act;
|
2026-10-05 01:23:18 +02:00
|
|
|
pending = new TaskCompletionSource<bool>();
|
|
|
|
|
Changed?.Invoke();
|
|
|
|
|
var accepted = await pending.Task;
|
|
|
|
|
pending = null;
|
|
|
|
|
Changed?.Invoke();
|
|
|
|
|
if (!accepted)
|
|
|
|
|
return false;
|
|
|
|
|
|
2026-10-18 09:50:46 +02:00
|
|
|
if (act == PublicAct.Push)
|
|
|
|
|
seen.PushTold = true;
|
|
|
|
|
else
|
|
|
|
|
told.Add(personaId);
|
2026-10-05 01:23:18 +02:00
|
|
|
await localStorage.SetItemAsync(nameof(PublicActionNotices), seen, cancellationToken);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Answer(bool accepted) => pending?.TrySetResult(accepted);
|
|
|
|
|
}
|
|
|
|
|
}
|