Singleton toast/toastbuilder UI helper. Stores current toast title, message, icon, copy behavior, tone and version, exposes fluent ToastBuilder to configure and show toasts, and handles dismissal and optional sound hooks.
namespace Sunless.Libraries.UI;
using System;
using Sandbox;
// Singleton toast state. Host <ToastHost /> once. Call:
//
// Toaster.Show( "#toast.saved" );
// Toaster.New().WithIcon( "save" ).WithCopy( path ).Show( "#toast.saved", path );
//
public static class Toaster
{
public static string Title { get; private set; }
public static string Message { get; private set; }
public static string Icon { get; private set; }
public static bool ShowCopy { get; private set; }
public static string CopyValue { get; private set; }
public static ToastTone Tone { get; private set; }
public static bool IsOpen => !string.IsNullOrEmpty( Message );
public static int Version { get; private set; }
public static Action OnShowSound { get; set; }
public static Action OnCopySound { get; set; }
public static ToastBuilder New() => new();
public static void Show( string message, string title = null )
=> New().Show( message, title );
public static void Dismiss()
{
if ( !IsOpen ) return;
Message = null;
Title = null;
Icon = null;
CopyValue = null;
ShowCopy = false;
Tone = ToastTone.Default;
Version++;
}
internal static void RaiseCopySound()
{
try { OnCopySound?.Invoke(); } catch ( Exception e ) { Log.Warning( $"[Toaster] copy sound threw: {e.Message}" ); }
}
internal static void Commit( ToastBuilder b )
{
Message = b._message;
Title = b._title;
Icon = b._icon;
ShowCopy = b._showCopy;
CopyValue = b._copyValue;
Tone = b._tone;
Version++;
try { (b._onShowSound ?? OnShowSound)?.Invoke(); } catch ( Exception e ) { Log.Warning( $"[Toaster] show sound threw: {e.Message}" ); }
}
}
public enum ToastTone { Default, Ok, Warn, Danger, Info }
public sealed class ToastBuilder
{
internal string _title;
internal string _message;
internal string _icon;
internal bool _showCopy;
internal string _copyValue;
internal ToastTone _tone = ToastTone.Default;
internal Action _onShowSound;
public ToastBuilder WithTitle( string title ) { _title = title; return this; }
public ToastBuilder WithIcon( string ligature ) { _icon = ligature; return this; }
public ToastBuilder WithCopy( string value = null ) { _showCopy = true; _copyValue = value; return this; }
public ToastBuilder WithTone( ToastTone tone ) { _tone = tone; return this; }
public ToastBuilder WithSound( Action sound ) { _onShowSound = sound; return this; }
public void Show( string message, string title = null )
{
_message = message;
if ( title is not null ) _title = title;
Toaster.Commit( this );
}
}