ElvUI/Modules/DataTexts/Friends.lua

590 lines
22 KiB
Lua

local E, L, V, P, G = unpack(select(2, ...)); --Import: Engine, Locales, PrivateDB, ProfileDB, GlobalDB
local DT = E:GetModule('DataTexts')
local _G = _G
local type, ipairs, pairs, select = type, ipairs, pairs, select
local sort, next, wipe, tremove, tinsert = sort, next, wipe, tremove, tinsert
local format, gsub, strfind, strjoin, strmatch = format, gsub, strfind, strjoin, strmatch
local BNet_GetValidatedCharacterName = BNet_GetValidatedCharacterName
local GetMouseFocus = GetMouseFocus
local BNGetInfo = BNGetInfo
local BNGetNumFriends = BNGetNumFriends
local BNInviteFriend = BNInviteFriend
local BNRequestInviteFriend = BNRequestInviteFriend
local BNSetCustomMessage = BNSetCustomMessage
local GetDisplayedInviteType = GetDisplayedInviteType
local GetQuestDifficultyColor = GetQuestDifficultyColor
local IsChatAFK = IsChatAFK
local IsChatDND = IsChatDND
local IsAltKeyDown = IsAltKeyDown
local IsShiftKeyDown = IsShiftKeyDown
local SendChatMessage = SendChatMessage
local SetItemRef = SetItemRef
local ToggleFriendsFrame = ToggleFriendsFrame
local UnitInParty = UnitInParty
local UnitInRaid = UnitInRaid
local C_FriendList_GetNumFriends = C_FriendList.GetNumFriends
local C_FriendList_GetNumOnlineFriends = C_FriendList.GetNumOnlineFriends
local C_FriendList_GetFriendInfoByIndex = C_FriendList.GetFriendInfoByIndex
local ChatFrame_SendBNetTell = ChatFrame_SendBNetTell
local InCombatLockdown = InCombatLockdown
local C_BattleNet_GetFriendAccountInfo = C_BattleNet.GetFriendAccountInfo
local C_BattleNet_GetFriendNumGameAccounts = C_BattleNet.GetFriendNumGameAccounts
local C_BattleNet_GetFriendGameAccountInfo = C_BattleNet.GetFriendGameAccountInfo
local C_PartyInfo_RequestInviteFromUnit = C_PartyInfo.RequestInviteFromUnit
local C_PartyInfo_InviteUnit = C_PartyInfo.InviteUnit
local PRIEST_COLOR = RAID_CLASS_COLORS.PRIEST
-- create a popup
E.PopupDialogs.SET_BN_BROADCAST = {
text = _G.BN_BROADCAST_TOOLTIP,
button1 = _G.ACCEPT,
button2 = _G.CANCEL,
hasEditBox = 1,
editBoxWidth = 350,
maxLetters = 127,
OnAccept = function(self) BNSetCustomMessage(self.editBox:GetText()) end,
OnShow = function(self) self.editBox:SetText(select(4, BNGetInfo()) ) self.editBox:SetFocus() end,
OnHide = _G.ChatEdit_FocusActiveWindow,
EditBoxOnEnterPressed = function(self) BNSetCustomMessage(self:GetText()) self:GetParent():Hide() end,
EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
timeout = 0,
exclusive = 1,
whileDead = 1,
hideOnEscape = 1,
preferredIndex = 3
}
local menuList = {
{ text = _G.OPTIONS_MENU, isTitle = true, notCheckable=true},
{ text = _G.INVITE, hasArrow = true, notCheckable=true, },
{ text = _G.CHAT_MSG_WHISPER_INFORM, hasArrow = true, notCheckable=true, },
{ text = _G.PLAYER_STATUS, hasArrow = true, notCheckable=true,
menuList = {
{ text = '|cff2BC226'.._G.AVAILABLE..'|r', notCheckable=true, func = function() if IsChatAFK() then SendChatMessage('', 'AFK') elseif IsChatDND() then SendChatMessage('', 'DND') end end },
{ text = '|cffE7E716'.._G.DND..'|r', notCheckable=true, func = function() if not IsChatDND() then SendChatMessage('', 'DND') end end },
{ text = '|cffFF0000'.._G.AFK..'|r', notCheckable=true, func = function() if not IsChatAFK() then SendChatMessage('', 'AFK') end end },
},
},
{ text = _G.BN_BROADCAST_TOOLTIP, notCheckable=true, func = function() E:StaticPopup_Show('SET_BN_BROADCAST') end },
}
local function inviteClick(_, name, guid)
DT.EasyMenu:Hide()
if not (name and name ~= '') then return end
local isBNet = type(name) == 'number'
if guid then
local inviteType = GetDisplayedInviteType(guid)
if inviteType == 'INVITE' or inviteType == 'SUGGEST_INVITE' then
if isBNet then
BNInviteFriend(name)
else
C_PartyInfo_InviteUnit(name)
end
elseif inviteType == 'REQUEST_INVITE' then
if isBNet then
BNRequestInviteFriend(name)
else
C_PartyInfo_RequestInviteFromUnit(name)
end
end
else
-- if for some reason guid isnt here fallback and just try to invite them
-- this is unlikely but having a fallback doesnt hurt
if isBNet then
BNInviteFriend(name)
else
C_PartyInfo_InviteUnit(name)
end
end
end
local function whisperClick(_, name, battleNet)
DT.EasyMenu:Hide()
if battleNet then
ChatFrame_SendBNetTell(name)
else
SetItemRef( 'player:'..name, format('|Hplayer:%1$s|h[%1$s]|h',name), 'LeftButton' )
end
end
local levelNameString = '|cff%02x%02x%02x%d|r |cff%02x%02x%02x%s|r'
local levelNameClassString = '|cff%02x%02x%02x%d|r %s%s%s'
local characterFriend = _G.CHARACTER_FRIEND
local battleNetString = _G.BATTLENET_OPTIONS_LABEL
local totalOnlineString = strjoin('', _G.FRIENDS_LIST_ONLINE, ': %s/%s')
local tthead = {r=0.4, g=0.78, b=1}
local activezone, inactivezone = {r=0.3, g=1.0, b=0.3}, {r=0.65, g=0.65, b=0.65}
local displayString = ''
local friendTable, BNTable, tableList = {}, {}, {}
local friendOnline, friendOffline = gsub(_G.ERR_FRIEND_ONLINE_SS,'\124Hplayer:%%s\124h%[%%s%]\124h',''), gsub(_G.ERR_FRIEND_OFFLINE_S,'%%s','')
local wowString = _G.BNET_CLIENT_WOW
local retailID = _G.WOW_PROJECT_ID
local WOW_CLASSIC = _G.BNET_FRIEND_TOOLTIP_WOW_CLASSIC
local dataValid, lastPanel = false
local statusTable = {
AFK = ' |cffFFFFFF[|r|cffFF9900'..L["AFK"]..'|r|cffFFFFFF]|r',
DND = ' |cffFFFFFF[|r|cffFF3333'..L["DND"]..'|r|cffFFFFFF]|r'
}
-- Makro for get the client: /run for i,v in pairs(_G) do if type(i)=='string' and i:match('BNET_CLIENT_') then print(i,'=',v) end end
local clientSorted = {}
local clientTags = {
[_G.BNET_CLIENT_WOW] = 'WoW',
[_G.BNET_CLIENT_D3] = 'D3',
[_G.BNET_CLIENT_WTCG] = 'HS',
[_G.BNET_CLIENT_HEROES] = 'HotS',
[_G.BNET_CLIENT_OVERWATCH] = 'OW',
[_G.BNET_CLIENT_SC] = 'SC',
[_G.BNET_CLIENT_SC2] = 'SC2',
[_G.BNET_CLIENT_COD] = 'BO4',
[_G.BNET_CLIENT_COD_MW] = 'MW',
[_G.BNET_CLIENT_COD_MW2] = 'MW2',
[_G.BNET_CLIENT_COD_BOCW] = 'CW',
BSAp = L["Mobile"],
}
local clientIndex = {
[_G.BNET_CLIENT_WOW] = 1,
[_G.BNET_CLIENT_D3] = 2,
[_G.BNET_CLIENT_WTCG] = 3,
[_G.BNET_CLIENT_HEROES] = 4,
[_G.BNET_CLIENT_OVERWATCH] = 5,
[_G.BNET_CLIENT_SC] = 6,
[_G.BNET_CLIENT_SC2] = 7,
[_G.BNET_CLIENT_COD] = 8,
[_G.BNET_CLIENT_COD_MW] = 9,
[_G.BNET_CLIENT_COD_MW2] = 10,
[_G.BNET_CLIENT_COD_BOCW] = 11,
App = 12,
BSAp = 13,
}
local function inGroup(name, realmName)
if realmName and realmName ~= '' and realmName ~= E.myrealm then
name = name..'-'..realmName
end
return (UnitInParty(name) or UnitInRaid(name)) and '|cffaaaaaa*|r' or ''
end
local function SortAlphabeticName(a, b)
if a.name and b.name then
return a.name < b.name
end
end
local function BuildFriendTable(total)
wipe(friendTable)
for i = 1, total do
local info = C_FriendList_GetFriendInfoByIndex(i)
if info and info.connected then
local className = E:UnlocalizedClassName(info.className) or ''
local status = (info.afk and statusTable.AFK) or (info.dnd and statusTable.DND) or ''
friendTable[i] = {
name = info.name, --1
level = info.level, --2
class = className, --3
zone = info.area, --4
online = info.connected, --5
status = status, --6
notes = info.notes, --7
guid = info.guid --8
}
end
end
if next(friendTable) then
sort(friendTable, SortAlphabeticName)
end
end
--Sort: client-> (WoW: project-> faction-> name) ELSE:btag
local function Sort(a, b)
if a.client and b.client then
if (a.client == b.client) then
if (a.client == wowString) and a.wowProjectID and b.wowProjectID then
if (a.wowProjectID == b.wowProjectID) and a.faction and b.faction then
if (a.faction == b.faction) and a.characterName and b.characterName then
return a.characterName < b.characterName
end
return a.faction < b.faction
end
return a.wowProjectID < b.wowProjectID
elseif (a.battleTag and b.battleTag) then
return a.battleTag < b.battleTag
end
end
return a.client < b.client
end
end
--Sort client by statically given index (this is a `pairs by keys` sorting method)
local function clientSort(a, b)
if a and b then
if clientIndex[a] and clientIndex[b] then
return clientIndex[a] < clientIndex[b]
end
return a < b
end
end
local function AddToBNTable(bnIndex, bnetIDAccount, accountName, battleTag, characterName, bnetIDGameAccount, client, isOnline, isBnetAFK, isBnetDND, noteText, wowProjectID, realmName, faction, race, className, zoneName, level, guid, gameText)
className = E:UnlocalizedClassName(className) or ''
characterName = BNet_GetValidatedCharacterName(characterName, battleTag, client) or ''
local obj = {
accountID = bnetIDAccount, --1
accountName = accountName, --2
battleTag = battleTag, --3
characterName = characterName, --4
gameID = bnetIDGameAccount, --5
client = client, --6
isOnline = isOnline, --7
isBnetAFK = isBnetAFK, --8
isBnetDND = isBnetDND, --9
noteText = noteText, --10
wowProjectID = wowProjectID, --11
realmName = realmName, --12
faction = faction, --13
race = race, --14
className = className, --15
zoneName = zoneName, --16
level = level, --17
guid = guid, --18
gameText = gameText --19
}
if strmatch(gameText, WOW_CLASSIC) then
obj.classicText, obj.realmName = strmatch(gameText, '(.-)%s%-%s(.+)')
end
BNTable[bnIndex] = obj
if tableList[client] then
tableList[client][#tableList[client]+1] = BNTable[bnIndex]
else
tableList[client] = {}
tableList[client][1] = BNTable[bnIndex]
end
end
local function PopulateBNTable(bnIndex, bnetIDAccount, accountName, battleTag, characterName, bnetIDGameAccount, client, isOnline, isBnetAFK, isBnetDND, noteText, wowProjectID, realmName, faction, race, class, zoneName, level, guid, gameText, hasFocus)
-- `hasFocus` is not added to BNTable[i]; we only need this to keep our friends datatext in sync with the friends list
for i = 1, bnIndex do
local isAdded, bnInfo = 0, BNTable[i]
if bnInfo and (bnInfo.accountID == bnetIDAccount) then
if bnInfo.client == 'BSAp' then
if client == 'BSAp' then -- unlikely to happen
isAdded = 1
elseif client == 'App' then
isAdded = (hasFocus and 2) or 1
else -- Mobile -> Game
isAdded = 2 --swap data
end
elseif bnInfo.client == 'App' then
if client == 'App' then -- unlikely to happen
isAdded = 1
elseif client == 'BSAp' then
isAdded = (hasFocus and 2) or 1
else -- App -> Game
isAdded = 2 --swap data
end
elseif bnInfo.client then -- Game
if client == 'BSAp' or client == 'App' then -- ignore Mobile and App
isAdded = 1
end
end
end
if isAdded == 2 then -- swap data
if bnInfo.client and tableList[bnInfo.client] then
for n, y in ipairs(tableList[bnInfo.client]) do
if y == bnInfo then
tremove(tableList[bnInfo.client], n)
break -- remove the old one from tableList
end
end
end
AddToBNTable(i, bnetIDAccount, accountName, battleTag, characterName, bnetIDGameAccount, client, isOnline, isBnetAFK, isBnetDND, noteText, wowProjectID, realmName, faction, race, class, zoneName, level, guid, gameText)
end
if isAdded ~= 0 then
return bnIndex
end
end
bnIndex = bnIndex + 1 --bump the index one for a new addition
AddToBNTable(bnIndex, bnetIDAccount, accountName, battleTag, characterName, bnetIDGameAccount, client, isOnline, isBnetAFK, isBnetDND, noteText, wowProjectID, realmName, faction, race, class, zoneName, level, guid, gameText)
return bnIndex
end
local function BuildBNTable(total)
for _, v in pairs(tableList) do wipe(v) end
wipe(BNTable)
wipe(clientSorted)
local bnIndex = 0
for i = 1, total do
local accountInfo = C_BattleNet_GetFriendAccountInfo(i)
if accountInfo and accountInfo.gameAccountInfo and accountInfo.gameAccountInfo.isOnline then
local numGameAccounts = C_BattleNet_GetFriendNumGameAccounts(i)
if numGameAccounts and numGameAccounts > 0 then
for y = 1, numGameAccounts do
local gameAccountInfo = C_BattleNet_GetFriendGameAccountInfo(i, y)
bnIndex = PopulateBNTable(bnIndex, accountInfo.bnetAccountID, accountInfo.accountName, accountInfo.battleTag, gameAccountInfo.characterName, gameAccountInfo.gameAccountID, gameAccountInfo.clientProgram, gameAccountInfo.isOnline, accountInfo.isAFK or gameAccountInfo.isGameAFK, accountInfo.isDND or gameAccountInfo.isGameBusy, accountInfo.note, accountInfo.gameAccountInfo.wowProjectID, gameAccountInfo.realmName, gameAccountInfo.factionName, gameAccountInfo.raceName, gameAccountInfo.className, gameAccountInfo.areaName, gameAccountInfo.characterLevel, gameAccountInfo.playerGuid, gameAccountInfo.richPresence, gameAccountInfo.hasFocus)
end
else
bnIndex = PopulateBNTable(bnIndex, accountInfo.bnetAccountID, accountInfo.accountName, accountInfo.battleTag, accountInfo.gameAccountInfo.characterName, accountInfo.gameAccountInfo.gameAccountID, accountInfo.gameAccountInfo.clientProgram, accountInfo.gameAccountInfo.isOnline, accountInfo.isAFK, accountInfo.isDND, accountInfo.note, accountInfo.gameAccountInfo.wowProjectID)
end
end
end
if next(BNTable) then
sort(BNTable, Sort)
end
for c, v in pairs(tableList) do
if next(v) then
sort(v, Sort)
end
tinsert(clientSorted, c)
end
if next(clientSorted) then
sort(clientSorted, clientSort)
end
end
local function Click(self, btn)
if btn == 'RightButton' then
local menuCountWhispers = 0
local menuCountInvites = 0
menuList[2].menuList = {}
menuList[3].menuList = {}
if not E.global.datatexts.settings.Friends.hideWoW then
for _, info in ipairs(friendTable) do
if info.online then
local shouldSkip = false
if (info.status == statusTable.AFK) and E.global.datatexts.settings.Friends.hideAFK then
shouldSkip = true
elseif (info.status == statusTable.DND) and E.global.datatexts.settings.Friends.hideDND then
shouldSkip = true
end
if not shouldSkip then
local classc, levelc = E:ClassColor(info.class), GetQuestDifficultyColor(info.level)
if not classc then classc = levelc end
menuCountWhispers = menuCountWhispers + 1
menuList[3].menuList[menuCountWhispers] = {text = format(levelNameString,levelc.r*255,levelc.g*255,levelc.b*255,info.level,classc.r*255,classc.g*255,classc.b*255,info.name), arg1 = info.name, notCheckable=true, func = whisperClick}
if inGroup(info.name) == '' then
menuCountInvites = menuCountInvites + 1
menuList[2].menuList[menuCountInvites] = {text = format(levelNameString,levelc.r*255,levelc.g*255,levelc.b*255,info.level,classc.r*255,classc.g*255,classc.b*255,info.name), arg1 = info.name, arg2 = info.guid, notCheckable=true, func = inviteClick}
end
end
end
end
end
for _, info in ipairs(BNTable) do
if info.isOnline then
local shouldSkip = false
if (info.isBnetAFK == true) and E.global.datatexts.settings.Friends.hideAFK then
shouldSkip = true
elseif (info.isBnetDND == true) and E.global.datatexts.settings.Friends.hideDND then
shouldSkip = true
end
if info.client and E.global.datatexts.settings.Friends['hide'..info.client] then
shouldSkip = true
end
if not shouldSkip then
local realID, hasBnet = info.accountName, false
for _, z in ipairs(menuList[3].menuList) do
if z and z.text and (z.text == realID) then
hasBnet = true
break
end
end
if not hasBnet then -- hasBnet will make sure only one is added to whispers but still allow us to add multiple into invites
menuCountWhispers = menuCountWhispers + 1
menuList[3].menuList[menuCountWhispers] = {text = realID, arg1 = realID, arg2 = true, notCheckable=true, func = whisperClick}
end
if (info.client and info.client == wowString) and (E.myfaction == info.faction) and inGroup(info.characterName, info.realmName) == '' then
local classc, levelc = E:ClassColor(info.className), GetQuestDifficultyColor(info.level)
if not classc then classc = levelc end
if info.wowProjectID == retailID then
menuCountInvites = menuCountInvites + 1
menuList[2].menuList[menuCountInvites] = {text = format(levelNameString,levelc.r*255,levelc.g*255,levelc.b*255,info.level,classc.r*255,classc.g*255,classc.b*255,info.characterName), arg1 = info.gameID, arg2 = info.guid, notCheckable=true, func = inviteClick}
end
end
end
end
end
DT:SetEasyMenuAnchor(DT.EasyMenu, self)
_G.EasyMenu(menuList, DT.EasyMenu, nil, nil, nil, 'MENU')
elseif InCombatLockdown() then
_G.UIErrorsFrame:AddMessage(E.InfoColor.._G.ERR_NOT_IN_COMBAT)
else
ToggleFriendsFrame(1)
end
end
local lastTooltipXLineHeader
local function TooltipAddXLine(X, header, ...)
X = (X == true and 'AddDoubleLine') or 'AddLine'
if lastTooltipXLineHeader ~= header then
DT.tooltip[X](DT.tooltip, ' ')
DT.tooltip[X](DT.tooltip, header)
lastTooltipXLineHeader = header
end
DT.tooltip[X](DT.tooltip, ...)
end
local function OnEnter()
DT.tooltip:ClearLines()
lastTooltipXLineHeader = nil
local onlineFriends = C_FriendList_GetNumOnlineFriends()
local numberOfFriends = C_FriendList_GetNumFriends()
local totalBNet, numBNetOnline = BNGetNumFriends()
local totalonline = onlineFriends + numBNetOnline
-- no friends online, quick exit
if totalonline == 0 then return end
if not dataValid then
-- only retrieve information for all on-line members when we actually view the tooltip
if numberOfFriends > 0 then BuildFriendTable(numberOfFriends) end
if totalBNet > 0 then BuildBNTable(totalBNet) end
dataValid = true
end
local totalfriends = numberOfFriends + totalBNet
local zonec, classc, levelc, realmc
local shiftDown = IsShiftKeyDown()
DT.tooltip:AddDoubleLine(L["Friends List"], format(totalOnlineString, totalonline, totalfriends),tthead.r,tthead.g,tthead.b,tthead.r,tthead.g,tthead.b)
if (onlineFriends > 0) and not E.global.datatexts.settings.Friends.hideWoW then
for _, info in ipairs(friendTable) do
if info.online then
local shouldSkip = false
if (info.status == statusTable.AFK) and E.global.datatexts.settings.Friends.hideAFK then
shouldSkip = true
elseif (info.status == statusTable.DND) and E.global.datatexts.settings.Friends.hideDND then
shouldSkip = true
end
if not shouldSkip then
if E.MapInfo.zoneText and (E.MapInfo.zoneText == info.zone) then zonec = activezone else zonec = inactivezone end
classc, levelc = E:ClassColor(info.class), GetQuestDifficultyColor(info.level)
if not classc then classc = levelc end
TooltipAddXLine(true, characterFriend, format(levelNameClassString,levelc.r*255,levelc.g*255,levelc.b*255,info.level,info.name,inGroup(info.name),info.status),info.zone,classc.r,classc.g,classc.b,zonec.r,zonec.g,zonec.b)
end
end
end
end
if numBNetOnline > 0 then
local status
for _, client in ipairs(clientSorted) do
local Table = tableList[client]
local shouldSkip = E.global.datatexts.settings.Friends['hide'..client]
if not shouldSkip then
for _, info in ipairs(Table) do
if info.isOnline then
shouldSkip = false
if info.isBnetAFK == true then
if E.global.datatexts.settings.Friends.hideAFK then
shouldSkip = true
end
status = statusTable.AFK
elseif info.isBnetDND == true then
if E.global.datatexts.settings.Friends.hideDND then
shouldSkip = true
end
status = statusTable.DND
else
status = ''
end
if not shouldSkip then
local header = format('%s (%s)', battleNetString, info.classicText or clientTags[client] or client)
if info.client and info.client == wowString then
classc = E:ClassColor(info.className)
if info.level and info.level ~= '' then
levelc = GetQuestDifficultyColor(info.level)
else
classc, levelc = PRIEST_COLOR, PRIEST_COLOR
end
--Sometimes the friend list is fubar with level 0 unknown friends
if not classc then classc = PRIEST_COLOR end
TooltipAddXLine(true, header, format(levelNameString..'%s%s',levelc.r*255,levelc.g*255,levelc.b*255,info.level,classc.r*255,classc.g*255,classc.b*255,info.characterName,inGroup(info.characterName, info.realmName),status),info.accountName,238,238,238,238,238,238)
if shiftDown then
if E.MapInfo.zoneText and (E.MapInfo.zoneText == info.zoneName) then zonec = activezone else zonec = inactivezone end
if E.myrealm == info.realmName then realmc = activezone else realmc = inactivezone end
TooltipAddXLine(true, header, info.zoneName, info.realmName, zonec.r, zonec.g, zonec.b, realmc.r, realmc.g, realmc.b)
end
else
TooltipAddXLine(true, header, info.characterName..status, info.accountName, .9, .9, .9, .9, .9, .9)
if shiftDown and (info.gameText and info.gameText ~= '') and (info.client and info.client ~= 'App' and info.client ~= 'BSAp') then
TooltipAddXLine(false, header, info.gameText, inactivezone.r, inactivezone.g, inactivezone.b)
end
end
end
end
end
end
end
end
DT.tooltip:Show()
end
local function OnEvent(self, event, message)
local onlineFriends = C_FriendList_GetNumOnlineFriends()
local _, numBNetOnline = BNGetNumFriends()
-- special handler to detect friend coming online or going offline
-- when this is the case, we invalidate our buffered table and update the
-- datatext information
if event == 'CHAT_MSG_SYSTEM' then
if not (strfind(message, friendOnline) or strfind(message, friendOffline)) then return end
end
-- force update when showing tooltip
dataValid = false
if not IsAltKeyDown() and event == 'MODIFIER_STATE_CHANGED' and GetMouseFocus() == self then
OnEnter(self)
end
if E.global.datatexts.settings.Friends.NoLabel then
self.text:SetFormattedText(displayString, onlineFriends + numBNetOnline)
else
self.text:SetFormattedText(displayString, E.global.datatexts.settings.Friends.Label ~= '' and E.global.datatexts.settings.Friends.Label or _G.FRIENDS..': ', onlineFriends + numBNetOnline)
end
lastPanel = self
end
local function ValueColorUpdate(hex)
displayString = strjoin('', E.global.datatexts.settings.Friends.NoLabel and '' or '%s', hex, '%d|r')
if lastPanel then
OnEvent(lastPanel, 'ELVUI_COLOR_UPDATE')
end
end
E.valueColorUpdateFuncs[ValueColorUpdate] = true
DT:RegisterDatatext('Friends', _G.SOCIAL_LABEL, {'BN_FRIEND_ACCOUNT_ONLINE', 'BN_FRIEND_ACCOUNT_OFFLINE', 'BN_FRIEND_INFO_CHANGED', 'FRIENDLIST_UPDATE', 'CHAT_MSG_SYSTEM', 'MODIFIER_STATE_CHANGED'}, OnEvent, nil, Click, OnEnter, nil, _G.FRIENDS, nil, ValueColorUpdate)