fix: mailbox tooltip
This commit is contained in:
+25
-5
@@ -95,6 +95,31 @@ function Utils:GetItemInfo(itemLink)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Create a hidden tooltip for scanning
|
||||||
|
local scanTooltip = CreateFrame("GameTooltip", "GudaBagScanTooltip", nil, "GameTooltipTemplate")
|
||||||
|
scanTooltip:SetOwner(WorldFrame, "ANCHOR_NONE")
|
||||||
|
|
||||||
|
-- Get item link from mailbox attachment (WoW 1.12.1 workaround)
|
||||||
|
function Utils:GetInboxItemLink(index, itemIndex)
|
||||||
|
-- In 1.12.1, GameTooltip:GetHyperlink() does not exist.
|
||||||
|
-- Actually, in 1.12.1, there's no official API to get the link from a mailbox item
|
||||||
|
-- if GetInboxItemLink(index) is not available (it's often NOT available in Vanilla).
|
||||||
|
|
||||||
|
-- Let's try to use GetItemInfo(name) as the primary way.
|
||||||
|
local name = GetInboxItem(index, itemIndex)
|
||||||
|
if name then
|
||||||
|
local _, link = GetItemInfo(name)
|
||||||
|
if link then
|
||||||
|
return link
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Fallback: If we still don't have it, we might try to scan the tooltip for the name
|
||||||
|
-- but GetInboxItem already gave us the name.
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
-- Get quality color
|
-- Get quality color
|
||||||
function Utils:GetQualityColor(quality)
|
function Utils:GetQualityColor(quality)
|
||||||
local color = addon.Constants.QUALITY_COLORS[quality] or addon.Constants.QUALITY_COLORS[1]
|
local color = addon.Constants.QUALITY_COLORS[quality] or addon.Constants.QUALITY_COLORS[1]
|
||||||
@@ -156,12 +181,7 @@ function Utils:FormatTimeAgo(timestamp)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Create hidden tooltip for scanning (only once)
|
-- Create hidden tooltip for scanning (only once)
|
||||||
local scanTooltip = nil
|
|
||||||
local function GetScanTooltip()
|
local function GetScanTooltip()
|
||||||
if not scanTooltip then
|
|
||||||
scanTooltip = CreateFrame("GameTooltip", "GudaBagScanTooltip", nil, "GameTooltipTemplate")
|
|
||||||
scanTooltip:SetOwner(WorldFrame, "ANCHOR_NONE")
|
|
||||||
end
|
|
||||||
return scanTooltip
|
return scanTooltip
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
+44
-34
@@ -27,42 +27,40 @@ end
|
|||||||
|
|
||||||
-- Scan a single mail item
|
-- Scan a single mail item
|
||||||
function MailboxScanner:ScanMailItem(index)
|
function MailboxScanner:ScanMailItem(index)
|
||||||
-- GetInboxItem(index) returns: packageIcon, stationeryIcon, sender, subject, money, CODAmount, daysLeft, hasItem, wasRead, wasReturned, textCreated, canReply, isGM
|
-- GetInboxHeaderInfo(index) returns: packageIcon, stationeryIcon, sender, subject, money, CODAmount, daysLeft, hasItem, wasRead, wasReturned, textCreated, canReply, isGM
|
||||||
local packageIcon, stationeryIcon, sender, subject, money, CODAmount, daysLeft, hasItem, wasRead, wasReturned, textCreated, canReply, isGM = GetInboxItem(index)
|
local packageIcon, stationeryIcon, sender, subject, money, CODAmount, daysLeft, hasItem, wasRead, wasReturned, textCreated, canReply, isGM = GetInboxHeaderInfo(index)
|
||||||
|
|
||||||
local itemData = nil
|
local items = {}
|
||||||
if hasItem then
|
if hasItem then
|
||||||
addon:Debug("Scanning mail item %d", index)
|
-- Turtle WoW supports up to 12 attachments per mail
|
||||||
-- In 1.12.1, GetInboxItemLink(index) returns the link
|
-- GetInboxItem(index, itemIndex) returns: name, texture, count, quality, canUse
|
||||||
local itemLink = GetInboxItemLink(index)
|
local name, texture, count, quality, canUse = GetInboxItem(index, itemIndex)
|
||||||
|
if name then
|
||||||
|
local itemLink = addon.Modules.Utils:GetInboxItemLink(index, itemIndex)
|
||||||
|
|
||||||
-- GetInboxItemInfo(index) returns: name, texture, count, quality, canUse
|
local itemData = {
|
||||||
local infoName, infoTexture, infoCount, infoQuality, infoCanUse = GetInboxItemInfo(index)
|
link = itemLink,
|
||||||
|
texture = texture or "Interface\\Icons\\INV_Misc_Bag_08",
|
||||||
|
count = count or 1,
|
||||||
|
quality = quality or 0,
|
||||||
|
name = name,
|
||||||
|
}
|
||||||
|
|
||||||
addon:Debug("Mail item %d: infoName=%s, infoTexture=%s", index, tostring(infoName), tostring(infoTexture))
|
-- If we have a link, try to get more detailed info
|
||||||
|
if itemLink then
|
||||||
-- Even if link is missing (not cached), we can store what we have from GetInboxItemInfo
|
local itemName, link, itemQuality, iLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice = addon.Modules.Utils:GetItemInfo(itemLink)
|
||||||
itemData = {
|
if itemName then
|
||||||
link = itemLink,
|
itemData.name = itemName
|
||||||
texture = infoTexture or packageIcon or "Interface\\Icons\\INV_Misc_Bag_08",
|
itemData.quality = itemQuality or itemData.quality
|
||||||
count = infoCount or 1,
|
itemData.iLevel = iLevel
|
||||||
quality = infoQuality or 0,
|
itemData.type = itemType
|
||||||
name = infoName or subject or "Unknown Item",
|
itemData.class = itemCategory
|
||||||
}
|
itemData.subclass = itemSubType
|
||||||
|
itemData.equipSlot = itemEquipLoc
|
||||||
-- If we have a link, try to get more detailed info
|
if itemTexture then itemData.texture = itemTexture end
|
||||||
if itemLink then
|
end
|
||||||
local itemName, link, itemQuality, iLevel, itemCategory, itemType, itemStackCount, itemSubType, itemTexture, itemEquipLoc, itemSellPrice = addon.Modules.Utils:GetItemInfo(itemLink)
|
end
|
||||||
if itemName then
|
table.insert(items, itemData)
|
||||||
itemData.name = itemName
|
|
||||||
itemData.quality = itemQuality or itemData.quality
|
|
||||||
itemData.iLevel = iLevel
|
|
||||||
itemData.type = itemType
|
|
||||||
itemData.class = itemCategory
|
|
||||||
itemData.subclass = itemSubType
|
|
||||||
itemData.equipSlot = itemEquipLoc
|
|
||||||
if itemTexture then itemData.texture = itemTexture end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -72,8 +70,9 @@ function MailboxScanner:ScanMailItem(index)
|
|||||||
money = money,
|
money = money,
|
||||||
CODAmount = CODAmount,
|
CODAmount = CODAmount,
|
||||||
daysLeft = daysLeft,
|
daysLeft = daysLeft,
|
||||||
hasItem = hasItem,
|
hasItem = (table.getn(items) > 0),
|
||||||
item = itemData,
|
item = items[1],
|
||||||
|
items = items,
|
||||||
wasRead = wasRead,
|
wasRead = wasRead,
|
||||||
packageIcon = packageIcon,
|
packageIcon = packageIcon,
|
||||||
}
|
}
|
||||||
@@ -111,6 +110,17 @@ function MailboxScanner:Initialize()
|
|||||||
end)
|
end)
|
||||||
end, "MailboxScanner")
|
end, "MailboxScanner")
|
||||||
|
|
||||||
|
-- Register for GET_ITEM_INFO_RECEIVED to refresh if item data arrives
|
||||||
|
addon.Modules.Events:Register("GET_ITEM_INFO_RECEIVED", function()
|
||||||
|
if mailboxOpen then
|
||||||
|
addon:Debug("GET_ITEM_INFO_RECEIVED: Refreshing mailbox")
|
||||||
|
MailboxScanner:SaveToDatabase()
|
||||||
|
end
|
||||||
|
end, "MailboxScanner")
|
||||||
|
|
||||||
|
-- Register for UI_ERROR_MESSAGE to handle "item not found" situations if needed
|
||||||
|
-- (Some items might not be in cache and fail silently otherwise)
|
||||||
|
|
||||||
-- Mailbox closed
|
-- Mailbox closed
|
||||||
addon.Modules.Events:OnMailClosed(function()
|
addon.Modules.Events:OnMailClosed(function()
|
||||||
-- Final save on close
|
-- Final save on close
|
||||||
|
|||||||
+58
-13
@@ -11,6 +11,8 @@ scanTooltip:SetOwner(WorldFrame, "ANCHOR_NONE")
|
|||||||
-- Check if an item is a quest item by scanning its tooltip
|
-- Check if an item is a quest item by scanning its tooltip
|
||||||
-- Check if an item is a quest item by scanning its tooltip and determine type
|
-- Check if an item is a quest item by scanning its tooltip and determine type
|
||||||
local function IsQuestItem(bagID, slotID, isBank)
|
local function IsQuestItem(bagID, slotID, isBank)
|
||||||
|
bagID = tonumber(bagID)
|
||||||
|
slotID = tonumber(slotID)
|
||||||
if not bagID or not slotID then return false end
|
if not bagID or not slotID then return false end
|
||||||
|
|
||||||
scanTooltip:ClearLines()
|
scanTooltip:ClearLines()
|
||||||
@@ -117,6 +119,8 @@ end
|
|||||||
|
|
||||||
-- Scan tooltip for red text that is NOT a durability line
|
-- Scan tooltip for red text that is NOT a durability line
|
||||||
local function IsItemUnusable(bagID, slotID, isBank)
|
local function IsItemUnusable(bagID, slotID, isBank)
|
||||||
|
bagID = tonumber(bagID)
|
||||||
|
slotID = tonumber(slotID)
|
||||||
if not bagID or not slotID then return false end
|
if not bagID or not slotID then return false end
|
||||||
|
|
||||||
-- Some clients require SetOwner before every SetBagItem/SetInventoryItem to populate lines
|
-- Some clients require SetOwner before every SetBagItem/SetInventoryItem to populate lines
|
||||||
@@ -425,6 +429,10 @@ end
|
|||||||
|
|
||||||
-- Set item data
|
-- Set item data
|
||||||
function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCharName, matchesFilter, isReadOnly)
|
function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCharName, matchesFilter, isReadOnly)
|
||||||
|
-- Proactively convert to number to avoid comparisons with strings in downstream functions
|
||||||
|
bagID = tonumber(bagID)
|
||||||
|
slotID = tonumber(slotID)
|
||||||
|
|
||||||
-- Proactively clear any previous cooldown overlay state before reassigning this pooled button
|
-- Proactively clear any previous cooldown overlay state before reassigning this pooled button
|
||||||
do
|
do
|
||||||
local cd = getglobal(self:GetName().."Cooldown") or self.cooldown
|
local cd = getglobal(self:GetName().."Cooldown") or self.cooldown
|
||||||
@@ -459,6 +467,8 @@ function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCha
|
|||||||
self.otherChar = otherCharName
|
self.otherChar = otherCharName
|
||||||
self.isReadOnly = isReadOnly or false -- Track if this is read-only mode
|
self.isReadOnly = isReadOnly or false -- Track if this is read-only mode
|
||||||
self.isMail = false -- Clear mailbox flag by default
|
self.isMail = false -- Clear mailbox flag by default
|
||||||
|
self.mailIndex = nil
|
||||||
|
self.mailItemIndex = nil
|
||||||
|
|
||||||
-- Re-register for drag/drop every time (crucial for button reuse in Classic/Vanilla)
|
-- Re-register for drag/drop every time (crucial for button reuse in Classic/Vanilla)
|
||||||
if not self.isReadOnly and not self.otherChar then
|
if not self.isReadOnly and not self.otherChar then
|
||||||
@@ -486,6 +496,8 @@ function Guda_ItemButton_SetItem(self, bagID, slotID, itemData, isBank, otherCha
|
|||||||
matchesFilter = true
|
matchesFilter = true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
self.mailData = nil -- Clear mail metadata by default
|
||||||
|
|
||||||
-- Use Blizzard's default count fontstring (ContainerFrameItemButtonTemplate creates $parentCount)
|
-- Use Blizzard's default count fontstring (ContainerFrameItemButtonTemplate creates $parentCount)
|
||||||
local countText = getglobal(self:GetName().."Count")
|
local countText = getglobal(self:GetName().."Count")
|
||||||
local emptySlotBg = getglobal(self:GetName().."_EmptySlotBg")
|
local emptySlotBg = getglobal(self:GetName().."_EmptySlotBg")
|
||||||
@@ -947,17 +959,7 @@ end
|
|||||||
|
|
||||||
-- OnEnter handler (show tooltip)
|
-- OnEnter handler (show tooltip)
|
||||||
function Guda_ItemButton_OnEnter(self)
|
function Guda_ItemButton_OnEnter(self)
|
||||||
-- DETACH from Blizzard's internal tooltip logic for mailbox items
|
-- Highlight the corresponding bag button in the footer (works for empty and filled slots)
|
||||||
if self.isMail or this.isMail or (this:GetParent() and this:GetParent():GetName() == "Guda_MailboxFrame_ItemContainer") then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Prevent Blizzard's ContainerFrameItemButton_OnEnter from running if it somehow got through
|
|
||||||
if not self.bagID or self.bagID == -100 then
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Highlight the corresponding bag button in the footer (works for empty and filled slots)
|
|
||||||
if not self.otherChar and self.bagID then
|
if not self.otherChar and self.bagID then
|
||||||
if self.isBank then
|
if self.isBank then
|
||||||
-- Bank item - highlight bank bag button
|
-- Bank item - highlight bank bag button
|
||||||
@@ -969,7 +971,7 @@ function Guda_ItemButton_OnEnter(self)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Early return for empty slots (no tooltip needed)
|
-- Early return for empty slots (no tooltip needed)
|
||||||
if not self.hasItem then
|
if not self.hasItem and not self.isMail then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -977,7 +979,50 @@ function Guda_ItemButton_OnEnter(self)
|
|||||||
-- important position of tooltip
|
-- important position of tooltip
|
||||||
GameTooltip:SetPoint("BOTTOMRIGHT", self, "TOPLEFT", 10, 0)
|
GameTooltip:SetPoint("BOTTOMRIGHT", self, "TOPLEFT", 10, 0)
|
||||||
|
|
||||||
if self.otherChar or self.isReadOnly then
|
-- Mailbox tooltip handling
|
||||||
|
if self.isMail then
|
||||||
|
local currentPlayerName = addon.Modules.DB:GetPlayerFullName()
|
||||||
|
if (not self.otherChar or self.otherChar == currentPlayerName) and self.mailIndex then
|
||||||
|
-- Live mailbox for current character
|
||||||
|
GameTooltip:SetInboxItem(self.mailIndex, self.mailItemIndex or 1)
|
||||||
|
elseif self.itemData and self.itemData.link then
|
||||||
|
-- Read-only / other character mailbox
|
||||||
|
GameTooltip.GudaViewedCharacter = self.otherChar
|
||||||
|
GameTooltip:SetHyperlink(self.itemData.link)
|
||||||
|
elseif self.itemData and self.itemData.name then
|
||||||
|
-- Money or generic mail
|
||||||
|
GameTooltip:AddLine(self.itemData.name, 1, 1, 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Add mailbox metadata if available
|
||||||
|
local mailData = self.mailData
|
||||||
|
if mailData then
|
||||||
|
-- If we already added a line (for money/generic), or SetHyperlink/SetInboxItem added lines,
|
||||||
|
-- we might want a separator if we're adding sender info.
|
||||||
|
if GameTooltip:NumLines() > 0 then
|
||||||
|
GameTooltip:AddLine(" ")
|
||||||
|
end
|
||||||
|
|
||||||
|
if mailData.sender then
|
||||||
|
GameTooltip:AddLine("From: " .. mailData.sender, 1, 1, 1)
|
||||||
|
end
|
||||||
|
if mailData.subject then
|
||||||
|
GameTooltip:AddLine("Subject: " .. mailData.subject, 1, 1, 0.8)
|
||||||
|
end
|
||||||
|
if (mailData.money or 0) > 0 and not (self.itemData and self.itemData.name == "Money") then
|
||||||
|
GameTooltip:AddLine("Money: " .. addon.Modules.Utils:FormatMoney(mailData.money), 1, 1, 1)
|
||||||
|
end
|
||||||
|
if (mailData.CODAmount or 0) > 0 then
|
||||||
|
GameTooltip:AddLine("COD: " .. addon.Modules.Utils:FormatMoney(mailData.CODAmount), 1, 0, 0)
|
||||||
|
end
|
||||||
|
if mailData.daysLeft then
|
||||||
|
GameTooltip:AddLine("Days left: " .. math.floor(mailData.daysLeft), 0.5, 0.5, 0.5)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
GameTooltip:Show()
|
||||||
|
return
|
||||||
|
elseif self.otherChar or self.isReadOnly then
|
||||||
GameTooltip.GudaViewedCharacter = self.otherChar
|
GameTooltip.GudaViewedCharacter = self.otherChar
|
||||||
if self.itemData and self.itemData.link then
|
if self.itemData and self.itemData.link then
|
||||||
GameTooltip:SetHyperlink(self.itemData.link)
|
GameTooltip:SetHyperlink(self.itemData.link)
|
||||||
|
|||||||
+131
-104
@@ -10,6 +10,9 @@ local currentViewChar = nil
|
|||||||
local searchText = ""
|
local searchText = ""
|
||||||
local isReadOnlyMode = true -- Mailbox is always read-only in this addon (viewing offline data)
|
local isReadOnlyMode = true -- Mailbox is always read-only in this addon (viewing offline data)
|
||||||
local itemButtons = {}
|
local itemButtons = {}
|
||||||
|
local mailboxRows = {}
|
||||||
|
local currentPage = 1
|
||||||
|
local ITEMS_PER_PAGE = 7
|
||||||
local mailboxClickCatcher = nil
|
local mailboxClickCatcher = nil
|
||||||
|
|
||||||
-- OnLoad
|
-- OnLoad
|
||||||
@@ -70,9 +73,23 @@ end
|
|||||||
-- Show specific character's mailbox
|
-- Show specific character's mailbox
|
||||||
function MailboxFrame:ShowCharacter(fullName)
|
function MailboxFrame:ShowCharacter(fullName)
|
||||||
currentViewChar = fullName
|
currentViewChar = fullName
|
||||||
|
currentPage = 1
|
||||||
self:Update()
|
self:Update()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Pagination
|
||||||
|
function MailboxFrame:NextPage()
|
||||||
|
currentPage = currentPage + 1
|
||||||
|
self:Update()
|
||||||
|
end
|
||||||
|
|
||||||
|
function MailboxFrame:PrevPage()
|
||||||
|
if currentPage > 1 then
|
||||||
|
currentPage = currentPage - 1
|
||||||
|
self:Update()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- Initialize module
|
-- Initialize module
|
||||||
function MailboxFrame:Initialize()
|
function MailboxFrame:Initialize()
|
||||||
-- Register events if needed
|
-- Register events if needed
|
||||||
@@ -105,13 +122,38 @@ function MailboxFrame:Update()
|
|||||||
matchesSearch = true
|
matchesSearch = true
|
||||||
elseif mail.subject and string.find(string.lower(mail.subject), searchText) then
|
elseif mail.subject and string.find(string.lower(mail.subject), searchText) then
|
||||||
matchesSearch = true
|
matchesSearch = true
|
||||||
|
elseif mail.items then
|
||||||
|
for _, item in ipairs(mail.items) do
|
||||||
|
if item.name and string.find(string.lower(item.name), searchText) then
|
||||||
|
matchesSearch = true
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
elseif mail.item and mail.item.name and string.find(string.lower(mail.item.name), searchText) then
|
elseif mail.item and mail.item.name and string.find(string.lower(mail.item.name), searchText) then
|
||||||
matchesSearch = true
|
matchesSearch = true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if matchesSearch then
|
if matchesSearch then
|
||||||
table.insert(filteredItems, mail)
|
-- Flatten mails with multiple items so they all show up in the grid
|
||||||
|
if mail.items and table.getn(mail.items) > 1 then
|
||||||
|
for itemIndex, item in ipairs(mail.items) do
|
||||||
|
local mailCopy = {}
|
||||||
|
for k, v in pairs(mail) do mailCopy[k] = v end
|
||||||
|
mailCopy.item = item
|
||||||
|
mailCopy.mailIndex = i
|
||||||
|
mailCopy.itemIndex = itemIndex
|
||||||
|
-- Clear items list in copy to avoid recursive flattening
|
||||||
|
mailCopy.items = nil
|
||||||
|
table.insert(filteredItems, mailCopy)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local mailCopy = {}
|
||||||
|
for k, v in pairs(mail) do mailCopy[k] = v end
|
||||||
|
mailCopy.mailIndex = i
|
||||||
|
mailCopy.itemIndex = 1
|
||||||
|
table.insert(filteredItems, mailCopy)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -135,61 +177,76 @@ function MailboxFrame:Update()
|
|||||||
MoneyFrame_Update("Guda_MailboxFrame_MoneyFrame", totalMoney)
|
MoneyFrame_Update("Guda_MailboxFrame_MoneyFrame", totalMoney)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Display mailbox items in a grid
|
-- Display mailbox items in a list
|
||||||
function MailboxFrame:DisplayItems(items, charFullName)
|
function MailboxFrame:DisplayItems(items, charFullName)
|
||||||
local container = getglobal("Guda_MailboxFrame_ItemContainer")
|
local container = getglobal("Guda_MailboxFrame_ItemContainer")
|
||||||
-- Explicitly set container ID to -100 to avoid being picked up as a bag
|
|
||||||
if container.SetID then container:SetID(-100) end
|
|
||||||
|
|
||||||
local columns = 10
|
-- Hide all existing rows first
|
||||||
local buttonSize = 34
|
for _, row in pairs(mailboxRows) do
|
||||||
local spacing = 2
|
row:Hide()
|
||||||
|
|
||||||
-- Hide all existing buttons first
|
|
||||||
for _, button in pairs(itemButtons) do
|
|
||||||
button:Hide()
|
|
||||||
button.inUse = false
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local row = 0
|
local totalItems = table.getn(items)
|
||||||
local col = 0
|
local totalPages = math.max(1, math.ceil(totalItems / ITEMS_PER_PAGE))
|
||||||
|
|
||||||
for i, mail in ipairs(items) do
|
if currentPage > totalPages then
|
||||||
local button = itemButtons[i]
|
currentPage = totalPages
|
||||||
if not button then
|
end
|
||||||
button = Guda_GetItemButton(container)
|
|
||||||
itemButtons[i] = button
|
local startIndex = (currentPage - 1) * ITEMS_PER_PAGE + 1
|
||||||
|
local endIndex = math.min(startIndex + ITEMS_PER_PAGE - 1, totalItems)
|
||||||
|
|
||||||
|
local rowIndex = 1
|
||||||
|
for i = startIndex, endIndex do
|
||||||
|
local mail = items[i]
|
||||||
|
local row = mailboxRows[rowIndex]
|
||||||
|
if not row then
|
||||||
|
row = CreateFrame("Frame", "Guda_MailboxRow" .. rowIndex, container, "Guda_MailboxRowTemplate")
|
||||||
|
mailboxRows[rowIndex] = row
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Consistently set button size for the mailbox grid
|
row:ClearAllPoints()
|
||||||
button:SetWidth(buttonSize)
|
row:SetPoint("TOPLEFT", container, "TOPLEFT", 0, -(rowIndex - 1) * 55)
|
||||||
button:SetHeight(buttonSize)
|
|
||||||
|
|
||||||
button:ClearAllPoints()
|
-- Fill row data
|
||||||
button:SetPoint("TOPLEFT", container, "TOPLEFT", col * (buttonSize + spacing), -row * (buttonSize + spacing))
|
getglobal(row:GetName() .. "_Sender"):SetText(mail.sender or "Unknown")
|
||||||
|
getglobal(row:GetName() .. "_Subject"):SetText(mail.subject or "No Subject")
|
||||||
|
|
||||||
-- Set button data
|
local expireText = ""
|
||||||
button.isBank = false
|
if mail.daysLeft then
|
||||||
button.otherChar = charFullName
|
if mail.daysLeft < 1 then
|
||||||
button.isMail = true -- Custom flag for mailbox items
|
expireText = string.format("|cffff0000%dh|r", math.floor(mail.daysLeft * 24))
|
||||||
button.inUse = true
|
else
|
||||||
|
expireText = string.format("%dd", math.floor(mail.daysLeft))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
getglobal(row:GetName() .. "_ExpireTime"):SetText(expireText)
|
||||||
|
|
||||||
|
-- Item Button
|
||||||
|
local itemButton = getglobal(row:GetName() .. "_ItemButton")
|
||||||
|
-- Re-assign shared namespace function if needed, but it should be available globally or via addon
|
||||||
|
|
||||||
|
itemButton.isBank = false
|
||||||
|
itemButton.otherChar = charFullName
|
||||||
|
itemButton.mailData = mail
|
||||||
|
itemButton.isMail = true
|
||||||
|
itemButton.mailIndex = mail.mailIndex
|
||||||
|
itemButton.mailItemIndex = mail.itemIndex or 1
|
||||||
|
|
||||||
if mail.item and (mail.item.texture or mail.item.link) then
|
if mail.item and (mail.item.texture or mail.item.link) then
|
||||||
Guda_ItemButton_SetItem(button, nil, nil, mail.item, false, charFullName, true, true)
|
Guda_ItemButton_SetItem(itemButton, nil, nil, mail.item, false, charFullName, true, true)
|
||||||
-- Re-enforce size because SetItem overrides it with global settings
|
itemButton.isMail = true
|
||||||
button:SetWidth(buttonSize)
|
itemButton.mailData = mail
|
||||||
button:SetHeight(buttonSize)
|
itemButton.mailIndex = mail.mailIndex
|
||||||
button.isMail = true -- Re-apply after SetItem clears it
|
itemButton.mailItemIndex = mail.itemIndex or 1
|
||||||
else
|
else
|
||||||
-- Use SetItem with nil itemData to clear the button properly first
|
Guda_ItemButton_SetItem(itemButton, nil, nil, nil, false, charFullName, true, true)
|
||||||
Guda_ItemButton_SetItem(button, nil, nil, nil, false, charFullName, true, true)
|
itemButton.isMail = true
|
||||||
button:SetWidth(buttonSize)
|
itemButton.mailData = mail
|
||||||
button:SetHeight(buttonSize)
|
itemButton.mailIndex = mail.mailIndex
|
||||||
button.isMail = true -- Re-apply after SetItem clears it
|
itemButton.mailItemIndex = 1
|
||||||
|
|
||||||
-- Then show our custom icon for money/mail
|
local icon = getglobal(itemButton:GetName().."IconTexture") or getglobal(itemButton:GetName().."Icon")
|
||||||
button.itemData = nil
|
|
||||||
local icon = getglobal(button:GetName().."IconTexture") or getglobal(button:GetName().."Icon")
|
|
||||||
if icon then
|
if icon then
|
||||||
if (mail.money or 0) > 0 then
|
if (mail.money or 0) > 0 then
|
||||||
icon:SetTexture("Interface\\Icons\\INV_Misc_Coin_01")
|
icon:SetTexture("Interface\\Icons\\INV_Misc_Coin_01")
|
||||||
@@ -201,73 +258,42 @@ function MailboxFrame:DisplayItems(items, charFullName)
|
|||||||
icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
|
icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
|
||||||
icon:Show()
|
icon:Show()
|
||||||
end
|
end
|
||||||
|
if itemButton.qualityBorder then itemButton.qualityBorder:Hide() end
|
||||||
if button.qualityBorder then button.qualityBorder:Hide() end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Custom Tooltip for mail items
|
-- Row Money Frame
|
||||||
button.mailData = mail -- Store data on button to avoid closure issues in Lua 5.0
|
local moneyFrame = getglobal(row:GetName() .. "_MoneyFrame")
|
||||||
button.isMail = true -- Redundant set to be safe
|
if (mail.money or 0) > 0 then
|
||||||
button:SetScript("OnEnter", function()
|
MoneyFrame_Update(moneyFrame:GetName(), mail.money)
|
||||||
-- Force detachment from Blizzard logic inside the closure as well
|
moneyFrame:Show()
|
||||||
if this.SetID then this:SetID(0) end
|
else
|
||||||
this.isMail = true
|
moneyFrame:Hide()
|
||||||
|
|
||||||
local mailData = this.mailData
|
|
||||||
if not mailData then return end
|
|
||||||
|
|
||||||
-- Explicitly use GameTooltip:ClearLines() and SetOwner to ensure a clean tooltip
|
|
||||||
GameTooltip:SetOwner(this, "ANCHOR_RIGHT")
|
|
||||||
GameTooltip:ClearLines()
|
|
||||||
|
|
||||||
if mailData.item and mailData.item.link then
|
|
||||||
GameTooltip:SetHyperlink(mailData.item.link)
|
|
||||||
-- Add a gap if there's also sender/subject info to show
|
|
||||||
GameTooltip:AddLine(" ")
|
|
||||||
elseif mailData.item and mailData.item.name then
|
|
||||||
-- Fallback if we have item data but no link (e.g. not in cache yet)
|
|
||||||
GameTooltip:AddLine(mailData.item.name, 1, 1, 1)
|
|
||||||
GameTooltip:AddLine(" ")
|
|
||||||
end
|
|
||||||
|
|
||||||
GameTooltip:AddLine("From: " .. (mailData.sender or "Unknown"), 1, 1, 1)
|
|
||||||
GameTooltip:AddLine("Subject: " .. (mailData.subject or "No Subject"), 1, 1, 0.8)
|
|
||||||
|
|
||||||
if (mailData.money or 0) > 0 then
|
|
||||||
GameTooltip:AddLine("Money: " .. addon.Modules.Utils:FormatMoney(mailData.money), 1, 1, 1)
|
|
||||||
end
|
|
||||||
if (mailData.CODAmount or 0) > 0 then
|
|
||||||
GameTooltip:AddLine("COD: " .. addon.Modules.Utils:FormatMoney(mailData.CODAmount), 1, 0, 0)
|
|
||||||
end
|
|
||||||
|
|
||||||
if mailData.daysLeft then
|
|
||||||
GameTooltip:AddLine("Days left: " .. math.floor(mailData.daysLeft), 0.5, 0.5, 0.5)
|
|
||||||
end
|
|
||||||
|
|
||||||
GameTooltip:Show()
|
|
||||||
end)
|
|
||||||
button:SetScript("OnLeave", function()
|
|
||||||
GameTooltip:Hide()
|
|
||||||
end)
|
|
||||||
|
|
||||||
-- Mailbox is read-only, so no clicking/dragging
|
|
||||||
button:RegisterForClicks()
|
|
||||||
button:SetScript("OnClick", nil)
|
|
||||||
button:SetScript("OnDragStart", nil)
|
|
||||||
button:SetScript("OnReceiveDrag", nil)
|
|
||||||
|
|
||||||
button:Show()
|
|
||||||
|
|
||||||
col = col + 1
|
|
||||||
if col >= columns then
|
|
||||||
col = 0
|
|
||||||
row = row + 1
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
row:Show()
|
||||||
|
rowIndex = rowIndex + 1
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Adjust container height
|
-- Update pagination buttons
|
||||||
local totalRows = row + (col > 0 and 1 or 0)
|
local prevBtn = getglobal("Guda_MailboxFrame_PrevPageButton")
|
||||||
container:SetHeight(math.max(420, totalRows * (buttonSize + spacing)))
|
local nextBtn = getglobal("Guda_MailboxFrame_NextPageButton")
|
||||||
|
|
||||||
|
if currentPage > 1 then
|
||||||
|
prevBtn:Enable()
|
||||||
|
else
|
||||||
|
prevBtn:Disable()
|
||||||
|
end
|
||||||
|
|
||||||
|
if currentPage < totalPages then
|
||||||
|
nextBtn:Enable()
|
||||||
|
else
|
||||||
|
nextBtn:Disable()
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Update page text in footer
|
||||||
|
local footerFontString = getglobal("Guda_MailboxFrame_Footer_Text")
|
||||||
|
local footerText = footerFontString:GetText() or ""
|
||||||
|
footerFontString:SetText(footerText .. " (Page " .. currentPage .. " of " .. totalPages .. ")")
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Search text changed
|
-- Search text changed
|
||||||
@@ -279,6 +305,7 @@ function Guda_MailboxFrame_OnSearchTextChanged()
|
|||||||
else
|
else
|
||||||
searchText = string.lower(text)
|
searchText = string.lower(text)
|
||||||
end
|
end
|
||||||
|
currentPage = 1
|
||||||
MailboxFrame:Update()
|
MailboxFrame:Update()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,82 @@
|
|||||||
<Ui xmlns="http://www.blizzard.com/wow/ui/"
|
<Ui xmlns="http://www.blizzard.com/wow/ui/"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/">
|
||||||
|
|
||||||
|
<!-- Mailbox Row Template -->
|
||||||
|
<Frame name="Guda_MailboxRowTemplate" virtual="true">
|
||||||
|
<Size>
|
||||||
|
<AbsDimension x="360" y="50"/>
|
||||||
|
</Size>
|
||||||
|
<Layers>
|
||||||
|
<Layer level="BACKGROUND">
|
||||||
|
<Texture name="$parent_Background">
|
||||||
|
<Anchors>
|
||||||
|
<Anchor point="TOPLEFT"/>
|
||||||
|
<Anchor point="BOTTOMRIGHT"/>
|
||||||
|
</Anchors>
|
||||||
|
<Color r="1" g="1" b="1" a="0.05"/>
|
||||||
|
</Texture>
|
||||||
|
</Layer>
|
||||||
|
<Layer level="ARTWORK">
|
||||||
|
<FontString name="$parent_Sender" inherits="GameFontNormal" justifyH="LEFT">
|
||||||
|
<Size>
|
||||||
|
<AbsDimension x="140" y="16"/>
|
||||||
|
</Size>
|
||||||
|
<Anchors>
|
||||||
|
<Anchor point="TOPLEFT">
|
||||||
|
<Offset>
|
||||||
|
<AbsDimension x="60" y="-8"/>
|
||||||
|
</Offset>
|
||||||
|
</Anchor>
|
||||||
|
</Anchors>
|
||||||
|
</FontString>
|
||||||
|
<FontString name="$parent_Subject" inherits="GameFontHighlightSmall" justifyH="LEFT">
|
||||||
|
<Size>
|
||||||
|
<AbsDimension x="280" y="14"/>
|
||||||
|
</Size>
|
||||||
|
<Anchors>
|
||||||
|
<Anchor point="TOPLEFT" relativeTo="$parent_Sender" relativePoint="BOTTOMLEFT">
|
||||||
|
<Offset>
|
||||||
|
<AbsDimension x="0" y="-2"/>
|
||||||
|
</Offset>
|
||||||
|
</Anchor>
|
||||||
|
</Anchors>
|
||||||
|
</FontString>
|
||||||
|
<FontString name="$parent_ExpireTime" inherits="GameFontDisableSmall" justifyH="RIGHT">
|
||||||
|
<Size>
|
||||||
|
<AbsDimension x="100" y="12"/>
|
||||||
|
</Size>
|
||||||
|
<Anchors>
|
||||||
|
<Anchor point="TOPRIGHT">
|
||||||
|
<Offset>
|
||||||
|
<AbsDimension x="-10" y="-8"/>
|
||||||
|
</Offset>
|
||||||
|
</Anchor>
|
||||||
|
</Anchors>
|
||||||
|
</FontString>
|
||||||
|
</Layer>
|
||||||
|
</Layers>
|
||||||
|
<Frames>
|
||||||
|
<Button name="$parent_ItemButton" inherits="Guda_ItemButtonTemplate">
|
||||||
|
<Anchors>
|
||||||
|
<Anchor point="LEFT" relativeTo="$parent" relativePoint="LEFT">
|
||||||
|
<Offset>
|
||||||
|
<AbsDimension x="10" y="0"/>
|
||||||
|
</Offset>
|
||||||
|
</Anchor>
|
||||||
|
</Anchors>
|
||||||
|
</Button>
|
||||||
|
<Frame name="$parent_MoneyFrame" inherits="SmallMoneyFrameTemplate">
|
||||||
|
<Anchors>
|
||||||
|
<Anchor point="BOTTOMRIGHT">
|
||||||
|
<Offset>
|
||||||
|
<AbsDimension x="-10" y="8"/>
|
||||||
|
</Offset>
|
||||||
|
</Anchor>
|
||||||
|
</Anchors>
|
||||||
|
</Frame>
|
||||||
|
</Frames>
|
||||||
|
</Frame>
|
||||||
|
|
||||||
<!-- Mailbox Frame -->
|
<!-- Mailbox Frame -->
|
||||||
<Frame name="Guda_MailboxFrame" toplevel="true" movable="true" enableMouse="true" hidden="true" parent="UIParent">
|
<Frame name="Guda_MailboxFrame" toplevel="true" movable="true" enableMouse="true" hidden="true" parent="UIParent">
|
||||||
<Size>
|
<Size>
|
||||||
@@ -224,6 +300,43 @@
|
|||||||
</Anchor>
|
</Anchor>
|
||||||
</Anchors>
|
</Anchors>
|
||||||
</Frame>
|
</Frame>
|
||||||
|
|
||||||
|
<!-- Pagination -->
|
||||||
|
<Button name="$parent_PrevPageButton" inherits="UIPanelButtonTemplate" text="Prev">
|
||||||
|
<Size>
|
||||||
|
<AbsDimension x="60" y="22"/>
|
||||||
|
</Size>
|
||||||
|
<Anchors>
|
||||||
|
<Anchor point="BOTTOMLEFT">
|
||||||
|
<Offset>
|
||||||
|
<AbsDimension x="120" y="10"/>
|
||||||
|
</Offset>
|
||||||
|
</Anchor>
|
||||||
|
</Anchors>
|
||||||
|
<Scripts>
|
||||||
|
<OnClick>
|
||||||
|
Guda.Modules.MailboxFrame:PrevPage()
|
||||||
|
</OnClick>
|
||||||
|
</Scripts>
|
||||||
|
</Button>
|
||||||
|
|
||||||
|
<Button name="$parent_NextPageButton" inherits="UIPanelButtonTemplate" text="Next">
|
||||||
|
<Size>
|
||||||
|
<AbsDimension x="60" y="22"/>
|
||||||
|
</Size>
|
||||||
|
<Anchors>
|
||||||
|
<Anchor point="BOTTOMRIGHT" relativeTo="$parent_MoneyFrame" relativePoint="BOTTOMLEFT">
|
||||||
|
<Offset>
|
||||||
|
<AbsDimension x="-10" y="0"/>
|
||||||
|
</Offset>
|
||||||
|
</Anchor>
|
||||||
|
</Anchors>
|
||||||
|
<Scripts>
|
||||||
|
<OnClick>
|
||||||
|
Guda.Modules.MailboxFrame:NextPage()
|
||||||
|
</OnClick>
|
||||||
|
</Scripts>
|
||||||
|
</Button>
|
||||||
</Frames>
|
</Frames>
|
||||||
|
|
||||||
<Scripts>
|
<Scripts>
|
||||||
|
|||||||
Reference in New Issue
Block a user