303 lines
10 KiB
Lua
303 lines
10 KiB
Lua
-- Mailbox Frame
|
|
-- Mailbox viewing UI
|
|
|
|
local addon = Guda
|
|
|
|
local MailboxFrame = {}
|
|
addon.Modules.MailboxFrame = MailboxFrame
|
|
|
|
local currentViewChar = nil
|
|
local searchText = ""
|
|
local isReadOnlyMode = true -- Mailbox is always read-only in this addon (viewing offline data)
|
|
local itemButtons = {}
|
|
local mailboxClickCatcher = nil
|
|
|
|
-- OnLoad
|
|
function Guda_MailboxFrame_OnLoad(self)
|
|
-- Set up initial backdrop
|
|
addon:ApplyBackdrop(self, "DEFAULT_FRAME")
|
|
|
|
-- Set up search box placeholder
|
|
local searchBox = getglobal(self:GetName().."_SearchBar_SearchBox")
|
|
if searchBox then
|
|
searchBox:SetText("Search mailbox...")
|
|
searchBox:SetTextColor(0.5, 0.5, 0.5, 1)
|
|
end
|
|
|
|
-- Create invisible full-screen frame to catch clicks outside the mailbox frame while typing in search
|
|
if not mailboxClickCatcher then
|
|
mailboxClickCatcher = CreateFrame("Frame", "Guda_MailboxClickCatcher", UIParent)
|
|
mailboxClickCatcher:SetFrameStrata("BACKGROUND")
|
|
mailboxClickCatcher:SetAllPoints(UIParent)
|
|
mailboxClickCatcher:EnableMouse(true)
|
|
mailboxClickCatcher:Hide()
|
|
|
|
mailboxClickCatcher:SetScript("OnMouseDown", function()
|
|
if Guda_MailboxFrame_ClearSearch then
|
|
Guda_MailboxFrame_ClearSearch()
|
|
end
|
|
end)
|
|
end
|
|
end
|
|
|
|
-- Clear search focus
|
|
function Guda_MailboxFrame_ClearSearch()
|
|
local searchBox = getglobal("Guda_MailboxFrame_SearchBar_SearchBox")
|
|
if searchBox then
|
|
searchBox:ClearFocus()
|
|
end
|
|
end
|
|
|
|
-- OnShow
|
|
function Guda_MailboxFrame_OnShow(self)
|
|
-- Apply frame transparency
|
|
if Guda_ApplyBackgroundTransparency then
|
|
Guda_ApplyBackgroundTransparency()
|
|
end
|
|
|
|
MailboxFrame:Update()
|
|
end
|
|
|
|
-- Toggle visibility
|
|
function MailboxFrame:Toggle()
|
|
if Guda_MailboxFrame:IsShown() then
|
|
Guda_MailboxFrame:Hide()
|
|
else
|
|
Guda_MailboxFrame:Show()
|
|
end
|
|
end
|
|
|
|
-- Show specific character's mailbox
|
|
function MailboxFrame:ShowCharacter(fullName)
|
|
currentViewChar = fullName
|
|
self:Update()
|
|
end
|
|
|
|
-- Initialize module
|
|
function MailboxFrame:Initialize()
|
|
-- Register events if needed
|
|
end
|
|
|
|
-- Update the mailbox frame
|
|
function MailboxFrame:Update()
|
|
if not Guda_MailboxFrame:IsShown() then return end
|
|
|
|
-- Determine which character to show
|
|
local charFullName = currentViewChar or addon.Modules.DB:GetPlayerFullName()
|
|
local mailboxData = addon.Modules.DB:GetCharacterMailbox(charFullName)
|
|
|
|
-- Extract character name from fullName
|
|
local charName = charFullName
|
|
local dashPos = string.find(charFullName, "-")
|
|
if dashPos then
|
|
charName = string.sub(charFullName, 1, dashPos - 1)
|
|
end
|
|
|
|
getglobal("Guda_MailboxFrame_Title"):SetText(charName .. "'s Mailbox")
|
|
|
|
-- Filter items based on search text
|
|
local filteredItems = {}
|
|
for i, mail in ipairs(mailboxData) do
|
|
local matchesSearch = true
|
|
if searchText ~= "" then
|
|
matchesSearch = false
|
|
if mail.sender and string.find(string.lower(mail.sender), searchText) then
|
|
matchesSearch = true
|
|
elseif mail.subject and string.find(string.lower(mail.subject), searchText) then
|
|
matchesSearch = true
|
|
elseif mail.item and mail.item.name and string.find(string.lower(mail.item.name), searchText) then
|
|
matchesSearch = true
|
|
end
|
|
end
|
|
|
|
if matchesSearch then
|
|
table.insert(filteredItems, mail)
|
|
end
|
|
end
|
|
|
|
-- Display items
|
|
self:DisplayItems(filteredItems, charFullName)
|
|
|
|
-- Update footer info
|
|
local totalItems = table.getn(mailboxData)
|
|
local displayedItems = table.getn(filteredItems)
|
|
local footerText = string.format("Items: %d", totalItems)
|
|
if searchText ~= "" then
|
|
footerText = string.format("Filtered: %d / %d", displayedItems, totalItems)
|
|
end
|
|
getglobal("Guda_MailboxFrame_Footer_Text"):SetText(footerText)
|
|
|
|
-- Update money (total money in mailbox)
|
|
local totalMoney = 0
|
|
for _, mail in ipairs(mailboxData) do
|
|
totalMoney = totalMoney + (mail.money or 0)
|
|
end
|
|
MoneyFrame_Update("Guda_MailboxFrame_MoneyFrame", totalMoney)
|
|
end
|
|
|
|
-- Display mailbox items in a grid
|
|
function MailboxFrame:DisplayItems(items, charFullName)
|
|
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
|
|
local buttonSize = 34
|
|
local spacing = 2
|
|
|
|
-- Hide all existing buttons first
|
|
for _, button in pairs(itemButtons) do
|
|
button:Hide()
|
|
button.inUse = false
|
|
end
|
|
|
|
local row = 0
|
|
local col = 0
|
|
|
|
for i, mail in ipairs(items) do
|
|
local button = itemButtons[i]
|
|
if not button then
|
|
button = Guda_GetItemButton(container)
|
|
itemButtons[i] = button
|
|
end
|
|
|
|
-- Consistently set button size for the mailbox grid
|
|
button:SetWidth(buttonSize)
|
|
button:SetHeight(buttonSize)
|
|
|
|
button:ClearAllPoints()
|
|
button:SetPoint("TOPLEFT", container, "TOPLEFT", col * (buttonSize + spacing), -row * (buttonSize + spacing))
|
|
|
|
-- Set button data
|
|
button.isBank = false
|
|
button.otherChar = charFullName
|
|
button.isMail = true -- Custom flag for mailbox items
|
|
button.inUse = true
|
|
|
|
if mail.item and (mail.item.texture or mail.item.link) then
|
|
Guda_ItemButton_SetItem(button, nil, nil, mail.item, false, charFullName, true, true)
|
|
-- Re-enforce size because SetItem overrides it with global settings
|
|
button:SetWidth(buttonSize)
|
|
button:SetHeight(buttonSize)
|
|
button.isMail = true -- Re-apply after SetItem clears it
|
|
else
|
|
-- Use SetItem with nil itemData to clear the button properly first
|
|
Guda_ItemButton_SetItem(button, nil, nil, nil, false, charFullName, true, true)
|
|
button:SetWidth(buttonSize)
|
|
button:SetHeight(buttonSize)
|
|
button.isMail = true -- Re-apply after SetItem clears it
|
|
|
|
-- Then show our custom icon for money/mail
|
|
button.itemData = nil
|
|
local icon = getglobal(button:GetName().."IconTexture") or getglobal(button:GetName().."Icon")
|
|
if icon then
|
|
if (mail.money or 0) > 0 then
|
|
icon:SetTexture("Interface\\Icons\\INV_Misc_Coin_01")
|
|
elseif mail.packageIcon then
|
|
icon:SetTexture(mail.packageIcon)
|
|
else
|
|
icon:SetTexture("Interface\\Icons\\INV_Letter_15")
|
|
end
|
|
icon:SetTexCoord(0.08, 0.92, 0.08, 0.92)
|
|
icon:Show()
|
|
end
|
|
|
|
if button.qualityBorder then button.qualityBorder:Hide() end
|
|
end
|
|
|
|
-- Custom Tooltip for mail items
|
|
button.mailData = mail -- Store data on button to avoid closure issues in Lua 5.0
|
|
button.isMail = true -- Redundant set to be safe
|
|
button:SetScript("OnEnter", function()
|
|
-- Force detachment from Blizzard logic inside the closure as well
|
|
if this.SetID then this:SetID(0) end
|
|
this.isMail = true
|
|
|
|
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
|
|
|
|
-- Adjust container height
|
|
local totalRows = row + (col > 0 and 1 or 0)
|
|
container:SetHeight(math.max(420, totalRows * (buttonSize + spacing)))
|
|
end
|
|
|
|
-- Search text changed
|
|
function Guda_MailboxFrame_OnSearchTextChanged()
|
|
local searchBox = getglobal("Guda_MailboxFrame_SearchBar_SearchBox")
|
|
local text = searchBox:GetText()
|
|
if text == "Search mailbox..." then
|
|
searchText = ""
|
|
else
|
|
searchText = string.lower(text)
|
|
end
|
|
MailboxFrame:Update()
|
|
end
|
|
|
|
-- Show character selection menu
|
|
function Guda_MailboxFrame_ShowCharacterMenu()
|
|
local characters = addon.Modules.DB:GetAllCharacters(true, true)
|
|
local menu = {}
|
|
|
|
for i, char in ipairs(characters) do
|
|
local charFullName = char.fullName
|
|
table.insert(menu, {
|
|
text = char.name,
|
|
func = function() MailboxFrame:ShowCharacter(charFullName) end,
|
|
checked = (currentViewChar == char.fullName or (not currentViewChar and char.fullName == addon.Modules.DB:GetPlayerFullName()))
|
|
})
|
|
end
|
|
|
|
-- EasyMenu is available in 1.12.1
|
|
local menuFrame = CreateFrame("Frame", "Guda_MailboxCharacterMenu", UIParent, "UIDropDownMenuTemplate")
|
|
EasyMenu(menu, menuFrame, "cursor", 0, 0, "MENU")
|
|
end
|