fix(ui): select items before drag mesh

Port ItemList_BeginDrag's select-before-waiting order so a direct press-drag shows the selection indicator on its first frame across inventory, paperdoll, and toolbar item lists.

Co-Authored-By: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-13 09:28:28 +02:00
parent 64a056e656
commit 609ed8bfc2
10 changed files with 71 additions and 14 deletions

View file

@ -12,8 +12,12 @@ public class DragDropSpineTests
public (UiItemList list, UiItemSlot cell, ItemDragPayload payload)? LastOver;
public (UiItemList list, UiItemSlot cell, ItemDragPayload payload)? LastDrop;
public (UiItemList list, UiItemSlot cell, ItemDragPayload payload)? LastLift;
public bool? WaitingAtLift;
public void OnDragLift(UiItemList list, UiItemSlot cell, ItemDragPayload p)
{ LastLift = (list, cell, p); }
{
WaitingAtLift = cell.WaitingVisual;
LastLift = (list, cell, p);
}
public ItemDragAcceptance OnDragOver(UiItemList list, UiItemSlot cell, ItemDragPayload p)
{ LastOver = (list, cell, p); return Acceptance; }
@ -191,6 +195,8 @@ public class DragDropSpineTests
root.OnMouseDown(UiMouseButton.Left, 10, 10);
root.OnMouseMove(20, 10); // BeginDrag → OnDragLift
Assert.False(h.WaitingAtLift); // retail selects/lifts before enabling the mesh
Assert.True(list.Cell.WaitingVisual);
root.OnMouseUp(UiMouseButton.Left, 600, 500); // release over empty space
Assert.NotNull(h.LastLift); // lift happened
Assert.Null(h.LastDrop); // no drop dispatched (off-bar)

View file

@ -772,13 +772,17 @@ public class InventoryControllerTests
}
[Fact]
public void OnDragLift_isNoOp_itemStaysUntilServerConfirms()
public void OnDragLift_selectsItem_butKeepsItUntilServerConfirms()
{
var (layout, grid, _, _, _, _, _, _) = BuildLayout();
var objects = new ClientObjectTable();
SeedContained(objects, 0xA, Player, slot: 0);
var ctrl = (IItemListDragHandler)Bind(layout, objects);
var selection = new SelectionState();
var ctrl = (IItemListDragHandler)Bind(layout, objects, selection: selection);
((IItemListDragHandler)ctrl).OnDragLift(grid, grid.GetItem(0)!, Payload(0xAu));
Assert.Equal(0xAu, selection.SelectedObjectId);
Assert.True(grid.GetItem(0)!.Selected);
Assert.Equal(Player, objects.Get(0xAu)!.ContainerId); // NOT removed on lift (unlike the toolbar)
}

View file

@ -81,6 +81,23 @@ public class PaperdollControllerTests
Assert.True(lists[HeadSlot].Cell.Selected);
}
[Fact]
public void DragLift_selectsEquippedItem_beforeWaitingVisual()
{
var (layout, lists) = BuildLayout();
var objects = new ClientObjectTable();
SeedEquipped(objects, 0xA01u, EquipMask.HeadWear);
var selection = new SelectionState();
var ctrl = Bind(layout, objects, selection: selection);
var cell = lists[HeadSlot].Cell;
var payload = new ItemDragPayload(0xA01u, ItemDragSource.Equipment, 0, cell);
ctrl.OnDragLift(lists[HeadSlot], cell, payload);
Assert.Equal(0xA01u, selection.SelectedObjectId);
Assert.True(cell.Selected);
}
[Fact]
public void Populate_matches_a_weapon_into_the_composite_slot()
{

View file

@ -1010,15 +1010,18 @@ public class ToolbarControllerTests
var shortcuts = new System.Collections.Generic.List<ShortcutEntry>
{ new(Index: 3, ObjectId: 0x5001u, SpellId: 0) };
var (adds, removes) = NewSpies(out var add, out var rem);
uint selected = 0;
var ctrl = ToolbarController.Bind(layout, repo, () => shortcuts,
iconIds: (_,_,_,_,_) => 0x77u, useItem: _ => { },
sendAddShortcut: add, sendRemoveShortcut: rem);
sendAddShortcut: add, sendRemoveShortcut: rem,
selectItem: item => selected = item, selectedObjectId: () => selected);
Assert.Equal(0x5001u, slots[Row1[3]].Cell.ItemId);
var payload = new ItemDragPayload(0x5001u, ItemDragSource.ShortcutBar, 3, slots[Row1[3]].Cell);
ctrl.OnDragLift(slots[Row1[3]], slots[Row1[3]].Cell, payload);
Assert.Equal(0x5001u, selected);
Assert.Contains(3u, removes);
Assert.Equal(0u, slots[Row1[3]].Cell.ItemId);
}