feat(ui): port retail dialog factory lifecycle
Replace the single mutable confirmation service with retail's property-backed DialogFactory model: fresh DAT roots, context ids, queue groups, priority preemption, callback/close-notice ordering, and context cancellation. Route /die, server confirmation aborts, and guarded item use through focused semantic owners. Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
parent
43f7c7807c
commit
66bdae7a83
22 changed files with 1442 additions and 220 deletions
113
src/AcDream.App/UI/Layout/RetailDialogData.cs
Normal file
113
src/AcDream.App/UI/Layout/RetailDialogData.cs
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
namespace AcDream.App.UI.Layout;
|
||||
|
||||
/// <summary>
|
||||
/// Property identifiers consumed by retail's <c>Dialog</c> and
|
||||
/// <c>DialogFactory</c> implementations.
|
||||
/// </summary>
|
||||
public static class RetailDialogProperty
|
||||
{
|
||||
public const uint Priority = 0x8Du;
|
||||
public const uint Type = 0x8Eu;
|
||||
public const uint AcceptLabel = 0x90u;
|
||||
public const uint RejectLabel = 0x91u;
|
||||
public const uint ConfirmationResult = 0x92u;
|
||||
/// <summary>
|
||||
/// When true, <c>Dialog::SetData @ 0x00476BE0</c> sets UIElement boolean
|
||||
/// attribute <c>0x40</c>. The Keystone-owned attribute name is unavailable.
|
||||
/// </summary>
|
||||
public const uint ElementAttribute40 = 0xACu;
|
||||
public const uint QueueKey = 0xC3u;
|
||||
public const uint Message = 0xC5u;
|
||||
public const uint UsageObjectId = 0x1000003Du;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retail dialog types selected by property <c>0x8E</c> in
|
||||
/// <c>DialogFactory::CreateDialog_ @ 0x00477AD0</c>.
|
||||
/// </summary>
|
||||
public enum RetailDialogType : uint
|
||||
{
|
||||
Confirmation = 1,
|
||||
Wait = 2,
|
||||
Message = 3,
|
||||
TextInput = 4,
|
||||
ConfirmationTextInput = 5,
|
||||
Menu = 6,
|
||||
ConfirmationMenu = 7,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Modern typed carrier for retail's <c>PropertyCollection</c> dialog contract.
|
||||
/// The raw numeric keys remain visible because type-specific presenters and semantic
|
||||
/// callbacks both extend the same collection in retail.
|
||||
/// </summary>
|
||||
public sealed class RetailDialogData
|
||||
{
|
||||
private readonly Dictionary<uint, object> _values = new();
|
||||
|
||||
public IReadOnlyDictionary<uint, object> Values => _values;
|
||||
|
||||
public RetailDialogData Set<T>(uint propertyId, T value) where T : notnull
|
||||
{
|
||||
_values[propertyId] = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
public bool Contains(uint propertyId) => _values.ContainsKey(propertyId);
|
||||
|
||||
public bool TryGet<T>(uint propertyId, out T value)
|
||||
{
|
||||
if (_values.TryGetValue(propertyId, out object? raw) && raw is T typed)
|
||||
{
|
||||
value = typed;
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default!;
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool GetBoolean(uint propertyId, bool defaultValue = false)
|
||||
=> _values.TryGetValue(propertyId, out object? raw)
|
||||
? raw switch
|
||||
{
|
||||
bool value => value,
|
||||
byte value => value != 0,
|
||||
int value => value != 0,
|
||||
uint value => value != 0,
|
||||
_ => defaultValue,
|
||||
}
|
||||
: defaultValue;
|
||||
|
||||
public uint GetUInt32(uint propertyId, uint defaultValue = 0u)
|
||||
=> _values.TryGetValue(propertyId, out object? raw)
|
||||
? raw switch
|
||||
{
|
||||
byte value => value,
|
||||
ushort value => value,
|
||||
int value when value >= 0 => (uint)value,
|
||||
uint value => value,
|
||||
Enum value => Convert.ToUInt32(value),
|
||||
_ => defaultValue,
|
||||
}
|
||||
: defaultValue;
|
||||
|
||||
public string? GetString(uint propertyId)
|
||||
=> _values.TryGetValue(propertyId, out object? raw) ? raw as string : null;
|
||||
|
||||
public RetailDialogData Clone()
|
||||
{
|
||||
var clone = new RetailDialogData();
|
||||
foreach ((uint propertyId, object value) in _values)
|
||||
clone._values.Add(propertyId, value);
|
||||
return clone;
|
||||
}
|
||||
|
||||
public static RetailDialogData Confirmation(string message)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(message);
|
||||
return new RetailDialogData()
|
||||
.Set(RetailDialogProperty.Type, RetailDialogType.Confirmation)
|
||||
.Set(RetailDialogProperty.Message, message);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue