-- states/inventory.lua — the item grid. -- -- The inventoryCursorPopup patch already speaks item details, but only when an -- item is actually under the cursor. Moving onto an empty slot, or switching to -- an empty tab, produced silence -- so you could not tell whether the cursor had -- moved, which tab you were on, or that the tab was simply empty. -- -- This descriptor owns narration for this screen instead: it reports the item if -- there is one, "empty" if not, and the category whenever the tab changes. -- patches/popups.lua stands down for any state that has a descriptor, so the two -- never double-speak. local itemCategories = require("modules.item.categories") local lastTab return { read = function(stateTable, menus) local window = menus.getAnyUpvalue(stateTable, "inventoryWindow") if type(window) ~= "table" or not window.getItemOnCursor then return nil, nil end local position = window.cursorPosition if type(position) ~= "number" then return nil, nil end -- activeTabIndex lives inside the window closure, not the state file, so -- reach it through one of the window's own methods. local tabIndex if window.adjustTab then tabIndex = menus.getUpvalue(window.adjustTab, "activeTabIndex") end local parts = {} if tabIndex and tabIndex ~= lastTab then lastTab = tabIndex local category = itemCategories[tabIndex] parts[#parts + 1] = (category and category.header) or ("tab " .. tabIndex) end local ok, item = pcall(window.getItemOnCursor) if ok and item then parts[#parts + 1] = item.name or item.templateId or "item" if item.quantity and item.quantity > 1 then parts[#parts + 1] = "x" .. item.quantity end else parts[#parts + 1] = "empty" end parts[#parts + 1] = "slot " .. position return table.concat(parts, ", "), tostring(tabIndex) .. ":" .. tostring(position) .. ":" .. tostring(ok and item and (item.name or "?")) end, }