Untitled diff

Created Diff never expires
BulkMailInbox = LibStub("AceAddon-3.0"):NewAddon("BulkMailInbox", "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0", "AceHook-3.0")
BulkMailInbox = LibStub("AceAddon-3.0"):NewAddon("BulkMailInbox", "AceConsole-3.0", "AceEvent-3.0", "AceTimer-3.0", "AceHook-3.0")


local mod, self, BulkMailInbox = BulkMailInbox, BulkMailInbox, BulkMailInbox
local mod, self, BulkMailInbox = BulkMailInbox, BulkMailInbox, BulkMailInbox


local VERSION = "7.0.0"
local VERSION = "7.0.0"
local LibStub = LibStub
local LibStub = LibStub


local L = LibStub("AceLocale-3.0"):GetLocale("BulkMailInbox", false)
local L = LibStub("AceLocale-3.0"):GetLocale("BulkMailInbox", false)


BulkMailInbox.L = L
BulkMailInbox.L = L


local media = LibStub("LibSharedMedia-3.0")
local media = LibStub("LibSharedMedia-3.0")
local abacus = LibStub("LibAbacus-3.0")
local abacus = LibStub("LibAbacus-3.0")
local QTIP = LibStub("LibQTip-1.0")
local QTIP = LibStub("LibQTip-1.0")
local AC = LibStub("AceConfig-3.0")
local AC = LibStub("AceConfig-3.0")
local ACD = LibStub("AceConfigDialog-3.0")
local ACD = LibStub("AceConfigDialog-3.0")
local DB = LibStub("AceDB-3.0")
local DB = LibStub("AceDB-3.0")
local LDB = LibStub("LibDataBroker-1.1", true)
local LDB = LibStub("LibDataBroker-1.1", true)
local LD = LibStub("LibDropdown-1.0")
local LD = LibStub("LibDropdown-1.0")




local _G = _G
local _G = _G
local fmt = string.format
local fmt = string.format
local lower = string.lower
local lower = string.lower


local sortFields, markTable -- tables
local sortFields, markTable -- tables
local ibIndex, ibAttachIndex, numInboxItems, inboxCash, cleanPass, cashOnly, markOnly, takeAllInProgress, invFull, filterText -- variables
local ibIndex, ibAttachIndex, numInboxItems, inboxCash, cleanPass, cashOnly, markOnly, takeAllInProgress, invFull, filterText -- variables
local spinnerText = { "Working ", "Working. ", "Working.. ", "Working..." }
local spinnerText = { "Working ", "Working. ", "Working.. ", "Working..." }
--[[----------------------------------------------------------------------------
--[[----------------------------------------------------------------------------
Table Handling
Table Handling
------------------------------------------------------------------------------]]
------------------------------------------------------------------------------]]
local newHash, del
local newHash, del
do
do
local list = setmetatable({}, {__mode='k'})
local list = setmetatable({}, {__mode='k'})
function newHash(...)
function newHash(...)
local t = next(list)
local t = next(list)
if t then
if t then
list[t] = nil
list[t] = nil
else
else
t = {}
t = {}
end
end
for i = 1, select('#', ...), 2 do
for i = 1, select('#', ...), 2 do
t[select(i, ...)] = select(i+1, ...)
t[select(i, ...)] = select(i+1, ...)
end
end
return t
return t
end
end
function del(t)
function del(t)
for k in pairs(t) do
for k in pairs(t) do
t[k] = nil
t[k] = nil
end
end
list[t] = true
list[t] = true
return nil
return nil
end
end
end
end


--[[----------------------------------------------------------------------------
--[[----------------------------------------------------------------------------
Local Processing
Local Processing
------------------------------------------------------------------------------]]
------------------------------------------------------------------------------]]
-- Build a table with info about all items and money in the Inbox
-- Build a table with info about all items and money in the Inbox
local inboxCache = {}
local inboxCache = {}
local function _sortInboxFunc(a,b)
local function _sortInboxFunc(a,b)
local sf = sortFields[BulkMailInbox.db.char.sortField]
local sf = sortFields[BulkMailInbox.db.char.sortField]
if a and b then
if a and b then
a, b = a[sf], b[sf]
a, b = a[sf], b[sf]
if sf == 'itemLink' then
if sf == 'itemLink' then
a = a and GetItemInfo(a) or a
local rarityA, itemIDAstring, _ = strsplit(":", a, 3)
b = b and GetItemInfo(b) or b
local rarityB, itemIDBstring, _ = strsplit(":", b, 3)
end
if rarityA..":" == ITEM_SOLD_COLON or rarityA == "Cash" then
a = type(a) == "nil" and 0 or type(a) == "boolean" and tostring(a) or a
numberA = 999999999
b = type(b) == "nil" and 0 or type(b) == "boolean" and tostring(b) or b
else
if mod.db.char.sortReversed then
local itemIDA = tonumber(itemIDAstring)
if a > b then return true end
local _, _, rarityANumber = GetItemInfo(itemIDA)
else
numberA = rarityANumber*10000000 + itemIDA
if a < b then return true end
end
end
if rarityB..":" == ITEM_SOLD_COLON or rarityB == "Cash" then
end
numberB = 999999999
else
local itemIDB = tonumber(itemIDBstring)
local _, _, rarityBNumber = GetItemInfo(itemIDB)
numberB = rarityBNumber*10000000 + itemIDB
end
if mod.db.char.sortReversed then
if numberA > numberB then return true end
else
if numberA < numberB then return true end
end
else
a = type(a) == "nil" and 0 or type(a) == "boolean" and tostring(a) or a
b = type(b) == "nil" and 0 or type(b) == "boolean" and tostring(b) or b
if mod.db.char.sortReversed then
if a > b then return true end
else
if a < b then return true end
end
end
end
end
end


-- These are the patterns that indicate that the item was received from the AH
-- These are the patterns that indicate that the item was received from the AH
-- In that case the items are not returnable
-- In that case the items are not returnable
local AHReceivedPatterns = {
local AHReceivedPatterns = {
(gsub(AUCTION_REMOVED_MAIL_SUBJECT, "%%s", ".*")),
(gsub(AUCTION_REMOVED_MAIL_SUBJECT, "%%s", ".*")),
(gsub(AUCTION_EXPIRED_MAIL_SUBJECT, "%%s", ".*")),
(gsub(AUCTION_EXPIRED_MAIL_SUBJECT, "%%s", ".*")),
(gsub(AUCTION_WON_MAIL_SUBJECT, "%%s", ".*"))
(gsub(AUCTION_WON_MAIL_SUBJECT, "%%s", ".*"))
}
}


