From 4bfa32b1f6be77d5ce8a1f9d532ebe9e53a932c8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 6 Sep 2026 07:27:50 +0000 Subject: [PATCH] fix: refresh charges after bag state settles --- .../workflows/fix-delayed-charge-refresh.yml | 55 ------------------- UI/BagFrame.lua | 39 ++++++++++--- 2 files changed, 32 insertions(+), 62 deletions(-) delete mode 100644 .github/workflows/fix-delayed-charge-refresh.yml diff --git a/.github/workflows/fix-delayed-charge-refresh.yml b/.github/workflows/fix-delayed-charge-refresh.yml deleted file mode 100644 index ee91856..0000000 --- a/.github/workflows/fix-delayed-charge-refresh.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: Apply delayed charge refresh - -on: - push: - branches: - - refactor/consolidate-patch-layers - -permissions: - contents: write - -jobs: - patch: - if: github.actor != 'github-actions[bot]' - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - with: - ref: refactor/consolidate-patch-layers - fetch-depth: 0 - - - name: Use BAG_UPDATE_DELAYED for charge overlays - shell: python - run: | - from pathlib import Path - - p = Path('UI/BagFrame.lua') - t = p.read_text(encoding='utf-8') - - old = ''' local bagUpdateFrame = CreateFrame("Frame")\n bagUpdateFrame:RegisterEvent("BAG_UPDATE")\n bagUpdateFrame:SetScript("OnEvent", function()\n if currentViewChar then return end\n if not Guda_BagFrame:IsShown() then return end\n\n -- Only handle player bags (0-4) - use tonumber for safe comparison\n local bagID = tonumber(arg1)\n if not bagID or bagID < 0 or bagID > 4 then\n return -- Skip bank bags (5-10) and invalid bags\n end\n\n local viewType = addon.Modules.DB:GetSetting("bagViewType") or "single"\n addon:DebugCategory("BAG_UPDATE (BagFrame): bagID=%d, viewType=%s", bagID, viewType)\n\n -- A charge use can fire BAG_UPDATE without changing item link or stack count.\n -- Refresh only already-known charge overlays before the incremental diff path.\n BagFrame:RefreshKnownChargeOverlays(bagID)\n''' - - new = ''' local pendingChargeBags = {}\n local bagUpdateFrame = CreateFrame("Frame")\n bagUpdateFrame:RegisterEvent("BAG_UPDATE")\n bagUpdateFrame:RegisterEvent("BAG_UPDATE_DELAYED")\n bagUpdateFrame:SetScript("OnEvent", function()\n -- ClassicAPI fires BAG_UPDATE_DELAYED at the tail of the world tick, after\n -- all BAG_UPDATE events for that frame and after bag contents have settled.\n -- This is the correct point to rescan instance-only data such as charges.\n if event == "BAG_UPDATE_DELAYED" then\n if not currentViewChar and Guda_BagFrame:IsShown() then\n for pendingBagID in pairs(pendingChargeBags) do\n pendingChargeBags[pendingBagID] = nil\n BagFrame:RefreshKnownChargeOverlays(pendingBagID)\n end\n else\n -- The positive charge cache was already invalidated on BAG_UPDATE.\n -- If bags are hidden, a future render will therefore read fresh data.\n for pendingBagID in pairs(pendingChargeBags) do\n pendingChargeBags[pendingBagID] = nil\n end\n end\n return\n end\n\n -- Only handle player bags (0-4) - use tonumber for safe comparison.\n local bagID = tonumber(arg1)\n if not bagID or bagID < 0 or bagID > 4 then\n return -- Skip bank bags (5-10) and invalid bags\n end\n\n -- BAG_UPDATE itself can arrive before the new charge count is readable.\n -- Invalidate now, remember the changed bag, but defer tooltip work until\n -- BAG_UPDATE_DELAYED. Normal stacks keep their cached negative result.\n if addon.Modules.ItemDetection and addon.Modules.ItemDetection.InvalidateCharges then\n addon.Modules.ItemDetection:InvalidateCharges(bagID)\n end\n pendingChargeBags[bagID] = true\n\n if currentViewChar then return end\n if not Guda_BagFrame:IsShown() then return end\n\n local viewType = addon.Modules.DB:GetSetting("bagViewType") or "single"\n addon:DebugCategory("BAG_UPDATE (BagFrame): bagID=%d, viewType=%s", bagID, viewType)\n''' - - if old not in t: - raise SystemExit('BagFrame BAG_UPDATE charge block not found') - t = t.replace(old, new, 1) - p.write_text(t, encoding='utf-8') - - Path('.github/workflows/fix-delayed-charge-refresh.yml').unlink() - - - name: Validate Lua - run: | - sudo apt-get update -qq - sudo apt-get install -y -qq lua5.1 - set -e - find . -name '*.lua' -print0 | while IFS= read -r -d '' f; do - luac5.1 -p "$f" - done - - - name: Commit patch - run: | - git config user.name "github-actions[bot]" - git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add -A - git commit -m "fix: refresh charges after bag state settles" - git push origin HEAD:refactor/consolidate-patch-layers diff --git a/UI/BagFrame.lua b/UI/BagFrame.lua index 4d65713..0b1b07e 100644 --- a/UI/BagFrame.lua +++ b/UI/BagFrame.lua @@ -4324,25 +4324,50 @@ function BagFrame:Initialize() -- Update on bag changes (debounced to prevent lag on rapid bag updates) -- Register directly to access arg1 (bagID that changed) for incremental cache updates + local pendingChargeBags = {} local bagUpdateFrame = CreateFrame("Frame") bagUpdateFrame:RegisterEvent("BAG_UPDATE") + bagUpdateFrame:RegisterEvent("BAG_UPDATE_DELAYED") bagUpdateFrame:SetScript("OnEvent", function() - if currentViewChar then return end - if not Guda_BagFrame:IsShown() then return end + -- ClassicAPI fires BAG_UPDATE_DELAYED at the tail of the world tick, after + -- all BAG_UPDATE events for that frame and after bag contents have settled. + -- This is the correct point to rescan instance-only data such as charges. + if event == "BAG_UPDATE_DELAYED" then + if not currentViewChar and Guda_BagFrame:IsShown() then + for pendingBagID in pairs(pendingChargeBags) do + pendingChargeBags[pendingBagID] = nil + BagFrame:RefreshKnownChargeOverlays(pendingBagID) + end + else + -- The positive charge cache was already invalidated on BAG_UPDATE. + -- If bags are hidden, a future render will therefore read fresh data. + for pendingBagID in pairs(pendingChargeBags) do + pendingChargeBags[pendingBagID] = nil + end + end + return + end - -- Only handle player bags (0-4) - use tonumber for safe comparison + -- Only handle player bags (0-4) - use tonumber for safe comparison. local bagID = tonumber(arg1) if not bagID or bagID < 0 or bagID > 4 then return -- Skip bank bags (5-10) and invalid bags end + -- BAG_UPDATE itself can arrive before the new charge count is readable. + -- Invalidate now, remember the changed bag, but defer tooltip work until + -- BAG_UPDATE_DELAYED. Normal stacks keep their cached negative result. + if addon.Modules.ItemDetection and addon.Modules.ItemDetection.InvalidateCharges then + addon.Modules.ItemDetection:InvalidateCharges(bagID) + end + pendingChargeBags[bagID] = true + + if currentViewChar then return end + if not Guda_BagFrame:IsShown() then return end + local viewType = addon.Modules.DB:GetSetting("bagViewType") or "single" addon:DebugCategory("BAG_UPDATE (BagFrame): bagID=%d, viewType=%s", bagID, viewType) - -- A charge use can fire BAG_UPDATE without changing item link or stack count. - -- Refresh only already-known charge overlays before the incremental diff path. - BagFrame:RefreshKnownChargeOverlays(bagID) - -- Check if sorting is in progress - use full redraw with throttle local isSorting = addon.Modules.SortEngine and addon.Modules.SortEngine.sortingInProgress