From bd4a40b0f236f014043ff11616ae11ea4853277c Mon Sep 17 00:00:00 2001
From: Brues <5278969+brues-code@users.noreply.github.com>
Date: Fri, 17 Jul 2026 14:45:49 -0500
Subject: [PATCH] Add newitem module: highlight freshly-acquired bag items
New module built on ClassicAPI's C_NewItems + BAG_NEW_ITEMS_UPDATED.
Glows bag slots (bags 0-4) holding items acquired since login, keyed on
item GUID so the flag survives rearranging. Hovering an item
acknowledges it (RemoveNewItem); closing the bags clears the rest via
ClearAll. Glow is UI-ActionButton-Border, sized off the slot width so it
tracks the icon_size config.
To stay decoupled from the bag frames, the bag module now broadcasts a
reusable "bag:closed" event through pfUI.events from its OnHide (carrying
the container so subscribers can tell backpack from bank), guarded so the
initial setup Hide() doesn't fire a phantom close.
Config: appearance.bags.newitem + newitem_color, with GUI toggles.
---
api/config.lua | 2 ++
env/translations_enUS.lua | 2 ++
init/modules.xml | 1 +
modules/bags.lua | 5 ++++
modules/gui.lua | 2 ++
modules/newitem.lua | 63 +++++++++++++++++++++++++++++++++++++++
pfUI.lua | 2 +-
7 files changed, 76 insertions(+), 1 deletion(-)
create mode 100644 modules/newitem.lua
diff --git a/api/config.lua b/api/config.lua
index ee777361..c335fad2 100644
--- a/api/config.lua
+++ b/api/config.lua
@@ -162,6 +162,8 @@ function pfUI:LoadConfig()
pfUI:UpdateConfig("appearance", "infight", "intensity", "16")
pfUI:UpdateConfig("appearance", "bags", "unusable", "1")
pfUI:UpdateConfig("appearance", "bags", "unusable_color", ".9,.2,.2,1")
+ pfUI:UpdateConfig("appearance", "bags", "newitem", "1")
+ pfUI:UpdateConfig("appearance", "bags", "newitem_color", "1,1,1,1")
pfUI:UpdateConfig("appearance", "bags", "borderlimit", "1")
pfUI:UpdateConfig("appearance", "bags", "borderonlygear", "0")
pfUI:UpdateConfig("appearance", "bags", "fulltext", "1")
diff --git a/env/translations_enUS.lua b/env/translations_enUS.lua
index 09e6b7e5..aaa565f7 100644
--- a/env/translations_enUS.lua
+++ b/env/translations_enUS.lua
@@ -411,6 +411,7 @@ pfUI_translation["enUS"] = {
["Highlight Equipped Items"] = nil,
["Highlight Not Usable Spells"] = nil,
["Highlight Out Of Mana Spells"] = nil,
+ ["Highlight New Items"] = nil,
["Highlight Out Of Range Spells"] = nil,
["Highlight Settings That Require Reload"] = nil,
["Highlight Unusable Items"] = nil,
@@ -529,6 +530,7 @@ pfUI_translation["enUS"] = {
["Network Latency"] = nil,
["Network Up"] = nil,
["New entry:"] = nil,
+ ["New Item Color"] = nil,
["NEW TIMER"] = nil,
["Next"] = nil,
["Next Memory Cleanup"] = nil,
diff --git a/init/modules.xml b/init/modules.xml
index 949eda24..67111e42 100644
--- a/init/modules.xml
+++ b/init/modules.xml
@@ -79,4 +79,5 @@
+
\ No newline at end of file
diff --git a/modules/bags.lua b/modules/bags.lua
index 56ce9e49..d8b1198b 100644
--- a/modules/bags.lua
+++ b/modules/bags.lua
@@ -337,6 +337,7 @@ pfUI:RegisterModule("bags", function ()
local chat = pfUI.chat and ( object == "bank" and pfUI.chat.left or pfUI.chat.right) or nil
frame:SetScript("OnShow", function()
+ frame.opened = true
if C.appearance.bags.hidechat == "1" and chat and chat:IsVisible() then
frame.chatWasOpen = true
chat:Hide()
@@ -355,6 +356,10 @@ pfUI:RegisterModule("bags", function ()
end
pfUI.bag:CreateBags(object)
PlaySound("INTERFACESOUND_BACKPACKCLOSE")
+ if frame.opened then
+ frame.opened = nil
+ pfUI.events:TriggerEvent("bag:closed", object)
+ end
end)
end
diff --git a/modules/gui.lua b/modules/gui.lua
index bf5726d5..0b587cd9 100644
--- a/modules/gui.lua
+++ b/modules/gui.lua
@@ -2413,6 +2413,8 @@ pfUI:RegisterModule("gui", function ()
CreateConfig(nil, T["Enable Item Quality Color For Equipment Only"], C.appearance.bags, "borderonlygear", "checkbox")
CreateConfig(nil, T["Highlight Unusable Items"], C.appearance.bags, "unusable", "checkbox")
CreateConfig(nil, T["Unusable Item Color"], C.appearance.bags, "unusable_color", "color")
+ CreateConfig(nil, T["Highlight New Items"], C.appearance.bags, "newitem", "checkbox")
+ CreateConfig(nil, T["New Item Color"], C.appearance.bags, "newitem_color", "color")
CreateConfig(nil, T["Enable Movable Bags"], C.appearance.bags, "movable", "checkbox")
CreateConfig(nil, T["Anchor Bags Above Chat"], C.appearance.bags, "abovechat", "checkbox")
CreateConfig(nil, T["Hide Chat When Bags Are Opened"], C.appearance.bags, "hidechat", "checkbox")
diff --git a/modules/newitem.lua b/modules/newitem.lua
new file mode 100644
index 00000000..6a29134f
--- /dev/null
+++ b/modules/newitem.lua
@@ -0,0 +1,63 @@
+pfUI:RegisterModule("newitem", function ()
+ if not pfUI.bag then return end
+ if C.appearance.bags.newitem ~= "1" then return end
+
+ pfUI.newitem = {}
+
+ local color = CreateColor(strsplit(",", C.appearance.bags.newitem_color))
+
+ function pfUI.newitem:UpdateSlot(bag, slot)
+ if bag < 0 or bag > 4 then return end
+ if not pfUI.bags[bag] then return end
+ if not pfUI.bags[bag].slots[slot] then return end
+
+ local frame = pfUI.bags[bag].slots[slot].frame
+
+ if not frame.newitem then
+ local glow = frame:CreateTexture(nil, "OVERLAY")
+ glow:SetTexture("Interface\\Buttons\\UI-ActionButton-Border")
+ glow:SetBlendMode("ADD")
+ glow:SetVertexColor(color:GetRGBA())
+ glow:SetPoint("CENTER", frame, "CENTER")
+ glow:Hide()
+ frame.newitem = glow
+
+ frame:HookScript("OnEnter", function()
+ C_NewItems.RemoveNewItem(bag, slot)
+ end)
+ end
+
+ local w = frame:GetWidth()
+ if w > 0 then frame.newitem:SetSize(w * 1.8, w * 1.8) end
+
+ frame.newitem:SetShown(frame.hasItem and C_NewItems.IsNewItem(bag, slot))
+ end
+
+ -- The new-item set can change without any slot's contents changing (an item
+ -- acknowledged, pruned when it leaves the bags, or ClearAll) -- re-evaluate
+ -- every decorated slot when that happens.
+ function pfUI.newitem:RefreshAll()
+ for bag in pairs(pfUI.bags) do
+ local slots = pfUI.bags[bag] and pfUI.bags[bag].slots
+ if slots then
+ for slot in pairs(slots) do
+ pfUI.newitem:UpdateSlot(bag, slot)
+ end
+ end
+ end
+ end
+
+ -- per-slot: pfUI re-runs UpdateSlot whenever a slot's contents change.
+ hooksecurefunc(pfUI.bag, "UpdateSlot", function(self, bag, slot)
+ pfUI.newitem:UpdateSlot(bag, slot)
+ end)
+
+ EventRegistry:RegisterFrameEventAndCallback("BAG_NEW_ITEMS_UPDATED", function()
+ pfUI.newitem:RefreshAll()
+ end)
+
+ pfUI.events:RegisterCallback("bag:closed", function(_, object)
+ if object then return end
+ C_NewItems.ClearAll()
+ end, "newitem")
+end)
diff --git a/pfUI.lua b/pfUI.lua
index 51e06c0f..5e9634d9 100644
--- a/pfUI.lua
+++ b/pfUI.lua
@@ -23,7 +23,7 @@ do
-- ClassicAPI dependency check.
-- pfUI relies pervasively on the modern C_* / SuperWoW / nameplate / focus
-- API surface that ClassicAPI polyfills, so presence is required.
- local PFUI_CLASSIC_API_MIN = 10605 -- (X*10000 + Y*100 + Z)
+ local PFUI_CLASSIC_API_MIN = 10700 -- (X*10000 + Y*100 + Z)
local PFUI_CLASSIC_API_LATEST = PFUI_CLASSIC_API_MIN
local PFUI_CLASSIC_API_WEBSITE = "https://github.com/brues-code/ClassicAPI"
local PFUI_CLASSIC_API_LATEST_URL = PFUI_CLASSIC_API_WEBSITE .. "/releases/latest"