local function _isAHSentMail(subject)
local function _isAHSentMail(subject)
if subject then
if subject then
for key,pattern in ipairs(AHReceivedPatterns) do
for key,pattern in ipairs(AHReceivedPatterns) do
if subject:find(pattern) ~= nil then
if subject:find(pattern) ~= nil then
return true
return true
end
end
end
end
end
end
end
end


local function _matchesFilter(text)
local function _matchesFilter(text)
if not filterText or filterText:len() == 0 then
if not filterText or filterText:len() == 0 then
return true
return true
end
end
return text:lower():find(filterText, 1, true) ~= nil
return text:lower():find(filterText, 1, true) ~= nil
end
end


local function inboxCacheBuild()
local function inboxCacheBuild()
local start = GetTime()
local start = GetTime()
for k in ipairs(inboxCache) do inboxCache[k] = del(inboxCache[k]) end
for k in ipairs(inboxCache) do inboxCache[k] = del(inboxCache[k]) end
inboxCash, numInboxItems = 0, 0
inboxCash, numInboxItems = 0, 0
for i = 1, GetInboxNumItems() do
for i = 1, GetInboxNumItems() do
local _, _, sender, subject, money, cod, daysLeft, numItems, _, wasReturned, _, canReply, isGM = GetInboxHeaderInfo(i)
local _, _, sender, subject, money, cod, daysLeft, numItems, _, wasReturned, _, canReply, isGM = GetInboxHeaderInfo(i)
if money > 0 then
if money > 0 then
local _, itemName = GetInboxInvoiceInfo(i)
local _, itemName = GetInboxInvoiceInfo(i)
local title = itemName and ITEM_SOLD_COLON..' '..itemName or L["Cash"]
local title = itemName and ITEM_SOLD_COLON..' '..itemName or L["Cash"]
if _matchesFilter(title) then
if _matchesFilter(title) then
-- Contributed by Scott Centoni
-- Contributed by Scott Centoni
table.insert(inboxCache, newHash(
table.insert(inboxCache, newHash(
'index', i, 'sender', sender, 'bmid', daysLeft..subject..0, 'returnable', not wasReturned, 'cod', cod,
'index', i, 'sender', sender, 'bmid', daysLeft..subject..0, 'returnable', not wasReturned, 'cod', cod,
'daysLeft', daysLeft, 'itemLink', title, 'money', money, 'texture', "Interface\\Icons\\INV_Misc_Coin_01"
'daysLeft', daysLeft, 'itemLink', title, 'money', money, 'texture', "Interface\\Icons\\INV_Misc_Coin_01"
))
))
inboxCash = inboxCash + money
inboxCash = inboxCash + money
end
end
end
end
if numItems then
if numItems then
local canReturnItem = not wasReturned
local canReturnItem = not wasReturned
if isGM or not canReply or _isAHSentMail(subject) then
if isGM or not canReply or _isAHSentMail(subject) then
canReturnItem = false
canReturnItem = false
end
end
for j=1, ATTACHMENTS_MAX_SEND do
for j=1, ATTACHMENTS_MAX_SEND do
if GetInboxItem(i,j) and _matchesFilter(GetInboxItem(i, j)) then
if GetInboxItem(i,j) and _matchesFilter(GetInboxItem(i, j)) then
table.insert(inboxCache, newHash(
table.insert(inboxCache, newHash(
'index', i, 'attachment', j, 'sender', sender, 'bmid', daysLeft..subject..j, 'returnable', canReturnItem, 'cod', cod,
'index', i, 'attachment', j, 'sender', sender, 'bmid', daysLeft..subject..j, 'returnable', canReturnItem, 'cod', cod,
'daysLeft', daysLeft, 'itemLink', GetInboxItemLink(i,j), 'qty', select(4, GetInboxItem(i,j)), 'texture', (select(3, GetInboxItem(i,j)))
'daysLeft', daysLeft, 'itemLink', GetInboxItemLink(i,j), 'qty', select(4, GetInboxItem(i,j)), 'texture', (select(3, GetInboxItem(i,j)))
))
))
numInboxItems = numInboxItems + 1
numInboxItems = numInboxItems + 1
end
end
end
end
end
end
end
end
table.sort(inboxCache, _sortInboxFunc)
table.sort(inboxCache, _sortInboxFunc)
end
end


local function takeAll(cash, mark)
local function takeAll(cash, mark)
-- Ace3 timers only allow one arg so support that hack
-- Ace3 timers only allow one arg so support that hack
if type(cash) == "table" then
if type(cash) == "table" then
mark = cash.markOnly
mark = cash.markOnly
cash = cash.cashOnly
cash = cash.cashOnly
end
end
cashOnly = cash
cashOnly = cash
markOnly = mark
markOnly = mark
ibIndex = GetInboxNumItems()
ibIndex = GetInboxNumItems()
ibAttachIndex = 0
ibAttachIndex = 0
takeAllInProgress = true
takeAllInProgress = true
inboxCacheBuild()
inboxCacheBuild()
mod:TakeNextItemFromMailbox()
mod:TakeNextItemFromMailbox()
end
end


--[[----------------------------------------------------------------------------
--[[----------------------------------------------------------------------------
Setup
Setup
------------------------------------------------------------------------------]]
------------------------------------------------------------------------------]]
local function color(text, color)
local function color(text, color)
return fmt("|cff%s%s|r", color, text or "")
return fmt("|cff%s%s|r", color, text or "")
end
end


function mod:OnInitialize()
function mod:OnInitialize()
if not BulkMail3InboxDB and BulkMail2InboxDB and BulkMail2InboxDB.chars then
if not BulkMail3InboxDB and BulkMail2InboxDB and BulkMail2InboxDB.chars then
BulkMail3InboxDB = { char = {} }
BulkMail3InboxDB = { char = {} }
for charname, data in pairs(BulkMail2InboxDB) do
for charname, data in pairs(BulkMail2InboxDB) do
BulkMail3InboxDB.char[charname] = data
BulkMail3InboxDB.char[charname] = data
end
end
end
end
self.db = DB:New("BulkMail3InboxDB", {
self.db = DB:New("BulkMail3InboxDB", {
char = {
char = {
altDel = false,
altDel = false,
ctrlRet = true,
ctrlRet = true,
shiftTake = true,
shiftTake = true,
takeAll = true,
takeAll = true,
inboxUI = true,
inboxUI = true,
takeStackable = true,
takeStackable = true,
sortField = 1,
sortField = 1,
},
},
profile = {
profile = {
disableTooltips = false,
disableTooltips = false,
scale = 1.0,
scale = 1.0,
font = "Friz Quadrata TT",
font = "Friz Quadrata TT",
fontSize = 12
fontSize = 12
}
}
}, "Default")
}, "Default")
sortFields = { 'itemLink', 'qty', 'returnable', 'sender', 'daysLeft', 'index' }
sortFields = { 'itemLink', 'qty', 'returnable', 'sender', 'daysLeft', 'index' }
markTable = {}
markTable = {}
inboxCash = 0
inboxCash = 0
invFull = false
invFull = false


