progress in category bank view
This commit is contained in:
+116
-3
@@ -45,22 +45,36 @@ end
|
||||
|
||||
-- Get cached bank data, or scan if cache is invalid
|
||||
function BankScanner:GetBankData()
|
||||
addon:DebugCategory("GetBankData: ENTRY bankOpen=%s, cacheValid=%s, hasCache=%s",
|
||||
tostring(bankOpen), tostring(cacheValid), tostring(bankCache ~= nil))
|
||||
|
||||
-- Check if bank is accessible (either officially open OR we can access bank slots)
|
||||
local bankAccessible = bankOpen
|
||||
local forceRescan = false
|
||||
if not bankAccessible then
|
||||
-- Try to access main bank - if it has slots, bank is actually accessible
|
||||
local testSlots = GetContainerNumSlots(-1)
|
||||
if testSlots and testSlots > 0 then
|
||||
bankAccessible = true
|
||||
addon:DebugCategory("GetBankData: bankOpen=false but bank accessible (%d slots)", testSlots)
|
||||
-- Force rescan when bankOpen is false but bank is accessible
|
||||
-- This handles edge cases where cache has stale data
|
||||
forceRescan = true
|
||||
addon:DebugCategory("GetBankData: bankOpen=false but bank accessible (%d slots), forcing rescan", testSlots)
|
||||
end
|
||||
end
|
||||
|
||||
if not bankAccessible then
|
||||
addon:DebugCategory("GetBankData: bank NOT accessible, returning empty")
|
||||
return {}
|
||||
end
|
||||
|
||||
-- Force rescan when bankOpen state is inconsistent
|
||||
if forceRescan then
|
||||
cacheValid = false
|
||||
end
|
||||
|
||||
if cacheValid and bankCache then
|
||||
addon:DebugCategory("GetBankData: using cached data (cacheValid=true)")
|
||||
-- Process any dirty slots incrementally
|
||||
for bagID, slots in pairs(dirtySlots) do
|
||||
if bagID ~= nil and type(slots) == "table" then
|
||||
@@ -91,16 +105,64 @@ function BankScanner:GetBankData()
|
||||
dirtySlots = {}
|
||||
|
||||
-- Check for invalidated bags (nil entries) and rescan them
|
||||
local rescannedBags = 0
|
||||
for _, bagID in ipairs(addon.Constants.BANK_BAGS) do
|
||||
if bankCache[bagID] == nil then
|
||||
addon:DebugCategory("GetBankData: rescanning invalidated bag %d", bagID)
|
||||
bankCache[bagID] = self:ScanBankBag(bagID)
|
||||
rescannedBags = rescannedBags + 1
|
||||
end
|
||||
end
|
||||
if rescannedBags > 0 then
|
||||
addon:DebugCategory("GetBankData: rescanned %d invalidated bags", rescannedBags)
|
||||
end
|
||||
|
||||
-- Verify cache matches reality for ALL bank bags
|
||||
-- Only force full rescan when items are ADDED (API > cache)
|
||||
-- When items are REMOVED (cache > API), the incremental update + empty placeholders should handle it
|
||||
local needsFullRescan = false
|
||||
for _, bagID in ipairs(addon.Constants.BANK_BAGS) do
|
||||
local cacheItems = 0
|
||||
local realItems = 0
|
||||
if bankCache[bagID] and bankCache[bagID].slots then
|
||||
for slotID, item in pairs(bankCache[bagID].slots) do
|
||||
if item then cacheItems = cacheItems + 1 end
|
||||
end
|
||||
end
|
||||
-- Check actual API state
|
||||
local numSlots = GetContainerNumSlots(bagID) or 0
|
||||
for slot = 1, numSlots do
|
||||
local texture = GetContainerItemInfo(bagID, slot)
|
||||
if texture then realItems = realItems + 1 end
|
||||
end
|
||||
if realItems > cacheItems then
|
||||
-- Items were ADDED to bank - need full rescan to show them
|
||||
addon:DebugCategory("GetBankData: ITEMS ADDED in bag %d! cache=%d, API=%d -> full rescan",
|
||||
bagID, cacheItems, realItems)
|
||||
needsFullRescan = true
|
||||
elseif cacheItems > realItems then
|
||||
-- Items were REMOVED from bank - incremental update handles this
|
||||
-- Just update the cache for this bag to reflect removals
|
||||
addon:DebugCategory("GetBankData: ITEMS REMOVED in bag %d, cache=%d, API=%d -> incremental update",
|
||||
bagID, cacheItems, realItems)
|
||||
-- Rescan just this bag to update the cache (not full UI redraw)
|
||||
bankCache[bagID] = self:ScanBankBag(bagID)
|
||||
end
|
||||
end
|
||||
if needsFullRescan then
|
||||
-- Force a full rescan only when items were added
|
||||
cacheValid = false
|
||||
bankCache = self:ScanBank()
|
||||
cacheValid = true
|
||||
addon:DebugCategory("GetBankData: forced full rescan due to new items")
|
||||
end
|
||||
|
||||
return bankCache
|
||||
end
|
||||
|
||||
-- Cache miss - do full scan
|
||||
addon:DebugCategory("GetBankData: cache miss, doing full scan (cacheValid=%s, bankCache=%s)",
|
||||
tostring(cacheValid), tostring(bankCache ~= nil))
|
||||
bankCache = self:ScanBank()
|
||||
cacheValid = true
|
||||
dirtySlots = {}
|
||||
@@ -120,11 +182,41 @@ function BankScanner:InvalidateCache()
|
||||
cacheValid = false
|
||||
end
|
||||
|
||||
-- Get the cached item count for a bag WITHOUT triggering a rescan
|
||||
-- Used for comparing before/after counts during event handling
|
||||
function BankScanner:GetCachedItemCount(bagID)
|
||||
if not bankCache or not bankCache[bagID] or not bankCache[bagID].slots then
|
||||
return 0
|
||||
end
|
||||
local count = 0
|
||||
for slotID, item in pairs(bankCache[bagID].slots) do
|
||||
if item then count = count + 1 end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
-- Invalidate a specific bag in the cache (force re-scan of just that bag)
|
||||
function BankScanner:InvalidateBag(bagID)
|
||||
if not bankOpen then return end
|
||||
if not bankCache then return end
|
||||
-- Allow invalidation if bank is accessible (not just officially open)
|
||||
local bankAccessible = bankOpen
|
||||
if not bankAccessible then
|
||||
local testSlots = GetContainerNumSlots(-1)
|
||||
if testSlots and testSlots > 0 then
|
||||
bankAccessible = true
|
||||
end
|
||||
end
|
||||
if not bankAccessible then
|
||||
addon:DebugCategory("InvalidateBag(%d): bank not accessible, skipping", bagID)
|
||||
return
|
||||
end
|
||||
if not bankCache then
|
||||
addon:DebugCategory("InvalidateBag(%d): no bankCache exists, skipping", bagID)
|
||||
return
|
||||
end
|
||||
local hadBag = (bankCache[bagID] ~= nil)
|
||||
bankCache[bagID] = nil
|
||||
addon:DebugCategory("InvalidateBag(%d): invalidated (hadBag=%s, cacheValid=%s)",
|
||||
bagID, tostring(hadBag), tostring(cacheValid))
|
||||
end
|
||||
|
||||
-- Scan all bank bags and return data (full scan)
|
||||
@@ -144,10 +236,24 @@ function BankScanner:ScanBank()
|
||||
end
|
||||
|
||||
local bankData = {}
|
||||
local totalItems = 0
|
||||
|
||||
for _, bagID in ipairs(addon.Constants.BANK_BAGS) do
|
||||
bankData[bagID] = self:ScanBankBag(bagID)
|
||||
local bagItems = 0
|
||||
if bankData[bagID] and bankData[bagID].slots then
|
||||
for _, item in pairs(bankData[bagID].slots) do
|
||||
if item then
|
||||
bagItems = bagItems + 1
|
||||
totalItems = totalItems + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if bagItems > 0 then
|
||||
addon:DebugCategory("ScanBank: bag %d has %d items", bagID, bagItems)
|
||||
end
|
||||
end
|
||||
addon:DebugCategory("ScanBank: total %d items across all bags", totalItems)
|
||||
|
||||
return bankData
|
||||
end
|
||||
@@ -174,18 +280,25 @@ function BankScanner:ScanBankBag(bagID)
|
||||
}
|
||||
|
||||
if not addon.Modules.Utils:IsBagValid(bagID) then
|
||||
addon:DebugCategory("ScanBankBag(%d): bag not valid", bagID)
|
||||
return bag
|
||||
end
|
||||
|
||||
local itemCount = 0
|
||||
for slot = 1, bag.numSlots do
|
||||
local itemData = addon.Modules.BagScanner:ScanSlot(bagID, slot)
|
||||
bag.slots[slot] = itemData
|
||||
|
||||
if not itemData then
|
||||
bag.freeSlots = bag.freeSlots + 1
|
||||
else
|
||||
itemCount = itemCount + 1
|
||||
end
|
||||
end
|
||||
|
||||
addon:DebugCategory("ScanBankBag(%d): numSlots=%d, items=%d, freeSlots=%d",
|
||||
bagID, bag.numSlots, itemCount, bag.freeSlots)
|
||||
|
||||
return bag
|
||||
end
|
||||
|
||||
|
||||
+113
-22
@@ -1988,6 +1988,9 @@ function BankFrame:Initialize()
|
||||
updateFrame:RegisterEvent("PLAYERBANKBAGSLOTS_CHANGED")
|
||||
updateFrame:RegisterEvent("BAG_UPDATE")
|
||||
updateFrame:SetScript("OnEvent", function()
|
||||
-- Debug: log ALL events received by this handler
|
||||
addon:DebugCategory("BankFrame EVENT: %s arg1=%s", tostring(event), tostring(arg1))
|
||||
|
||||
-- Check if we should process bank events:
|
||||
-- 1. Bank is officially open (IsBankOpen), OR
|
||||
-- 2. Our BankFrame is shown and we're viewing current character (for edge cases)
|
||||
@@ -1996,38 +1999,126 @@ function BankFrame:Initialize()
|
||||
local viewingCurrent = not currentViewChar
|
||||
|
||||
if not bankOpen and not (frameShown and viewingCurrent) then
|
||||
addon:DebugCategory("BankFrame event %s: bank not open and frame not shown, ignoring", event or "nil")
|
||||
addon:DebugCategory(" -> ignored (bank not open, frame not shown)")
|
||||
return
|
||||
end
|
||||
if currentViewChar then
|
||||
addon:DebugCategory(" -> ignored (viewing other character)")
|
||||
return
|
||||
end
|
||||
if currentViewChar then return end
|
||||
|
||||
-- Check if sorting is in progress - use full redraw with throttle
|
||||
local isSorting = addon.Modules.SortEngine and addon.Modules.SortEngine.sortingInProgress
|
||||
|
||||
if event == "PLAYERBANKSLOTS_CHANGED" and arg1 then
|
||||
-- arg1 is the slot number (1-28 for main bank)
|
||||
addon:DebugCategory("EVENT: PLAYERBANKSLOTS_CHANGED slot=%d, isSorting=%s", arg1, tostring(isSorting))
|
||||
-- Try single-slot update if not sorting
|
||||
if not isSorting then
|
||||
-- Invalidate bag scanner cache for fresh slot data
|
||||
-- NOTE: Don't clear ItemDetection cache - item properties don't change on move
|
||||
addon.Modules.BankScanner:InvalidateBag(-1)
|
||||
-- Try single-slot update
|
||||
local success = BankFrame:UpdateSingleSlot(-1, arg1)
|
||||
addon:DebugCategory(" UpdateSingleSlot(-1, %d) = %s", arg1, tostring(success))
|
||||
if success then
|
||||
-- Incremental update succeeded - no need for full redraw for THIS slot
|
||||
-- But don't cancel pending redraws - other slots might need them
|
||||
if event == "PLAYERBANKSLOTS_CHANGED" then
|
||||
-- arg1 is the slot number (1-28 for main bank), but can be nil in some cases
|
||||
local viewType = addon.Modules.DB:GetSetting("bankViewType") or "single"
|
||||
|
||||
if arg1 then
|
||||
-- Specific slot changed
|
||||
local rawTexture, rawCount = GetContainerItemInfo(-1, arg1)
|
||||
local rawLink = GetContainerItemLink(-1, arg1)
|
||||
local slotIsNowEmpty = (rawTexture == nil)
|
||||
addon:DebugCategory(" PLAYERBANKSLOTS_CHANGED slot=%d, slotIsNowEmpty=%s, isSorting=%s",
|
||||
arg1, tostring(slotIsNowEmpty), tostring(isSorting))
|
||||
|
||||
-- Try single-slot update if not sorting
|
||||
if not isSorting then
|
||||
-- Invalidate bag scanner cache for fresh slot data
|
||||
addon.Modules.BankScanner:InvalidateBag(-1)
|
||||
-- Try single-slot update
|
||||
local success = BankFrame:UpdateSingleSlot(-1, arg1)
|
||||
addon:DebugCategory(" UpdateSingleSlot(-1, %d) = %s", arg1, tostring(success))
|
||||
if success then
|
||||
-- Incremental update succeeded
|
||||
if slotIsNowEmpty then
|
||||
addon:DebugCategory(" -> slot emptied, incremental update done, no full redraw needed")
|
||||
else
|
||||
addon:DebugCategory(" -> item added, incremental update done")
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- Fallback: full redraw needed
|
||||
-- BUT if slot just became empty and we have no button, that's OK in Category View
|
||||
if slotIsNowEmpty and viewType == "category" then
|
||||
addon:DebugCategory(" -> slot emptied in Category View, no button exists, updating cache only")
|
||||
addon.Modules.BankScanner:InvalidateBag(-1)
|
||||
return
|
||||
end
|
||||
|
||||
addon:DebugCategory(" -> falling through to full redraw")
|
||||
addon.Modules.BankScanner:InvalidateBag(-1)
|
||||
else
|
||||
-- arg1 is nil - generic bank change notification
|
||||
-- In Category View, check if items were removed (no need for full redraw)
|
||||
addon:DebugCategory(" PLAYERBANKSLOTS_CHANGED arg1=nil (generic)")
|
||||
|
||||
if viewType == "category" then
|
||||
-- First, count items in the CURRENT API state (this is the "after" count)
|
||||
local realItems = 0
|
||||
local numSlots = GetContainerNumSlots(-1) or 0
|
||||
for slot = 1, numSlots do
|
||||
local texture = GetContainerItemInfo(-1, slot)
|
||||
if texture then realItems = realItems + 1 end
|
||||
end
|
||||
|
||||
-- Get the cached count BEFORE updating (this is the "before" count)
|
||||
-- Use GetCachedItemCount to avoid triggering mismatch detection
|
||||
local cacheItems = addon.Modules.BankScanner:GetCachedItemCount(-1)
|
||||
|
||||
addon:DebugCategory(" -> comparing cache=%d vs API=%d", cacheItems, realItems)
|
||||
|
||||
if realItems < cacheItems then
|
||||
-- Items were REMOVED - update only the emptied slots, no full redraw
|
||||
addon:DebugCategory(" -> items removed (%d -> %d), updating emptied slots only", cacheItems, realItems)
|
||||
|
||||
-- Find and update slots that became empty
|
||||
-- Use button's stored itemData (not cache, which may already be updated)
|
||||
if bankSlotToButton[-1] then
|
||||
for slotID, button in pairs(bankSlotToButton[-1]) do
|
||||
local buttonHadItem = button.itemData and button.itemData.link
|
||||
local currentTexture = GetContainerItemInfo(-1, slotID)
|
||||
|
||||
-- If button had item but API doesn't, this slot was emptied
|
||||
if buttonHadItem and not currentTexture then
|
||||
addon:DebugCategory(" -> slot %d emptied, updating button", slotID)
|
||||
-- Mark slot as emptied for placeholder tracking
|
||||
local category = button.itemCategory or "Miscellaneous"
|
||||
self:MarkSlotAsEmptied(-1, slotID, category, button.itemData)
|
||||
-- Update the button to show empty state
|
||||
local matchesFilter = self:PassesSearchFilter(nil)
|
||||
Guda_ItemButton_SetItem(button, -1, slotID, nil, true, nil, matchesFilter, isReadOnlyMode)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
addon.Modules.BankScanner:InvalidateBag(-1)
|
||||
return
|
||||
elseif realItems == cacheItems then
|
||||
-- No change in item count - might be item swap, skip update
|
||||
addon:DebugCategory(" -> item count unchanged (%d), skipping", realItems)
|
||||
return
|
||||
end
|
||||
-- Items were added - need full redraw
|
||||
addon:DebugCategory(" -> items added (%d -> %d), need full redraw", cacheItems, realItems)
|
||||
end
|
||||
|
||||
addon.Modules.BankScanner:InvalidateBag(-1)
|
||||
end
|
||||
-- Fallback: full redraw (sorting or single-slot failed)
|
||||
addon:DebugCategory(" -> falling through to full redraw")
|
||||
addon.Modules.BankScanner:InvalidateBag(-1)
|
||||
elseif event == "BAG_UPDATE" and arg1 then
|
||||
-- Check if this is a bank bag (5-10)
|
||||
if arg1 >= 5 and arg1 <= 10 then
|
||||
addon:DebugCategory("EVENT: BAG_UPDATE bankBag=%d, isSorting=%s", arg1, tostring(isSorting))
|
||||
-- Debug: count items in this bank bag via raw API
|
||||
local rawItemCount = 0
|
||||
local numSlots = GetContainerNumSlots(arg1) or 0
|
||||
for slot = 1, numSlots do
|
||||
local texture = GetContainerItemInfo(arg1, slot)
|
||||
if texture then rawItemCount = rawItemCount + 1 end
|
||||
end
|
||||
addon:DebugCategory("EVENT: BAG_UPDATE bankBag=%d, rawItems=%d, numSlots=%d, isSorting=%s",
|
||||
arg1, rawItemCount, numSlots, tostring(isSorting))
|
||||
-- Invalidate bag scanner cache for fresh slot data
|
||||
-- NOTE: Don't clear ItemDetection cache - item properties don't change on move
|
||||
addon.Modules.BankScanner:InvalidateBag(arg1)
|
||||
@@ -2056,8 +2147,8 @@ function BankFrame:Initialize()
|
||||
addon.Modules.BankScanner:ClearCache()
|
||||
end
|
||||
|
||||
-- Slightly longer delay to ensure WoW API has updated
|
||||
ScheduleBankFrameUpdate(0.15)
|
||||
-- Longer delay to ensure WoW API has fully updated after item moves
|
||||
ScheduleBankFrameUpdate(0.2)
|
||||
end)
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user