fix(ui): FA5 mechanism-review SF-1 — remove the invented offline-vassal name-grey

The FA5 mechanism review found the offline-vassal name-grey
(OfflineNameColor) is an invented visual: retail's UpdateVassalsData
@004924c3 writes the vassal name with no colour change, and the offline
cue is EXCLUSIVELY the authored 0x100004AA marker (already wired,
SetVisible per online state). Removed OfflineNameColor; the vassal name
always renders in the normal white. The Allegiance page now carries NO
invented tint (unlike Fellowship's registered leader/selection tints).
Pinned by Allegiance_OfflineCue_IsTheMarkerOnly_NameStaysWhite (marker
visible iff offline, name always white). AD-82's FA5 addendum corrected
(it had described the now-removed grey as 'covered by the marker'); AD-86
count corrected seven -> nine.

Full Release suite: 13,297 passed / 4 skipped / 0 failed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-12 09:07:58 +02:00
parent f12aefe948
commit eac28dc1f0
3 changed files with 65 additions and 5 deletions

View file

@ -1,3 +1,4 @@
using System.Numerics;
using AcDream.App.UI;
using AcDream.App.UI.Layout;
using AcDream.Core.Net.Messages;
@ -416,6 +417,61 @@ public sealed class SocialPanelControllerTests
Assert.Equal(2, listBox.ViewportForTest!.Children.Count);
}
/// <summary>FA5 mechanism-review SF-1: the offline cue is the authored
/// <c>0x100004AA</c> marker ALONE — visible for an offline vassal, hidden
/// for an online one — and the vassal NAME always renders in the normal
/// white <see cref="Vector4"/> regardless of online state (retail's
/// <c>UpdateVassalsData</c> writes the name with no colour change; the
/// grey-name cue was invented and is removed).</summary>
[Fact]
public void Allegiance_OfflineCue_IsTheMarkerOnly_NameStaysWhite()
{
const uint selfGuid = 100u;
var vassals = new List<RuntimeAllegianceMemberSnapshot>
{
new(401u, selfGuid, true, "Online Vassal", 0, 0, 0, 0, 0u, 0u, 0, 0, true),
new(402u, selfGuid, false, "Offline Vassal", 0, 0, 0, 0, 0u, 0u, 0, 0, true),
};
static UiElement? TaggedRowResolver(uint layoutId, uint elementId)
{
var row = new UiPanel();
var name = new UiText { DatElementId = 0x10000268u };
var marker = new UiPanel { DatElementId = 0x100004AAu };
row.AddChild(name);
row.AddChild(marker);
return row;
}
ImportedLayout layout = FixtureLoader.LoadSocialPanelHost();
SocialAllegiancePageController.Bindings bindings = MakeAllegianceBindings(
snapshot: new RuntimeAllegianceSnapshot { HasProfile = true, Revision = 1 },
vassals: guid => guid == selfGuid ? vassals : [],
localPlayerGuid: selfGuid,
templateResolver: TaggedRowResolver);
SocialPanelController? controller = SocialPanelController.Bind(
layout, MakeCallbacks(allegianceBindings: bindings));
Assert.NotNull(controller);
UiElement page = UiElement.FindDescendant(controller!.TabPanel, 0x10000291u)!;
var listBox = Assert.IsType<UiTemplateListBox>(
UiElement.FindDescendant(page, 0x10000260u));
var rows = listBox.ViewportForTest!.Children;
Assert.Equal(2, rows.Count);
foreach (UiElement row in rows)
{
var name = Assert.IsType<UiText>(UiElement.FindDescendant(row, 0x10000268u));
UiElement marker = UiElement.FindDescendant(row, 0x100004AAu)!;
bool online = name.LinesProvider()[0].Text == "Online Vassal";
// The marker IS the offline cue: shown iff offline.
Assert.Equal(!online, marker.Visible);
// The name is always white — no invented offline grey.
Assert.Equal(Vector4.One, name.LinesProvider()[0].Color);
}
}
/// <summary>Swear latches the WORLD selection at click time and, on
/// accept, sends the swear command for that exact guid.</summary>
[Fact]