self.opts = {
self.opts = {
type = 'group',
type = 'group',
args = {
args = {
altdel = {
altdel = {
name = L["Alt-click Delete"], type = 'toggle',
name = L["Alt-click Delete"], type = 'toggle',
desc = L["Enable Alt-Click on inbox items to delete the mail in which they are contained."],
desc = L["Enable Alt-Click on inbox items to delete the mail in which they are contained."],
get = function() return self.db.char.altDel end,
get = function() return self.db.char.altDel end,
set = function(args,v) self.db.char.altDel = v end,
set = function(args,v) self.db.char.altDel = v end,
},
},
ctrlret = {
ctrlret = {
name = L["Ctrl-click Return"], type = 'toggle',
name = L["Ctrl-click Return"], type = 'toggle',
desc = L["Enable Ctrl-click on inbox items to return the mail in which they are contained."],
desc = L["Enable Ctrl-click on inbox items to return the mail in which they are contained."],
get = function() return self.db.char.ctrlRet end,
get = function() return self.db.char.ctrlRet end,
set = function(args,v) self.db.char.ctrlRet = v end,
set = function(args,v) self.db.char.ctrlRet = v end,
},
},
shifttake = {
shifttake = {
name = L["Shift-click Take"], type = 'toggle',
name = L["Shift-click Take"], type = 'toggle',
desc = L["Enable Shift-click on inbox items to take them."],
desc = L["Enable Shift-click on inbox items to take them."],
get = function() return self.db.char.shiftTake end,
get = function() return self.db.char.shiftTake end,
set = function(args,v) self.db.char.shiftTake = v end,
set = function(args,v) self.db.char.shiftTake = v end,
},
},
takeall = {
takeall = {
name = L["Take All"], type = 'toggle',
name = L["Take All"], type = 'toggle',
desc = L["Enable 'Take All' button in inbox."],
desc = L["Enable 'Take All' button in inbox."],
get = function() return self.db.char.takeAll end,
get = function() return self.db.char.takeAll end,
set = function(args,v) self.db.char.takeAll = v self:UpdateTakeAllButton() end,
set = function(args,v) self.db.char.takeAll = v self:UpdateTakeAllButton() end,
},
},
gui = {
gui = {
name = L["Show Inbox GUI"], type = 'toggle',
name = L["Show Inbox GUI"], type = 'toggle',
desc = L["Show the Inbox Items GUI"],
desc = L["Show the Inbox Items GUI"],
get = function() return self.db.char.inboxUI end,
get = function() return self.db.char.inboxUI end,
set = function(args,v) self.db.char.inboxUI = v self:RefreshInboxGUI() end,
set = function(args,v) self.db.char.inboxUI = v self:RefreshInboxGUI() end,
},
},
takeStackable = {
takeStackable = {
name = L["Always Take Stackable Items"], type = 'toggle',
name = L["Always Take Stackable Items"], type = 'toggle',
desc = L["Continue taking partial stacks of stackable items even if the mailbox is full."],
desc = L["Continue taking partial stacks of stackable items even if the mailbox is full."],
get = function() return self.db.char.takeStackable end,
get = function() return self.db.char.takeStackable end,
set = function(args,v) self.db.char.takeStackable = v end,
set = function(args,v) self.db.char.takeStackable = v end,
},
},
disableTooltips = {
disableTooltips = {
name = L["Disable Tooltips"], type = 'toggle',
name = L["Disable Tooltips"], type = 'toggle',
desc = L["Disable the help tooltips for the toolbar buttons."],
desc = L["Disable the help tooltips for the toolbar buttons."],
get = function() return self.db.profile.disableTooltips end,
get = function() return self.db.profile.disableTooltips end,
set = function(args,v) self.db.profile.disableTooltips = v end,
set = function(args,v) self.db.profile.disableTooltips = v end,
},
},
scale = {
scale = {
type = "range",
type = "range",
name = L["GUI Scale"],
name = L["GUI Scale"],
desc = L["Set the window scale of the Inbox GUI."],
desc = L["Set the window scale of the Inbox GUI."],
min = 0.3, max = 3.0, step = 0.1,
min = 0.3, max = 3.0, step = 0.1,
set = function(_,val) mod.db.profile.scale = val mod:RefreshInboxGUI(true) end,
set = function(_,val) mod.db.profile.scale = val mod:RefreshInboxGUI(true) end,
get = function() return mod.db.profile.scale end,
get = function() return mod.db.profile.scale end,
order = 500,
order = 500,
},
},
font = {
font = {
type = "select",
type = "select",
dialogControl = "LSM30_Font",
dialogControl = "LSM30_Font",
name = L["Font"],
name = L["Font"],
desc = L["Font used in the inbox list"],
desc = L["Font used in the inbox list"],
values = AceGUIWidgetLSMlists.font,
values = AceGUIWidgetLSMlists.font,
set = function(_,key) mod.db.profile.font = key mod:RefreshInboxGUI() end,
set = function(_,key) mod.db.profile.font = key mod:RefreshInboxGUI() end,
get = function() return mod.db.profile.font end,
get = function() return mod.db.profile.font end,
order = 1000,
order = 1000,
},
},
fontsize = {
fontsize = {
type = "range",
type = "range",
name = L["Font size"],
name = L["Font size"],
min = 6, max = 30, step = 1,
min = 6, max = 30, step = 1,
set = function(_,val) mod.db.profile.fontSize = val mod:RefreshInboxGUI() end,
set = function(_,val) mod.db.profile.fontSize = val mod:RefreshInboxGUI() end,
get = function() return mod.db.profile.fontSize end,
get = function() return mod.db.profile.fontSize end,
order = 2000,
order = 2000,
},
},


},
},
}
}


-- set up LDB, but only if the user doesn't have Bulk Mail already
-- set up LDB, but only if the user doesn't have Bulk Mail already
if LDB and not BulkMail then
if LDB and not BulkMail then
self.ldb =
self.ldb =
LDB:NewDataObject("BulkMailInbox",
LDB:NewDataObject("BulkMailInbox",
{
{
type = "data source",
type = "data source",
label = L["Bulk Mail Inbox"]..VERSION,
label = L["Bulk Mail Inbox"]..VERSION,
icon = [[Interface\Addons\BulkMail2Inbox\icon]],
icon = [[Interface\Addons\BulkMail2Inbox\icon]],
tooltiptext = color(L["Bulk Mail Inbox"]..VERSION.."\n\n", "ffff00")..color(L["Hint:"].." "..L["Left click to open the config panel."].."\n"..
tooltiptext = color(L["Bulk Mail Inbox"]..VERSION.."\n\n", "ffff00")..color(L["Hint:"].." "..L["Left click to open the config panel."].."\n"..
L["Right click to open the config menu."], "ffd200"),
L["Right click to open the config menu."], "ffd200"),
OnClick = function(clickedframe, button)
OnClick = function(clickedframe, button)
if button == "RightButton" then
if button == "RightButton" then
mod:OpenConfigMenu(clickedframe)
mod:OpenConfigMenu(clickedframe)
else
else
mod:ToggleConfigDialog()
mod:ToggleConfigDialog()
end
end
end,
end,
})
})
end
end


