You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

387 lines
12 KiB

-- module independent variables --
----------------------------------
local addon, ns = ...
local C, L, I = ns.LC.color, ns.L, ns.I
-- module own local variables and local cached functions --
-----------------------------------------------------------
local name = "Mail" -- BUTTON_LAG_MAIL L["ModDesc-Mail"]
local ttName, tooltip, tt, module = name.."TT"
local alertLocked,onUpdateLocked,hookOn = false,false,false;
local storedMailLineFaction = "%s%s |TInterface\\PVPFrame\\PVP-Currency-%s:16:16:0:-1:16:16:0:16:0:16|t";
local storedMailLineNeutral = "%s%s";
local icons = {}
-- register icon names and default files --
-------------------------------------------
I[name] = {iconfile="interface\\icons\\inv_letter_15",coords={0.05,0.95,0.05,0.95}} --IconName::Mail--
I[name..'_new'] = {iconfile="interface\\icons\\inv_letter_"..(ns.client_version<2 and 16 or 18),coords={0.05,0.95,0.05,0.95}} --IconName::Mail_new--
I[name..'_stored'] = {iconfile="interface\\icons\\inv_letter_03",coords={0.05,0.95,0.05,0.95}} --IconName::Mail_stored--
-- some local functions --
--------------------------
local function clearAllStoredMails()
for i=1, #Broker_Everything_CharacterDB.order do
local toonName = Broker_Everything_CharacterDB.order[i];
if toonName and toonName~=ns.player.name_realm then
ns.tablePath(Broker_Everything_CharacterDB,toonName,"mail");
Broker_Everything_CharacterDB[toonName].mail = {new={},stored={}};
end
end
module.onevent({},"BE_DUMMY_EVENT");
end
local function toonHasMails(toonMails,key,counter)
local has,t,sender,oldest,returns = false,time();
local mails = toonMails[key];
if mails and #mails>0 then
for i=1, #mails do
if type(mails[i])=="table" then
sender,returns = mails[i].sender,mails[i].returns;
else
sender,returns = strsplit(";",mails[i]);
end
returns = tonumber(returns);
if returns then
if returns<t then
counter.returned = counter.returned + 1;
else
has = true;
counter[key] = (counter[key] or 0) + 1;
if (not oldest) or (oldest and returns<oldest) then
oldest = returns;
end
end
end
end
end
return has,oldest;
end
local function sortStoredMails(a,b)
return (a.returns or 0)<(b.returns or 0);
end
local function UpdateStatus(event)
if ns.toon.mail==nil then
ns.toon.mail = { new={}, stored={} };
end
local mailNew, _time = HasNewMail(), time();
local sender,daysLeft,dt,ht,_;
local returns,mailState,next1,next2,next3,tmp = (99*86400),0;
if (_G.MailFrame:IsShown()) or (event=="MAIL_CLOSED") then
ns.toon.mail.num, ns.toon.mail.total = GetInboxNumItems();
ns.toon.mail.num, ns.toon.mail.total = ns.toon.mail.num or 0, ns.toon.mail.total or 0;
if ns.toon.mail.stored==nil then
ns.toon.mail.stored={};
else
wipe(ns.toon.mail.stored);
end
for i=1, ns.toon.mail.num do
local _, _, sender_realm, _, _, _, daysLeft = GetInboxHeaderInfo(i);
if sender_realm then
local returns = _time + floor(daysLeft * 86400);
if not sender_realm:find("%-") then
sender_realm = sender_realm.."-"..ns.realm_short;
end
tinsert(ns.toon.mail.stored,sender_realm..";"..returns);
end
end
wipe(ns.toon.mail.new);
else
local names = {};
if ns.toon.mail.stored then
for i=1, #ns.toon.mail.stored do
local sender = strsplit(";",ns.toon.mail.stored[i]);
names[sender]=true;
end
end
if ns.toon.mail.new then
for i=1, #ns.toon.mail.new do
if type(ns.toon.mail.new[i])=="string" then
local sender = strsplit(";",ns.toon.mail.new[i]);
names[sender]=true;
else
ns.toon.mail.new[i] = nil;
end
end
end
local latest = {GetLatestThreeSenders()};
for i=1, #latest do
if type(latest[i])=="string" then
latest[i] = ns.realmCheckOrAppend(latest[i]);
if not names[latest[i]] then
tinsert(ns.toon.mail.new,latest[i]);
end
end
end
end
local mailStored,counter,_time,oldest = false,{stored=0,new=0,returned=0},time();
for i=1, #Broker_Everything_CharacterDB.order do
local toonName = Broker_Everything_CharacterDB.order[i];
if toonName and toonName~=ns.player.name_realm then
local toonMails = Broker_Everything_CharacterDB[toonName].mail or {};
for _,key in pairs({"stored","new"}) do
local has,_oldest = toonHasMails(toonMails,key,counter);
if has then
if (not oldest) or (oldest and oldest>_oldest) then
oldest = _oldest;
end
mailStored = true;
end
end
end
end
local icon,text,obj = I(name), L["No Mail"],ns.LDB:GetDataObjectByName(module.ldbName);
if #ns.toon.mail.new>0 then
icon, text = I(name.."_new"), C("green",L["New mail"]);
elseif mailStored then
icon, text = I(name.."_stored"), C("yellow",L["Stored mails"]);
end
obj.iconCoords,obj.icon,obj.text = icon.coords or {0,1,0,1},icon.iconfile,text;
end
local function AddStoredMailsLine(tt,toon)
local hasData,toonName,_time = false,{strsplit("-",toon,2)},time();
local faction,class = Broker_Everything_CharacterDB[toon].faction, Broker_Everything_CharacterDB[toon].class;
if Broker_Everything_CharacterDB[toon].mail and ns.showThisChar(name,toonName[2],faction) then
local toonMails = Broker_Everything_CharacterDB[toon].mail or {};
local counter,key,oldest,has={stored=0,new=0,returned=0};
for _,key in pairs({"stored","new"}) do
local has,_oldest = toonHasMails(toonMails,key,counter);
if has then
oldest = _oldest;
end
end
if counter.new>0 or counter.stored>0 then
local str="";
if counter.stored==0 and counter.new>0 then
str = C("green",L["New mails"]..CHAT_HEADER_SUFFIX..counter.new);
elseif counter.stored>0 or counter.new>0 then
str = L["Mails"]..CHAT_HEADER_SUFFIX..counter.stored;
if counter.new>0 then
str = str.." "..C("green","("..NEW..CHAT_HEADER_SUFFIX..counter.new..")");
end
end
local l=tt:AddLine(
(faction=="Neutral" and storedMailLineNeutral or storedMailLineFaction):format(C(class,ns.scm(toonName[1])),ns.showRealmName(name,toonName[2]),faction),
str
);
if toon==ns.toon.name_realm then
tt:SetLineColor(l, .5, .5, .5);
end
hasData = true;
end
if oldest then
local returnsIn = oldest-_time;
tt:AddLine(" "..C("ltgray",L["Oldest:"]), C((returnsIn<86400 and "red") or (returnsIn<(3*86400) and "orange") or (returnsIn<(7*86400) and "yellow") or "ltgray",SecondsToTime(returnsIn)));
end
end
return hasData;
end
local function createTooltip(tt)
if not (tt and tt.key and tt.key==ttName) then return end -- don't override other LibQTip tooltips...
local newMails = {};
if HasNewMail() then
newMails = {GetLatestThreeSenders()}; -- this function is unreliable after clearing and closing mail box. must be captured by HasNewMail().
end
local l,c
if tt.lines~=nil then tt:Clear(); end
local l = tt:AddLine();
tt:SetCell(l,1,C("dkyellow",BUTTON_LAG_MAIL),tt:GetHeaderFont(),"LEFT");
tt:AddSeparator(3,0,0,0,0);
if #newMails>0 then
tt:SetCell(l,2,C("green",L["You have new mails"]),nil,"RIGHT");
tt:AddLine(C("ltblue",L["Lastest senders:"]));
tt:AddSeparator()
for i,v in ipairs(newMails) do
tt:AddLine(" "..ns.scm(v));
end
else
tt:SetCell(l,2,C("gray",L["No new mails"]),nil,"RIGHT");
end
if (ns.profile[name].showDaysLeft) then
tt:AddSeparator(3,0,0,0,0);
tt:SetCell(tt:AddLine(),1,C("dkyellow",L["Left in mailbox"]),nil,"LEFT",0);
tt:AddSeparator();
local hasData,t = false;
if AddStoredMailsLine(tt,ns.player.name_realm) then
hasData=true;
end
for i=1, #Broker_Everything_CharacterDB.order do
if Broker_Everything_CharacterDB.order[i]~=ns.player.name_realm then
if AddStoredMailsLine(tt,Broker_Everything_CharacterDB.order[i]) then
hasData = true;
end
end
end
if not hasData then
tt:AddLine(C("gray",L["No data"]));
end
end
if (ns.profile.GeneralOptions.showHints) then
tt:AddSeparator(4,0,0,0,0)
ns.ClickOpts.ttAddHints(tt,name);
end
ns.roundupTooltip(tt);
end
local function SendMailHook(targetName)
if debugstack():find("?") and type(targetName)~="string" then return end -- ignore double executed function
local t = time()+30*86400;
if targetName:find("-") then
local tn,r = strsplit("-",targetName,2);
if type(r)=="string" and r:len()>0 and type(ns.realms[r])=="string" then
targetName = tn.."-"..ns.realms[r];
end
else
targetName = targetName.."-"..ns.realm;
end
if Broker_Everything_CharacterDB[targetName] then
if Broker_Everything_CharacterDB[targetName].mail==nil then
Broker_Everything_CharacterDB[targetName].mail = { new={}, stored={} };
end
tinsert(Broker_Everything_CharacterDB[targetName].mail.new,ns.player.name..";"..t);
end
end
-- module functions and variables --
------------------------------------
module = {
events = {
"PLAYER_LOGIN",
"UPDATE_PENDING_MAIL",
"MAIL_CLOSED",
"MAIL_SHOW"
},
config_defaults = {
enabled = false,
playsound = false,
showDaysLeft = true,
hideMinimapMail = false,
showAllFactions=true,
showRealmNames=true,
showCharsFrom="2"
},
clickOptionsRename = {
["menu"] = "open_menu"
},
clickOptions = {
["menu"] = "OptionMenu"
}
}
ns.ClickOpts.addDefaults(module,{
menu = "_RIGHT"
});
function module.options()
return {
broker = nil,
tooltip = {
showDaysLeft={ type="toggle", order=1, name=L["List mails on chars"], desc=L["Display a list of chars on all realms with there mail counts and 3 lowest days before return to sender. Chars with empty mail box aren't displayed."] },
showAllFactions=2,
showRealmNames=3,
showCharsFrom=4,
},
misc = {
playsound={ type="toggle", order=1, name=L["Play sound on new mail"], desc=L["Enable to play a sound on receiving a new mail message. Default is off"], width="full" },
hideMinimapMail={ type="toggle", order=2, name=L["Hide minimap mail icon"], desc=L["Hide minimap mail icon"], width="full", disabled=ns.coexist.IsNotAlone },
hideMinimapMailInfo = { type="description", order=3, name=ns.coexist.optionInfo, fontSize="medium", hidden=ns.coexist.IsNotAlone }
},
},
{
hideMinimapMail = "BE_HIDE_MINIMAPMAIL",
}
end
function module.init()
for i=1, 22 do
local I = ("inv_letter_%02d"):format(i);
icons[I] = "|Tinterface\\icons\\"..I..":16:16:0:0|t";
end
if (not ns.coexist.IsNotAlone()) and ns.profile[name].hideMinimapMail then
ns.hideFrames("MiniMapMailFrame",true);
end
end
function module.onevent(self,event,msg)
if event=="BE_UPDATE_CFG" and msg and msg:find("^ClickOpt") then
ns.ClickOpts.update(name);
elseif event=="BE_UPDATE_CFG" then
if not ns.coexist.IsNotAlone() then
ns.hideFrames("MiniMapMailFrame",ns.profile[name].hideMinimapMail);
end
elseif event=="PLAYER_LOGIN" then
hooksecurefunc("SendMail",SendMailHook);
for i=1, #Broker_Everything_CharacterDB.order do
local toonName = Broker_Everything_CharacterDB.order[i];
if toonName then
ns.tablePath(Broker_Everything_CharacterDB,toonName,"mail","new");
ns.tablePath(Broker_Everything_CharacterDB,toonName,"mail","store");
if Broker_Everything_CharacterDB[toonName].mail.count~=nil then -- deprecated counter
Broker_Everything_CharacterDB[toonName].mail.count=nil;
end
end
end
end
if ns.eventPlayerEnteredWorld then
if (HasNewMail()) and (ns.profile[name].playsound) and (not alertLocked) then
PlaySoundFile("Interface\\Addons\\"..addon.."\\media\\mailalert.mp3", "Master"); -- or SFX?
alertLocked=true;
elseif (not HasNewMail()) then
alertLocked=false;
end
if event=="MAIL_SHOW" and ns.IsRetailClient() and not self.MailFrameOnHideHooked then
_G.MailFrame:HookScript("OnHide",function()
UpdateStatus("MAIL_CLOSED")
end);
self.MailFrameOnHideHooked = true;
end
UpdateStatus(event);
end
end
-- function module.optionspanel(panel) end
-- function module.onmousewheel(self,direction) end
-- function module.ontooltip(tooltip) end
function module.onenter(self)
if (ns.tooltipChkOnShowModifier(false)) then return; end
tt = ns.acquireTooltip({ttName, 2, "LEFT", "RIGHT"},{true},{self});
createTooltip(tt);
end
-- function module.onleave(self) end
-- function module.onclick(self,button) end
-- function module.ondblclick(self,button) end
-- final module registration --
-------------------------------
ns.modules[name] = module;