File Details
VamoosesDyeStudio-2.1.4.zip
- R
- May 26, 2026
- 921.16 KB
- 399
- 12.0.5
- Retail
File Name
VamoosesDyeStudio-2.1.4.zip
Supported Versions
- 12.0.5
## [Unreleased]
## Version 2.1.4 (Released May 2026)
**Fixes**
- Send to Auctionator no longer ships a stale herb/dye list on repeat clicks. Reported on CurseForge: the first click sent the correct list, but subsequent clicks (even after resetting targets) kept shipping the original herbs. Root cause: the Send-to-AH cart accumulated entries on every click and was never cleared. Each click now ignores any prior cart state and ships exactly the live deficit (current target minus current owned), so the Auctionator list always mirrors what the Stock tab shows. Same fix applied to Buy (Dyes) mode.
- Buy (Dyes) Send-to-AH was silently skipping any color group you had collapsed in the Stock list -- the list reflected what was visible on screen, not the full shopping list. Now ships every dye you're short on, regardless of which groups are expanded.
**Stock tab**
- The "Herbs needed to craft target" popout now shows TWO total rows at the bottom so the buy gap is visible at a glance regardless of toggle state:
- `Crafts will use | x4800 | 10k g` -- what the planned crafts actually consume (gross)
- `You need to buy | x3200 | 7k g` -- what's left after subtracting on-hand bag + bank + reagent bank + warband (net)
- New **Use owned herbs** checkbox above the Send-to-AH button (Craft mode only -- hidden in Buy mode where the dye deficit is already net). When on (default), the herb list subtracts what you already hold row-by-row, the `Buy Herbs: Xg` button shows the after-on-hand gold, and Send-to-AH ships the net amount. Toggle off to see and ship gross totals. The button label flips to `Craft from on-hand` when your stock covers every remaining craft. Hover the checkbox for details.
- Herb rows in the "Herbs needed to craft target" popout now spell out ownership in the subline: `@ 2g each - own 331 of 1360 needed`. The per-row buy gap is now visible without flipping the toggle.
- The dual footer totals now use the body font (larger / easier to read) instead of the caption font, with the cells re-sized to fit the 224px popout container.
- Send-to-AH chat print is now more verbose so you can verify what you shipped without leaving Stock: `Sent 8 herb kinds (4800 herbs total) to Auctionator list: VDS-Herbs`. Buy (Dyes) mode uses the equivalent dye phrasing.
- Clicking Buy Herbs / Buy Dyes when there's nothing to buy now prints `Nothing to buy -- all at target. Auctionator list unchanged.` Previously the button click was silent, which felt broken.
- Herbs popout subtitle simplified from `X herbs - Y kinds` to just `Y kinds` (the qty is in the footer rows now).
**Stock tab visual refresh**
- Expanded warehouse rows (Brass, Bronze, Gold, etc.) now carry the dye's swatch colour as a full-row backdrop -- same chrome the Browse panel uses for dye rows. Lets you scan the Stock list by colour the way you scan Colors.
- Group-header rows (RED, ORANGE, etc.) now sit on a neutral dark-grey backdrop so they read as a "band" without competing with the group's own RGB on the chev/name/progress bar. BLACK group label gets a luminance floor so it stays legible against the dark backdrop (would otherwise read invisible since the dye-group RGB and the row tint are identical).
- All Stock tab +/- buttons (per-dye target, group-header target, header all-groups bumper) swapped from FontString `+` / `-` to the `communities-chat-icon-plus` / `communities-chat-icon-minus` atlases. Resting: desaturated grey at 85% alpha. Hover: full colour at 100% alpha. Settled after iterating from desat/0.75 (washed out on coloured rows) -> no-desat/0.9 (taking over) -> the current midpoint.
- Action bar tightened: the "Auto-save" checkbox shrunk 92px -> 76px (fixed an over-spec warning + pulled the `+1 dye / -1 back` cost text closer to the checkbox). Added a 10px breather row between the channel picker and the action bar so the buttons read as a distinct band.
- Tooltip text rewrites: "Buy Herbs" button now reads `Send this list to Auctionator's shopping list` (was misleading "Browse the auction house"). "Use owned herbs" checkbox now reads `Subtract herbs you already own (bag, bank, warband) from the totals.` (was an essay). Apply button drops the stale `shown above` directional copy now that the cost sits beside the button rather than above it.
**Live mode**
- Right-click any slot row in the Live edit panel to clear that channel's selected dye, without leaving Live mode. Then hit **Apply** to commit the cleared state to the decor. Discord feedback: there was previously no way to unselect a channel's dye short of hitting Cancel (which exits the whole flow). Matches the pre-Lattice donor behaviour. Hovering a slot now shows a tooltip with the click hints + the currently-selected dye name. (Slot-clear sentinel: `ApplyDyeToSelectedDecor(slotID, nil)` per donor; the MCP-recorded `dyeColorID=0` is a silent no-op on 12.0.5 retail.)
- **Cancel** now reverts pending dye changes and keeps you in Live mode instead of slamming the window shut. Previously it called `CancelActiveEditing()` which killed customize mode AND closed VDS -- jarring when you just wanted to back out of one experiment. Walks the per-slot snapshot taken on enter and re-applies each original dye (or clears the slot if it was empty originally). Tooltip updated to `Revert pending dye changes.`
- **Empty-slot Cancel bug**: an originally-empty slot's snapshotted `dyeColorID` is `0` (Blizzard's sentinel for "no dye" in reads). Lua treats `0` as truthy, so Cancel was routing it through `ApplyDye(slotID, 0)` -- a verified silent no-op on 12.0.5. Now Cancel explicitly checks `~= 0` and routes empties through `ClearSlot(slotID, nil)`, so painting into a previously-undyed channel and hitting Cancel actually reverts it.
- New **Clear all** button to the right of the decor name. Wipes every slot's preview back to "no dye"; Apply commits. Decor name now left-aligned (was centred) to make room. Note: Blizzard's bulk-clear APIs are both broken on 12.0.5 -- `ClearDyesOnSelectedDecor` doesn't exist (despite a "verified" MCP entry, same trap class as `GetNumDyeSlots`), and `ClearDyesForSelectedDecor` is a silent no-op. VDS works around it by iterating `info.dyeSlots` from `GetSelectedDecorInfo` and calling `ApplyDyeToSelectedDecor(slot.ID, nil)` per slot. The three broken APIs have updated MCP gotchas to prevent future code from repeating the trap.
**Fixes (late cycle)**
- Send-to-AH no longer ships `\" Dye\"` as a search string when `C_Item.GetItemNameByID` returns `\"\"` for a not-yet-loaded item. The cache layer already filtered empty strings, but the boundary API call didn't; Lua treats `\"\"` as truthy so the downstream "pad with Dye suffix" path produced `\" Dye\"`. `resolveItemName` now treats both cache and API empties as a miss.
- `TooltipEngine.resolveDef` now logs via `VDS.Log:Warn("tooltip", ...)` when a function recipe (like `R.LiveSlot`) errors inside the `pcall`. Previously the error was silently swallowed; per CLAUDE.md no silent pcall is allowed.
- Iron Invariant cleanup: dropped defensive `widget._check or widget` fallback in `dispatchCheckbox`, `self._slotID = ... or nil` fallback in Live-slot OnClick, and `if not (live and live.originalDyes)` guard in Cancel. Each was structurally guaranteed by other invariants (build() always assigns `_check`; visibility selector gates the slot widget on `live.hasSlotN`; `originalDyes` is `{}`-initialized at boot + reset on LIVE_MODE_EXIT). Failure now surfaces loud instead of hiding schema drift.
**Tooltip engine audit**
- String tooltip recipes now render. Previously `TooltipEngine.resolveDef` returned `nil` for any non-table / non-function recipe, so the 30+ `R.X = "..."` string recipes (Snapshot, Apply, OwnedOnly, StockMinusAll, StockPlusAll, every checkbox in the config sidebar, every iconButton in the palette toolbar, etc.) hovered silent. Strings now wrap as `{ body = string }` and render as a single wrapped line.
- 4 widget kinds had spec-attached recipes that never rendered because their `build()` functions didn't read `spec.tooltip`: `searchBox` (SearchDecor, SearchDyesHerbs), `tabBar` (StockModeToggle), `scopeDropdown` (ScopeFilter), `categoryDropdown` (CategoryFilter). All four now route through a new `TooltipEngine:AttachFromSpec(widget, spec)` helper so future kinds get tooltip support in one line instead of duplicating the recipe-lookup boilerplate.
**Internal**
- Send-to-Auctionator now reads deficit selectors (`stock.buy.cart`, `stock.herbs.list`) directly instead of routing through a persisted cart projection. Removed `account.cart` (`shoppingList`, `herbCart`, `dirty`) from SavedVariables -- the cart was a redundant snapshot, persisted-but-unread, and the source of the accumulation bug above. Existing installs auto-drop the stale `account.cart` slot on first load. Aligns VDS with the HDGR Mogul tab's send-to-Auctionator pattern.
- `test_layout_compute` now exercises the Stock view (Craft mode) and asserts `Layout._overSpecWarned` is empty after every Compute. Previously the test only loaded the master `VDS_LayoutConfig.lua` and skipped the four sub-LayoutConfig modules (`_Default`, `_Canvas`, `_Live`, `_Warehouse`), so panel-internal sections were missing from the normalized tree and the engine's over-spec check never ran on them. The dual footer rows landed with a 244px width inside a 224px container and only surfaced at runtime via a chat warning; the regression net would now catch the same class of bug offline.
- `test_first_paint` + `test_controller_wire_smoke` now load `VDS_TooltipEngine` + `VDS_TooltipRecipes` before the Components / Controllers dofiles. The new `AttachFromSpec` calls in widget builds (searchBox, tabBar, dropdowns) require the engine module at file-load time; the wire-smoke also needs it for `LiveSlot`-style controller-attached tooltips.
## Version 2.1.3 (Released May 2026)
**Canvas tab reliability**
- Canvas now opens with your last-session decor list instantly, instead of "Loading..." while the housing catalog primes. The catalog is snapshotted to SavedVariables on every successful fetch and re-hydrated on /reload before the live searcher returns. First-ever Canvas open on a new install still waits for the live fetch; every session after that is instant.
- When the live catalog search fails to return data, VDS now auto-retries up to 3 times (5 seconds each) with a fresh searcher each attempt, instead of getting stuck on "Loading..." forever. Visible status during the retry: "Loading dyeable decor..." -> "Catalog stuck, retrying... (N/3)" -> "Catalog unavailable" if all attempts fail. Addresses the "stuck on Loading..." case reported on Reddit.
- After a hard "Catalog unavailable" failure, switching tabs and back into Canvas triggers a fresh retry attempt -- no need to /reload unless that also fails. Recovers transient failures (network blips, slow Blizzard backend, addon-priming races) automatically.
- Live catalog fetch is now deferred until you open VDS and view the Canvas tab (mirrors Blizzard's own Housing Dashboard, which lazy-loads its catalog when you click it). Previously VDS would kick the searcher at login for users whose saved view was Canvas -- that's the window where the housing backend is least likely to be ready on fresh chars / cold machines. Combined with snapshot rehydrate, the user-visible cost of the deferral is zero: you still see your last-session decor list the moment Canvas opens. Should make the retry / failure path much rarer in practice.
**Live Customize mode**
- New **Snapshot** button next to Cancel/Apply -- saves the currently-displayed dye scheme as a variant without applying. Useful for capturing a palette you've found on existing decor before experimenting. Dedup is automatic; identical palettes are bumped to the top of the variants list instead of duplicating.
- **Apply** button now greys out when there are no pending dye changes, instead of being clickable but a no-op.
- Footer layout tightened: "Auto-save applied" -> "Auto-save" so the action buttons (Snapshot/Cancel/Apply) fit without clipping at narrow widths.
**Config sidebar**
- New **Open Debug Log** button under the Debug Mode checkbox. Opens the same popup window as /vds log. Useful for grabbing logs for bug reports without remembering the slash command.
**Debug log window**
- Every line now has a `[HH:MM:SS]` timestamp prefix for correlating events to chat / Blizzard event timing.
- New Discord invite footer in the log popup -- one click to copy the invite URL when grabbing logs for a bug report.
- Hint text + footer message now use readable text colors (previously dim grey, easily missed).
**Internal**
- Every tooltip in VDS now lives in a central `VDS.TooltipRecipes` registry. Widget specs reference recipes by name (`tooltip = { recipe = "..." }`) instead of inline strings/tables/functions. Boot validator enforces declaration on every widget. Sets up the seam for future localization and consistent tooltip styling.
- Catalog hydration (snapshot rehydrate + live searcher Init) consolidated under a single `Hydrate()` entry point on the DecorInfoResolver. Previously the two phases ran at different lifecycle points (rehydrate at module-enable, Init at canvas-shown); now both fire from the same canvas-shown wake event in the correct snapshot-then-live order. Easier to reason about, easier to log, removes a class of "why did rehydrate fire but Init didn't" debugging puzzles.
- Herb item-name pre-warm moved out of `Init.lua` into `ItemNameResolver`'s own `onEnable`. Init.lua no longer pokes into module-specific bootstrap code; each module owns its own hydration lifecycle.
## Version 2.1.2 (Released May 2026)
**Canvas tab**
- Loadout chips now support right-click to rename and shift+right-click to delete. Previously the only way to remove a saved loadout was to enter Live Customize mode on the actual decor and use the gallery tile -- a Canvas-tab cleanup loop is now possible without leaving the tab.
- The "+" save tile pulses through a rainbow color cycle (the same spectrum used by the title bar) whenever the current channel colors are not saved as a loadout for the selected decor. It quiets the moment the combo matches a saved loadout or you save it. Tooltip switches to "Loadout not saved -- click to save" while pulsing.
- The "+" tile is now hidden when you're at the 10/10 cap for a decor instead of misleadingly inviting another save that would silently fail.
- The "+" tile is now a hollow bordered icon in keeping with the rest of the chip wall, instead of a brassy gold block.
**Fixes**
- Item names that read as "Loading..." on first paint of a cold session now resolve reliably. The async name resolver now uses Blizzard's canonical ItemEventListener primitive (the same one AllTheThings uses) which wraps the kick + listen wiring around C_Item.RequestLoadItemDataByID and ITEM_DATA_LOAD_RESULT. Replaces the previous interim fix which was listening for the wrong event. Affects herb names in Stock tab, Canvas decor picker, Warehouse rows, and anywhere else item names appear.
## Version 2.1.1 (Released May 2026)
**UX**
- ESC now closes the main window, matching the journal/collections/character panel behaviour. (Boggle, Discord)
**Fixes**
- Herb names that read as "Herb <itemID>" on first paint now resolve and re-paint when the item info arrives, instead of staying stuck for the rest of the session. The async name resolver was kicking C_Item.GetItemNameByID, which warms a name-only cache but does NOT fire GET_ITEM_INFO_RECEIVED -- so the re-paint trigger never arrived for cold items. Now also calls C_Item.RequestLoadItemDataByID in the miss path to force the full-info fetch that the event actually listens to.
- Canvas decor picker no longer renders empty on the first open of a cold session (especially noticeable on slower machines where the housing catalog populates after VDS's initial searcher pass). DecorInfoResolver now listens for HOUSING_CATALOG_CATEGORY_UPDATED / HOUSING_CATALOG_SUBCATEGORY_UPDATED and re-runs the catalog search if the prior pass returned zero. Previously the only fix was /reload. (Boggle, Discord)
## Version 2.1.0 (Released May 2026)
**Canvas tab**
- The Canvas decor picker now has a Category dropdown above the list to narrow decor by Housing category.
- A new Scope filter at the top of the Canvas tab narrows the available dyes to a curated theme or one of your custom palettes. Default is "All Dyes".
- Saved loadouts for the selected decor appear as color chips below the channel pickers in the preview panel. Click a chip to apply.
- Each row in the Canvas decor picker now shows droplet icons for the decor's dye channels, plus a count badge for how many saved loadouts you have for that decor.
- Picker lists every available dyeable decor, including decor you don't own.
**Fixes**
- Saving the same color combination twice for one decor no longer creates a duplicate entry.
- Clear button now resets all three channel pickers.
- Category dropdown no longer flashes "All Categories (0)" on first open.
## Version 2.0.0 (Released May 2026)
Complete rewrite. The colored vials look the same; everything underneath is new.
**New: Stock tab**
- Set per-color-group target counts (e.g. "3 of every red"), with per-dye
overrides for the specific dyes you want more of.
- Deficit roll-up across bags, bank, reagent bank, and warband bank.
- One-click Restock-and-Send-to-AH: Buy mode ships missing dyes to an
Auctionator shopping list; Craft mode ships the cheapest herbs needed to
craft them. Auctionator is a soft dependency.
- Master +/- bumps every group target at once (shift-click for x10).
- Per-dye reset button reverts an override back to the group default.
**New defaults**
- "Replace Blizzard's dye picker" is on by default for new installs.
- Custom palette and Canvas loadout creation pre-fills "Palette N" /
"Loadout N" with an auto-incrementing number; press Enter to accept.
**Live dye mode polish**
- Focused slot now has a gold border matching the Canvas channel picker.
- Cost preview tracks Blizzard's dye-bottle spend as you preview changes.
**Tabs:** Colors / Custom / Theme / Stock / Herbs / Canvas.
**Migration**
- Your custom palettes carry forward from v1.x.
- Other state (cart, loadouts, dyeable-item cache, minimap/panel position)
resets to defaults on first launch.
**Slash commands:** `/vds` / `/dyes` (toggle), `/vds debug`, `/vds minimap`,
`/vds hardreset`.

