Fixes the OP5 (Chat tab) dual-lens review findings against e71e5a96:
- M1 (MUST-FIX): each opacity row's own apply closure now pushes its OWN
slider's thumb from the post-link truth (bindings.Current*Opacity()),
mirroring the OP4 binding pattern. Before this, a single-slider drag
followed by Reset reverted the live value/link but left that slider's
own thumb stuck at the dragged position.
- S1 (SHOULD-FIX): the Chat tab's two opacity sliders no longer round-trip
the whole settings.json on every drag MouseMove tick. UiScrollbar gains
IsDragging + a DragCompleted callback (fires once, at the MouseUp that
ends an actual thumb drag); the opacity apply closures flush immediately
when not mid-drag (Reset/Defaults/discrete edits, same as before) and
defer to DragCompleted otherwise, collapsing dozens of per-tick writes
into exactly one per drag gesture. Live opacity still applies every tick.
- S2 (SHOULD-FIX): filed register row AP-201 and issue #371 for the
UiScrollablePanel whole-row-cull-vs-clip divergence the review found
(predates OP5, made user-visible by OP5's 240-260px filter blocks). Not
fixed in this round (a renderer-level scissor stack is out of scope
here) — corrected the OP5 connected-gate script instead so a straddling
block's disappear-then-reappear-whole is no longer reported as a
self-sizing regression.
- S3 (SHOULD-FIX): the chatWindowMainFilter round-trip test already
existed in e71e5a96 (the review missed it scrolling past line 330);
added the genuinely missing coverage instead — a composed test pinning
RetailUiRuntime.MountChat's window-0 SettingsStore -> ChatWindowState
seed (MountChat itself needs live DAT access and isn't unit-testable
directly).
- N11: ScrollbarLinkage_ModelPointsAtTheChatListBoxScroll now asserts
through the scoped page-slot lookup (UiElement.FindDescendant) instead
of the flat layout.FindElement, which passed for the wrong reason given
the shared scrollbar id 0x10000201 — matches OP6's own scrollbar-linkage
test pattern.
Also updated ConfigOptionsPageControllerTests' local ChatOptionsPageController
Bindings fake for the new FlushOpacity parameter.
Full Release suite: 13,117 passed / 4 skipped / 0 failed (baseline 13,107/4/0
post-OP6 — 10 tests added, zero skips added, zero failures).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Binds the retail Options panel's Config tab (LayoutDesc 0x21000029, 27
authored rows across 6 sections) through OP2's template mechanism and
OP3's per-page OptionPage model, matching the Character/Chat tab
controllers' established pattern.
The row table is transcribed directly from two decompiled sources —
gmConfigUI::InitOptions @0x0049E400 (row order, widget shape, defaults)
and gmClient::InitUIPreferences @0x004035b0 (the complete
UIPreferences::AttachPreference registration: every label/tooltip key,
every slider's real-unit range, every menu's enum choices) — which
resolves the research docs' own "U4" unverified slider-caption pairing:
retail ships ZERO range captions on this tab (every SetSliderLabel call
passes literal string id 0).
Consumer disposition: LIVE — Sound/Ambient volume-trio sliders and their
toggle halves (AudioSettings.SfxDisabled/AmbientDisabled now gate the
already-live engine write; RuntimeSettingsController.SaveAudio newly
pushes into OpenAlAudioEngine on every change, not just at startup),
Resolution/Full Screen (immediate window resize on save). NEXT-LAUNCH
(pre-existing precedent): Sync To Refresh, Field of View. STORE-ONLY
(register rows AP-198/199/200, TS-74 extended): Sound Features/Interface
trio/Play-Only-When-Active, the nine Graphics/Rendering-Quality rows
(Vulkan has no per-feature render knobs), Camera/Input's six rows and
Use Mouse Turning (no persistent mouse-turning camera mode), Chat Font
Face/Size (distinct new fields from the existing live ChatSettings.FontSize).
AudioSettings/DisplaySettings/CameraTurningSettings/ChatSettings each
gain new fields for their slice of the 27 rows, backed by SettingsStore
round-trips. A real bug caught by testing: the scrollbar scope lookup
used the standalone-layout root id (0x100001FF), which does not survive
base-merge into the host-mounted tree — fixed to scope from the tab
host's own page-slot id (0x10000213), matching Chat's established
pattern for the same shared-scrollbar-id hazard (0x10000201, authored by
both the Chat and Config ListBoxes).
30 new tests (27 authored rows register as 30 IOptionRow instances — the
three toggle+slider trios each register two). Full Release suite:
13,107 passed / 4 skipped / 0 failed (was 13,083/4/0 — net +24, the one
existing RuntimeSettingsControllerTests case updated for SaveAudio's new
live-apply call, not a regression).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>