namespace SteUp.Shared.Core.Messages.System; /// /// Ponte fra il tasto indietro del dispositivo (host nativo) e la UI Blazor. /// Il form scheda si registra mentre è aperto così il back non manda l'app in /// background buttando via il lavoro non salvato: passa invece dallo stesso /// percorso del pulsante "Annulla", che propone il salvataggio come bozza. /// /// I gestori sono impilati: sopra il form può aprirsi un bottom sheet, e il /// tasto indietro deve chiudere prima quello. Chiudendolo si torna al gestore /// sottostante, che resta valido — senza la pila il sheet, uscendo di scena, /// porterebbe via con sé anche la registrazione del form. /// public class BackButtonService { private readonly List> _handlers = []; /// /// Segnala all'host se in questo momento c'è qualcuno da avvisare. L'host /// se ne serve per accendere e spegnere la propria intercettazione, così /// quando la UI non ha nulla da dire il tasto indietro torna a comportarsi /// esattamente come sempre. /// public event Action? HandlersChanged; public bool HasHandlers => _handlers.Count > 0; /// Registra il gestore corrente in cima alla pila. Ritorna la deregistrazione. public IDisposable Register(Func handler) { _handlers.Add(handler); HandlersChanged?.Invoke(true); return new Registration(this, handler); } /// /// Invocato dall'host nativo. Ritorna true se la UI Blazor ha preso in carico /// il tasto indietro: in quel caso l'host non deve fare altro. /// public bool TryHandleBackPressed() { if (_handlers.Count == 0) return false; // Fire-and-forget: il gestore rientra nel dispatcher Blazor da solo. _ = _handlers[^1](); return true; } private sealed class Registration(BackButtonService owner, Func handler) : IDisposable { public void Dispose() { if (!owner._handlers.Remove(handler)) return; owner.HandlersChanged?.Invoke(owner.HasHandlers); } } }