self._mainConfig = self:OptReg(L["Bulk Mail Inbox"], self.opts, { "bmi", "bulkmailinbox" })
self._mainConfig = self:OptReg(L["Bulk Mail Inbox"], self.opts, { "bmi", "bulkmailinbox" })


if BulkMail then
if BulkMail then
BulkMail.opts.args.inbox = { type = "group",
BulkMail.opts.args.inbox = { type = "group",
handler = mod,
handler = mod,
name = L["Inbox"],
name = L["Inbox"],
desc = L["Bulk Mail Inbox Options"],
desc = L["Bulk Mail Inbox Options"],
args = BulkMailInbox.opts.args
args = BulkMailInbox.opts.args
}
}
end
end
end
end


function mod:OnEnable()
function mod:OnEnable()
self:UpdateTakeAllButton()
self:UpdateTakeAllButton()
self:RegisterEvent('MAIL_SHOW')
self:RegisterEvent('MAIL_SHOW')
self:RegisterEvent('MAIL_CLOSED')
self:RegisterEvent('MAIL_CLOSED')
self:RegisterEvent('PLAYER_ENTERING_WORLD')
self:RegisterEvent('PLAYER_ENTERING_WORLD')
self:RegisterEvent('UI_ERROR_MESSAGE')
self:RegisterEvent('UI_ERROR_MESSAGE')
self:RegisterEvent('MAIL_INBOX_UPDATE')
self:RegisterEvent('MAIL_INBOX_UPDATE')


-- Handle being LoD loaded while at the mailbox
-- Handle being LoD loaded while at the mailbox
if MailFrame:IsVisible() then
if MailFrame:IsVisible() then
self:MAIL_SHOW()
self:MAIL_SHOW()
end
end
end
end


function mod:OnDisable()
function mod:OnDisable()
self:UnregisterAllEvents()
self:UnregisterAllEvents()
end
end


------------------------------------------------------------------------------
------------------------------------------------------------------------------
-- Events
-- Events
------------------------------------------------------------------------------
------------------------------------------------------------------------------
function mod:MAIL_SHOW()
function mod:MAIL_SHOW()
ibIndex = GetInboxNumItems()
ibIndex = GetInboxNumItems()


if not self:IsHooked('CheckInbox') then
if not self:IsHooked('CheckInbox') then
self:SecureHook('CheckInbox', 'RefreshInboxGUI')
self:SecureHook('CheckInbox', 'RefreshInboxGUI')
self:SecureHook(GameTooltip, 'SetInboxItem')
self:SecureHook(GameTooltip, 'SetInboxItem')
self:Hook('InboxFrame_OnClick', nil, true)
self:Hook('InboxFrame_OnClick', nil, true)
self:SecureHookScript(MailFrameTab1, 'OnClick', 'ShowInboxGUI')
self:SecureHookScript(MailFrameTab1, 'OnClick', 'ShowInboxGUI')
self:SecureHookScript(MailFrameTab2, 'OnClick', 'HideInboxGUI')
self:SecureHookScript(MailFrameTab2, 'OnClick', 'HideInboxGUI')
end
end


self:ShowInboxGUI()
self:ShowInboxGUI()
end
end


function mod:MAIL_CLOSED()
function mod:MAIL_CLOSED()
takeAllInProgress = false
takeAllInProgress = false
self:HideInboxGUI()
self:HideInboxGUI()
GameTooltip:Hide()
GameTooltip:Hide()
self:UnhookAll()
self:UnhookAll()
end
end


BulkMailInbox.PLAYER_ENTERING_WORLD = BulkMailInbox.MAIL_CLOSED -- MAIL_CLOSED doesn't get called if, for example, the player accepts a port with the mail window open
BulkMailInbox.PLAYER_ENTERING_WORLD = BulkMailInbox.MAIL_CLOSED -- MAIL_CLOSED doesn't get called if, for example, the player accepts a port with the mail window open


function mod:UI_ERROR_MESSAGE(event, msg) -- prevent infinite loop when inventory is full
function mod:UI_ERROR_MESSAGE(event, n, msg) -- prevent infinite loop when inventory is full
if msg == ERR_INV_FULL then
if msg == ERR_INV_FULL then
invFull = true
invFull = true
end
end
end
end


-- Take next inbox item or money skip past CoD items and letters.
-- Take next inbox item or money skip past CoD items and letters.
local prevSubject = ''
local prevSubject = ''


function mod:SmartCancelTimer(name)
function mod:SmartCancelTimer(name)
mod.timers = mod.timers or {}
mod.timers = mod.timers or {}
if mod.timers[name] then
if mod.timers[name] then
mod:CancelTimer(mod.timers[name], true)
mod:CancelTimer(mod.timers[name], true)
mod.timers[name] = nil
mod.timers[name] = nil
end
end
end
end


function mod:SmartScheduleTimer(name, override, method, timeout, ...)
function mod:SmartScheduleTimer(name, override, method, timeout, ...)
mod.timers = mod.timers or {}
mod.timers = mod.timers or {}
if mod.timers[name] and override then
if mod.timers[name] and override then
mod:CancelTimer(mod.timers[name], true)
mod:CancelTimer(mod.timers[name], true)
mod.timers[name] = nil
mod.timers[name] = nil
end
end
if not mod.timers[name] then
if not mod.timers[name] then
mod.timers[name] = mod:ScheduleTimer(method, timeout, ...)
mod.timers[name] = mod:ScheduleTimer(method, timeout, ...)
end
end
end
end


function mod:MAIL_INBOX_UPDATE()
function mod:MAIL_INBOX_UPDATE()
if not takeAllInProgress and not self.refreshInboxTimer then
if not takeAllInProgress and not self.refreshInboxTimer then
mod:SmartScheduleTimer('BMI_RefreshInboxGUI', false, "RefreshInboxGUI", .5)
mod:SmartScheduleTimer('BMI_RefreshInboxGUI', false, "RefreshInboxGUI", .5)
end
end
end
end


