using System.Threading;
using System.Threading.Tasks;
namespace BaseGames.UI
{
///
/// 返回结果的模态面板基类(确认框、模式 / 难度选择等)。
///
/// 用法(调用方走线性 await,无回调嵌套):
///
/// bool ok = await _confirmDialog.ShowAsync("CONFIRM_OVERWRITE_TITLE", "CONFIRM_OVERWRITE_BODY", ct);
/// if (!ok) return;
///
///
/// 结果通道由 承载,并对所有"提前结束"路径兜底
/// (ESC 取消出栈、外部强关、所属场景卸载、CancellationToken 取消),保证 await 绝不悬挂。
///
public abstract class UIResultPanel : UIPanelBase
{
private TaskCompletionSource _tcs;
private CancellationTokenRegistration _ctReg;
/// 取消 / 默认结果:ESC、返回、销毁、场景卸载、ct 取消时以此完成。
protected abstract T CancelResult { get; }
/// 由导航器 调用:开启一轮结果等待。
internal Task BeginResult(CancellationToken ct)
{
// 复用面板:若上一轮仍未决,先以默认值收口,避免句柄泄漏。
ResolvePending();
_tcs = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously);
_ctReg = ct.CanBeCanceled ? ct.Register(ResolvePending) : default;
return _tcs.Task;
}
/// 具体按钮回调:以 完成并出栈自身。
protected void Complete(T result)
{
var tcs = _tcs;
if (tcs != null && tcs.TrySetResult(result))
{
_ctReg.Dispose();
GetService()?.Pop(); // 弹出自己(栈顶)
}
}
/// 以取消默认值收口未决结果(幂等)。
private void ResolvePending()
{
var tcs = _tcs;
if (tcs != null && tcs.TrySetResult(CancelResult))
_ctReg.Dispose();
}
// 出栈(含 ESC 取消)会 SetActive(false) → OnDisable → OnPanelClose;
// 场景卸载 / 销毁同样经 OnDisable。统一在此兜底,覆盖所有提前结束路径。
protected override void OnPanelClose() => ResolvePending();
}
}