local _fetchCount = 0
local _fetchCount = 0
local _lastCount = -1
local _lastCount = -1
local function _updateSpinner()
local function _updateSpinner()
local spinner = mod._toolbar and mod._toolbar.spinner
local spinner = mod._toolbar and mod._toolbar.spinner
if not spinner or (takeAllInProgress and _fetchCount == _lastCount) then return end
if not spinner or (takeAllInProgress and _fetchCount == _lastCount) then return end
_lastCount = _fetchCount
_lastCount = _fetchCount
local isVisible = mod.buttons.Cancel:IsVisible()
local isVisible = mod.buttons.Cancel:IsVisible()
if takeAllInProgress then
if takeAllInProgress then
spinner:SetText(spinnerText[1+math.fmod(_fetchCount, #spinnerText)]);
spinner:SetText(spinnerText[1+math.fmod(_fetchCount, #spinnerText)]);
if not isVisible then
if not isVisible then
mod.buttons.Cancel:Show()
mod.buttons.Cancel:Show()
end
end
elseif isVisible then
elseif isVisible then
mod.buttons.Cancel:Hide()
mod.buttons.Cancel:Hide()
spinner:SetText("")
spinner:SetText("")
end
end
end
end


function mod:TakeNextItemFromMailbox()
function mod:TakeNextItemFromMailbox()
_updateSpinner()
_updateSpinner()
if not takeAllInProgress then
if not takeAllInProgress then
return
return
end
end


local numMails = GetInboxNumItems()
local numMails = GetInboxNumItems()
cashOnly = cashOnly or (invFull and not mod.db.char.takeStackable)
cashOnly = cashOnly or (invFull and not mod.db.char.takeStackable)


if ibIndex <= 0 then
if ibIndex <= 0 then
if cleanPass or numMails <= 0 then
if cleanPass or numMails <= 0 then
takeAllInProgress = false
takeAllInProgress = false
invFull = false
invFull = false
return self:RefreshInboxGUI()
return self:RefreshInboxGUI()
else
else
ibIndex = numMails
ibIndex = numMails
ibAttachIndex = 0
ibAttachIndex = 0
cleanPass = true
cleanPass = true
return self:SmartScheduleTimer('BMI_takeAll', true, takeAll, .1, { cashOnly = cashOnly, markOnly = markOnly })
return self:SmartScheduleTimer('BMI_takeAll', true, takeAll, .1, { cashOnly = cashOnly, markOnly = markOnly })
end
end
end
end
local curIndex, curAttachIndex = ibIndex, ibAttachIndex
local curIndex, curAttachIndex = ibIndex, ibAttachIndex
local sender, subject, money, cod, daysLeft, item, _, _, text, _, isGM = select(3, GetInboxHeaderInfo(curIndex))
local sender, subject, money, cod, daysLeft, item, _, _, text, _, isGM = select(3, GetInboxHeaderInfo(curIndex))


if subject then
if subject then
prevSubject = subject
prevSubject = subject
else
else
subject = prevSubject
subject = prevSubject
end
end


if curAttachIndex == ATTACHMENTS_MAX_SEND then
if curAttachIndex == ATTACHMENTS_MAX_SEND then
ibIndex = ibIndex - 1
ibIndex = ibIndex - 1
ibAttachIndex = 0
ibAttachIndex = 0
else
else
ibAttachIndex = ibAttachIndex + 1
ibAttachIndex = ibAttachIndex + 1
end
end
local itemName, _, _, itemCount = GetInboxItem(curIndex, curAttachIndex)
local itemName, _, _, itemCount = GetInboxItem(curIndex, curAttachIndex)
local markKey = daysLeft..subject..curAttachIndex
local markKey = daysLeft..subject..curAttachIndex


if (sender == "The Postmaster" or sender == "Thaumaturge Vashreen") and not itemName and money == 0 and not item then
if (sender == "The Postmaster" or sender == "Thaumaturge Vashreen") and not itemName and money == 0 and not item then
DeleteInboxItem(curIndex)
DeleteInboxItem(curIndex)
self:SmartScheduleTimer('BMI_RefreshInboxGUI', false, "RefreshInboxGUI", 1)
self:SmartScheduleTimer('BMI_RefreshInboxGUI', false, "RefreshInboxGUI", 1)
self:SmartScheduleTimer('BMI_TakeNextItem', true, "TakeNextItemFromMailbox", 0.4)
self:SmartScheduleTimer('BMI_TakeNextItem', true, "TakeNextItemFromMailbox", 0.4)
return
return
end
end


if curAttachIndex > 0 and not itemName or markOnly and not markTable[markKey] or itemName and not _matchesFilter(itemName)
if curAttachIndex > 0 and not itemName or markOnly and not markTable[markKey] or itemName and not _matchesFilter(itemName)
then
then
return self:TakeNextItemFromMailbox()
return self:TakeNextItemFromMailbox()
end
end
local actionTaken
local actionTaken
if not string.find(subject, "Sale Pending") then
if not string.find(subject, "Sale Pending") then
if curAttachIndex == 0 and money > 0 then
if curAttachIndex == 0 and money > 0 then
local _, itemName = GetInboxInvoiceInfo(curIndex)
local _, itemName = GetInboxInvoiceInfo(curIndex)
local title = itemName and ITEM_SOLD_COLON..' '..itemName or L["Cash"]
local title = itemName and ITEM_SOLD_COLON..' '..itemName or L["Cash"]
if _matchesFilter(title) then
if _matchesFilter(title) then
cleanPass = false
cleanPass = false
actionTaken = true
actionTaken = true
TakeInboxMoney(curIndex)
TakeInboxMoney(curIndex)
end
end
elseif not cashOnly and cod == 0 then
elseif not cashOnly and cod == 0 then
cleanPass = invFull -- this ensures we'll die properly after a full mailbox iteration
cleanPass = invFull -- this ensures we'll die properly after a full mailbox iteration
local inboxitem = GetInboxItemLink(curIndex,curAttachIndex)
local inboxitem = GetInboxItemLink(curIndex,curAttachIndex)
if inboxitem and
if inboxitem and
(not invFull or -- inventory not full
(not invFull or -- inventory not full
(mod.db.char.takeStackable and -- or continue taking stackable items even if full
(mod.db.char.takeStackable and -- or continue taking stackable items even if full
itemCount < select(8, GetItemInfo(inboxitem)))) then
itemCount < select(8, GetItemInfo(inboxitem)))) then
TakeInboxItem(curIndex, curAttachIndex)
TakeInboxItem(curIndex, curAttachIndex)
markTable[markKey] = nil
markTable[markKey] = nil
actionTaken = true
actionTaken = true
end
end
end
end
end
end


if actionTaken then
if actionTaken then
-- Since we did something, we'll add a delay to prevent erroring out
-- Since we did something, we'll add a delay to prevent erroring out
self:SmartScheduleTimer('BMI_RefreshInboxGUI', false, "RefreshInboxGUI", 1)
self:SmartScheduleTimer('BMI_RefreshInboxGUI', false, "RefreshInboxGUI", 1)
self:SmartScheduleTimer('BMI_TakeNextItem', true, "TakeNextItemFromMailbox", 0.4)
self:SmartScheduleTimer('BMI_TakeNextItem', true, "TakeNextItemFromMailbox", 0.4)
_fetchCount = _fetchCount + 1
_fetchCount = _fetchCount + 1
else
else
-- We didn't take any items so let's move on
-- We didn't take any items so let's move on
self:TakeNextItemFromMailbox()
self:TakeNextItemFromMailbox()
end
end
end
end


--[[----------------------------------------------------------------------------
--[[----------------------------------------------------------------------------
Hooks
Hooks
------------------------------------------------------------------------------]]
------------------------------------------------------------------------------]]
function mod:SetInboxItem(tooltip, index, attachment, ...)
function mod:SetInboxItem(tooltip, index, attachment, ...)
if takeAllInProgress then return end
if takeAllInProgress then return end
local money, _, _, _, _, wasReturned, _, canReply = select(5, GetInboxHeaderInfo(index))
local money, _, _, _, _, wasReturned, _, canReply = select(5, GetInboxHeaderInfo(index))
if self.db.char.shiftTake then tooltip:AddLine(L["Shift - Take Item"]) end
if self.db.char.shiftTake then tooltip:AddLine(L["Shift - Take Item"]) end
if wasReturned then
if wasReturned then
if self.db.char.altDel then
if self.db.char.altDel then
tooltip:AddLine(L["Alt - Delete Containing Mail"])
tooltip:AddLine(L["Alt - Delete Containing Mail"])
end
end
elseif canReply and self.db.char.ctrlRet then
elseif canReply and self.db.char.ctrlRet then
tooltip:AddLine(L["Ctrl - Return Containing Mail"])
tooltip:AddLine(L["Ctrl - Return Containing Mail"])
end
end
end
end


function mod:InboxFrame_OnClick(parentself, index, attachment, ...)
function mod:InboxFrame_OnClick(parentself, index, attachment, ...)
takeAllInProgress = false
takeAllInProgress = false
local _, _, _, _, money, cod, _, hasItem, _, wasReturned, _, canReply = GetInboxHeaderInfo(index)
local _, _, _, _, money, cod, _, hasItem, _, wasReturned, _, canReply = GetInboxHeaderInfo(index)
if self.db.char.shiftTake and IsShiftKeyDown() then
if self.db.char.shiftTake and IsShiftKeyDown() then
if money > 0 then TakeInboxMoney(index)
if money > 0 then TakeInboxMoney(index)
elseif cod > 0 then return
elseif cod > 0 then return
elseif hasItem then TakeInboxItem(index, attachment) end
elseif hasItem then TakeInboxItem(index, attachment) end
elseif self.db.char.ctrlRet and IsControlKeyDown() and not wasReturned and canReply then ReturnInboxItem(index)
elseif self.db.char.ctrlRet and IsControlKeyDown() and not wasReturned and canReply then ReturnInboxItem(index)
elseif self.db.char.altDel and IsAltKeyDown() and wasReturned then DeleteInboxItem(index)
elseif self.db.char.altDel and IsAltKeyDown() and wasReturned then DeleteInboxItem(index)
elseif parentself and parentself:GetObjectType() == 'CheckButton' then self.hooks.InboxFrame_OnClick(parentself, index, ...) end
elseif parentself and parentself:GetObjectType() == 'CheckButton' then self.hooks.InboxFrame_OnClick(parentself, index, ...) end
mod:SmartScheduleTimer("BMI_RefreshInboxGUI", true, "RefreshInboxGUI", 0.1)
mod:SmartScheduleTimer("BMI_RefreshInboxGUI", true, "RefreshInboxGUI", 0.1)
end
end


--[[----------------------------------------------------------------------------
--[[----------------------------------------------------------------------------
Inbox GUI
Inbox GUI
------------------------------------------------------------------------------]]
------------------------------------------------------------------------------]]
-- Update/Create the Take All button
-- Update/Create the Take All button
function mod:UpdateTakeAllButton()
function mod:UpdateTakeAllButton()
if self.db.char.takeAll then
if self.db.char.takeAll then
if _G.BMI_TakeAllButton then return end
if _G.BMI_TakeAllButton then return end
local bmiTakeAllButton = CreateFrame("Button", "BMI_TakeAllButton", InboxFrame, "UIPanelButtonTemplate")
local bmiTakeAllButton = CreateFrame("Button", "BMI_TakeAllButton", InboxFrame, "UIPanelButtonTemplate")
bmiTakeAllButton:SetWidth(120)
bmiTakeAllButton:SetWidth(120)
bmiTakeAllButton:SetHeight(25)
bmiTakeAllButton:SetHeight(25)
bmiTakeAllButton:SetPoint("CENTER", InboxFrame, "TOP", -15, -410)
bmiTakeAllButton:SetPoint("CENTER", InboxFrame, "TOP", -15, -410)
bmiTakeAllButton:SetText(L["Take All"])
bmiTakeAllButton:SetText(L["Take All"])
bmiTakeAllButton:SetScript("OnClick", function() takeAll() end)
bmiTakeAllButton:SetScript("OnClick", function() takeAll() end)
else
else
if _G.BMI_TakeAllButton then _G.BMI_TakeAllButton:Hide() end
if _G.BMI_TakeAllButton then _G.BMI_TakeAllButton:Hide() end
_G.BMI_TakeAllButton = nil
_G.BMI_TakeAllButton = nil
end
end
end
end


-- Inbox Items Tablet
-- Inbox Items Tablet
local function highlightSameMailItems(index, ...)
local function highlightSameMailItems(index, ...)
if self.db.char.altDel and IsAltKeyDown() or self.db.char.ctrlRet and IsControlKeyDown() then
if self.db.char.altDel and IsAltKeyDown() or self.db.char.ctrlRet and IsControlKeyDown() then
for i = 1, select('#', ...) do
for i = 1, select('#', ...) do
local row = select(i, ...)
local row = select(i, ...)
if row.col6 and row.col6:GetText() == index then
if row.col6 and row.col6:GetText() == index then
row.highlight:Show()
row.highlight:Show()
end
end
end
end
end
end
end
end


local function unhighlightSameMailItems(index, ...)
local function unhighlightSameMailItems(index, ...)
for i = 1, select('#', ...) do
for i = 1, select('#', ...) do
local row = select(i, ...)
local row = select(i, ...)
if row.col6 and row.col6:GetText() == index then
if row.col6 and row.col6:GetText() == index then
row.highlight:Hide()
row.highlight:Hide()
end
end
end
end
end
end


--[[----------------------------------------------------------------------------
--[[----------------------------------------------------------------------------
QTip GUI
QTip GUI
------------------------------------------------------------------------------]]
------------------------------------------------------------------------------]]
-- For pagination
-- For pagination
local MAX_ROWS = 100
local MAX_ROWS = 100
local startPage = 0
local startPage = 0


local function _closeHelpTooltip(parentFrame)
local function _closeHelpTooltip(parentFrame)
if mod.helpTooltip and mod.helpTooltip.owner == parentFrame then
if mod.helpTooltip and mod.helpTooltip.owner == parentFrame then
mod.helpTooltip.owner = nil
mod.helpTooltip.owner = nil
QTIP:Release(mod.helpTooltip)
QTIP:Release(mod.helpTooltip)
mod.helpTooltip = nil
mod.helpTooltip = nil
end
end
end
end


local function _openHelpTooltip(parentFrame, header, text)
local function _openHelpTooltip(parentFrame, header, text)
if self.db.profile.disableTooltips then return end
if self.db.profile.disableTooltips then return end
local tooltip = mod.helpTooltip or QTIP:Acquire("BulkMailInboxHelpTooltip")
local tooltip = mod.helpTooltip or QTIP:Acquire("BulkMailInboxHelpTooltip")
mod.helpTooltip = tooltip
mod.helpTooltip = tooltip
tooltip:Clear()
tooltip:Clear()


tooltip.owner = parentFrame
tooltip.owner = parentFrame
tooltip:SetColumnLayout(1, "LEFT")
tooltip:SetColumnLayout(1, "LEFT")
tooltip:AddHeader(header)
tooltip:AddHeader(header)
tooltip:AddLine(color(text, "ffd200"))
tooltip:AddLine(color(text, "ffd200"))
tooltip:SmartAnchorTo(parentFrame)
tooltip:SmartAnchorTo(parentFrame)
tooltip:SetClampedToScreen(true)
tooltip:SetClampedToScreen(true)
tooltip:Show()
tooltip:Show()
end
end


local function _addTooltipToFrame(frame, header, text)
local function _addTooltipToFrame(frame, header, text)
frame:SetScript("OnEnter", function(self) _openHelpTooltip(self, header, text) end)
frame:SetScript("OnEnter", function(self) _openHelpTooltip(self, header, text) end)
frame:SetScript("OnLeave", _closeHelpTooltip)
frame:SetScript("OnLeave", _closeHelpTooltip)
end
end




local function _addIndentedCell(tooltip, text, indentation, func, arg)
local function _addIndentedCell(tooltip, text, indentation, func, arg)
local y, x = tooltip:AddLine()
local y, x = tooltip:AddLine()
tooltip:SetCell(y, x, text, tooltip:GetFont(), "LEFT", 1, nil, indentation)
tooltip:SetCell(y, x, text, tooltip:GetFont(), "LEFT", 1, nil, indentation)
if func then
if func then
tooltip:SetLineScript(y, "OnMouseUp", func, arg)
tooltip:SetLineScript(y, "OnMouseUp", func, arg)
end
end
return y, x
return y, x
end
end


local function _addColspanCell(tooltip, text, colspan, func, arg, y)
local function _addColspanCell(tooltip, text, colspan, func, arg, y)
y = y or tooltip:AddLine()
y = y or tooltip:AddLine()
tooltip:SetCell(y, 1, text, tooltip:GetFont(), "LEFT", colspan)
tooltip:SetCell(y, 1, text, tooltip:GetFont(), "LEFT", colspan)
if func then
if func then
tooltip:SetLineScript(y, "OnMouseUp", func, true)
tooltip:SetLineScript(y, "OnMouseUp", func, true)
else
else
tooltip:SetLineScript(y, "OnMouseUp", nil)
tooltip:SetLineScript(y, "OnMouseUp", nil)
end
end
return y
return y
end
end


function mod:HideInboxGUI()
function mod:HideInboxGUI()
mod:SmartCancelTimer('BMI_takeAll')
mod:SmartCancelTimer('BMI_takeAll')
mod:SmartCancelTimer('BMI_TakeNextItem')
mod:SmartCancelTimer('BMI_TakeNextItem')
mod:SmartCancelTimer('BMI_RefreshInboxGUI')
mod:SmartCancelTimer('BMI_RefreshInboxGUI')
if mod._toolbar then
if mod._toolbar then
mod._toolbar:Hide()
mod._toolbar:Hide()
mod._toolbar:SetParent(nil)
mod._toolbar:SetParent(nil)
end
end


local tooltip = mod.inboxGUI
local tooltip = mod.inboxGUI
if tooltip then
if tooltip then
mod.inboxGUI = nil
mod.inboxGUI = nil
tooltip:EnableMouse(false)
tooltip:EnableMouse(false)
tooltip:SetScript("OnDragStart", nil)
tooltip:SetScript("OnDragStart", nil)
tooltip:SetScript("OnDragStop", nil)
tooltip:SetScript("OnDragStop", nil)
tooltip:SetMovable(false)
tooltip:SetMovable(false)
tooltip:RegisterForDrag()
tooltip:RegisterForDrag()
tooltip:SetFrameStrata("TOOLTIP")
tooltip:SetFrameStrata("TOOLTIP")
tooltip.moved = nil
tooltip.moved = nil
tooltip:SetScale(GameTooltip:GetScale())
tooltip:SetScale(GameTooltip:GetScale())
QTIP:Release(tooltip)
QTIP:Release(tooltip)
end
end
mod._wantGui = nil
mod._wantGui = nil
end
end


function mod:RefreshInboxGUI(resetMoved)
function mod:RefreshInboxGUI(resetMoved)
_updateSpinner()
_updateSpinner()
mod:SmartCancelTimer('BMI_RefreshInboxGUI')
mod:SmartCancelTimer('BMI_RefreshInboxGUI')
if not mod.db.char.inboxUI then return end
if not mod.db.char.inboxUI then return end
inboxCacheBuild()
inboxCacheBuild()
if mod.inboxGUI then
if mod.inboxGUI then
if resetMoved then
if resetMoved then
mod.inboxGUI.moved = nil
mod.inboxGUI.moved = nil
end
end
-- Rebuild it since it's visible
-- Rebuild it since it's visible
mod:ShowInboxGUI()
mod:ShowInboxGUI()
end
end
end
end




local function _onLeaveFunc(frame, info)
local function _onLeaveFunc(frame, info)
if mod.tooltipShowing == frame then
if mod.tooltipShowing == frame then
GameTooltip:Hide()
GameTooltip:Hide()
mod.tooltipShowing = nil
mod.tooltipShowing = nil
frame:SetScript("OnKeyUp", nil)
frame:SetScript("OnKeyUp", nil)
frame:SetScript("OnKeyDown", nil)
frame:SetScript("OnKeyDown", nil)
end
end
end
end


local function _toggleCompareItem()
local function _toggleCompareItem()
if IsShiftKeyDown() then
if IsShiftKeyDown() then
GameTooltip_ShowCompareItem()
GameTooltip_ShowCompareItem()
else
else
-- There appears to be no other way. Sigh.
-- There appears to be no other way. Sigh.
if ( GameTooltip.shoppingTooltips ) then
if ( GameTooltip.shoppingTooltips ) then
for _, frame in pairs(GameTooltip.shoppingTooltips) do
for _, frame in pairs(GameTooltip.shoppingTooltips) do
frame:Hide()
frame:Hide()
end
end
end
end
GameTooltip.comparing = false
GameTooltip.comparing = false
end
end
end
end


local function _onEnterFunc(frame, info) -- contributed by bigzero
local function _onEnterFunc(frame, info) -- contributed by bigzero
mod.tooltipShowing = frame
mod.tooltipShowing = frame
GameTooltip:SetOwner(frame, 'ANCHOR_BOTTOMRIGHT', 0, 0)
GameTooltip:SetOwner(frame, 'ANCHOR_BOTTOMRIGHT', 0, 0)
if info.index and info.attachment and GetInboxItem(info.index, info.attachment) then
if info.index and info.attachment and GetInboxItem(info.index, info.attachment) then
GameTooltip:SetInboxItem(info.index, info.attachment)
GameTooltip:SetInboxItem(info.index, info.attachment)
end
end
if IsShiftKeyDown() then
if IsShiftKeyDown() then
GameTooltip_ShowCompareItem()
GameTooltip_ShowCompareItem()
end
end
if info.money then
if info.money then
GameTooltip:AddLine(ENCLOSED_MONEY, "", 1, 1, 1)
GameTooltip:AddLine(ENCLOSED_MONEY, "", 1, 1, 1)
SetTooltipMoney(GameTooltip, info.money)
SetTooltipMoney(GameTooltip, info.money)
SetMoneyFrameColor('GameTooltipMoneyFrame', HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
SetMoneyFrameColor('GameTooltipMoneyFrame', HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
end
end
if (info.cod or 0) > 0 then
if (info.cod or 0) > 0 then
GameTooltip:AddLine(COD_AMOUNT, "", 1, 1, 1)
GameTooltip:AddLine(COD_AMOUNT, "", 1, 1, 1)
SetTooltipMoney(GameTooltip, info.cod)
SetTooltipMoney(GameTooltip, info.cod)
SetMoneyFrameColor('GameTooltipMoneyFrame', HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
SetMoneyFrameColor('GameTooltipMoneyFrame', HIGHLIGHT_FONT_COLOR.r, HIGHLIGHT_FONT_COLOR.g, HIGHLIGHT_FONT_COLOR.b)
end
end
GameTooltip:Show()
GameTooltip:Show()
frame:SetScript("OnKeyDown", _toggleCompareItem)
frame:SetScript("OnKeyDown", _toggleCompareItem)
frame:SetScript("OnKeyUp", _toggleCompareItem)
frame:SetScript("OnKeyUp", _toggleCompareItem)
end
end


local function _createButton(title, parent, onclick, anchorTo, xoffset, tooltipHeader, tooltipText)
local function _createButton(title, parent, onclick, anchorTo, xoffset, tooltipHeader, tooltipText)
local buttons = mod.buttons or {}
local buttons = mod.buttons or {}
mod.buttons = buttons
mod.buttons = buttons
local button = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
local button = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
button:SetText(title)
button:SetText(title)
button:SetWidth(25)
button:SetWidth(25)
button:SetHeight(20)
button:SetHeight(20)
button:SetScript("OnClick", onclick)
button:SetScript("OnClick", onclick)
buttons[title] = button
buttons[title] = button
button:SetPoint("RIGHT", anchorTo, "LEFT", xoffset, 0)
button:SetPoint("RIGHT", anchorTo, "LEFT", xoffset, 0)
_addTooltipToFrame(button, tooltipHeader, tooltipText)
_addTooltipToFrame(button, tooltipHeader, tooltipText)
return button
return button
end
end


local function _createOrAttachSearchBar(tooltip)
local function _createOrAttachSearchBar(tooltip)
local toolbar = mod._toolbar
local toolbar = mod._toolbar
if not toolbar then
if not toolbar then
toolbar = CreateFrame("Frame", nil, UIParent)
toolbar = CreateFrame("Frame", nil, UIParent)
toolbar:SetHeight(49)
toolbar:SetHeight(49)


local closeButton = CreateFrame("Button", "BulkMailInboxToolbarCloseButton", toolbar, "UIPanelCloseButton")
local closeButton = CreateFrame("Button", "BulkMailInboxToolbarCloseButton", toolbar, "UIPanelCloseButton")
closeButton:SetPoint("TOPRIGHT", toolbar, "TOPRIGHT", 0, 0)
closeButton:SetPoint("TOPRIGHT", toolbar, "TOPRIGHT", 0, 0)
closeButton:SetScript("OnClick", function() mod:HideInboxGUI() end)
closeButton:SetScript("OnClick", function() mod:HideInboxGUI() end)
_addTooltipToFrame(closeButton, L["Close"], L["Close the window and stop taking items from the inbox."])
_addTooltipToFrame(closeButton, L["Close"], L["Close the window and stop taking items from the inbox."])
local nextButton = CreateFrame("Button", nil, toolbar)
local nextButton = CreateFrame("Button", nil, toolbar)
nextButton:SetNormalTexture([[Interface\Buttons\UI-SpellbookIcon-NextPage-Up]])
nextButton:SetNormalTexture([[Interface\Buttons\UI-SpellbookIcon-NextPage-Up]])
nextButton:SetPushedTexture([[Interface\Buttons\UI-SpellbookIcon-NextPage-Down]])
nextButton:SetPushedTexture([[Interface\Buttons\UI-SpellbookIcon-NextPage-Down]])
nextButton:SetDisabledTexture([[Interface\Buttons\UI-SpellbookIcon-NextPage-Disabled]])
nextButton:SetHighlightTexture([[Interface\Buttons\UI-Common-MouseHilight]], "ADD")
nextButton:SetPoint("TOP", closeButton, "BOTTOM", 0, 9)
nextButton:SetScript("OnClick", function() startPage = startPage + 1 mod:ShowInboxGUI() end)
nextButton:SetWidth(25)
nextButton:SetHeight(25)
_addTooltipToFrame(nextButton, L["Next Page"], L["Go to the next page of items."])
local prevButton = CreateFrame("Button", nil, toolbar)
prevButton:SetNormalTexture([[Interface\Buttons\UI-Sp