Files
HailMaryGuildTools/Core/VersionNoticeWindow.lua

328 lines
11 KiB
Lua

local ADDON_NAME = "HailMaryGuildTools"
local HMGT = _G[ADDON_NAME]
if not HMGT then return end
local L = HMGT.L or LibStub("AceLocale-3.0"):GetLocale(ADDON_NAME)
local AceGUI = LibStub("AceGUI-3.0", true)
local CLASS_ICON_TCOORDS = CLASS_ICON_TCOORDS or {}
local function NormalizeName(name)
if HMGT.NormalizePlayerName then
return HMGT:NormalizePlayerName(name)
end
return tostring(name or "")
end
local function GetRosterRows()
local rows = {}
local seen = {}
local function addUnit(unitId)
if not unitId or not UnitExists(unitId) then
return
end
local name = NormalizeName(UnitName(unitId))
if not name or name == "" or seen[name] then
return
end
seen[name] = true
rows[#rows + 1] = {
name = name,
class = select(2, UnitClass(unitId)),
isLeader = UnitIsGroupLeader and UnitIsGroupLeader(unitId) or false,
isAssistant = UnitIsGroupAssistant and UnitIsGroupAssistant(unitId) or false,
connected = UnitIsConnected and UnitIsConnected(unitId) ~= false or true,
isPlayer = UnitIsUnit and UnitIsUnit(unitId, "player") or unitId == "player",
}
end
if IsInRaid() then
for i = 1, GetNumGroupMembers() do
addUnit("raid" .. i)
end
elseif IsInGroup() then
addUnit("player")
for i = 1, GetNumSubgroupMembers() do
addUnit("party" .. i)
end
else
addUnit("player")
end
table.sort(rows, function(a, b)
if a.isLeader ~= b.isLeader then
return a.isLeader
end
if a.isPlayer ~= b.isPlayer then
return a.isPlayer
end
return tostring(a.name or "") < tostring(b.name or "")
end)
return rows
end
local function GetPlayerVersionText(name)
local normalized = NormalizeName(name)
if normalized == NormalizeName(UnitName("player")) then
return tostring(HMGT.ADDON_VERSION or "dev"), tonumber(HMGT.PROTOCOL_VERSION) or 0, true
end
local version = HMGT.peerVersions and HMGT.peerVersions[normalized] or nil
local protocol = HMGT.GetPeerProtocolVersion and HMGT:GetPeerProtocolVersion(normalized) or 0
if version and version ~= "" then
return tostring(version), tonumber(protocol) or 0, true
end
return nil, tonumber(protocol) or 0, false
end
local function ApplyClassIcon(texture, classTag)
if not texture then
return
end
local coords = classTag and CLASS_ICON_TCOORDS[classTag]
if coords then
texture:SetTexture("Interface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES")
texture:SetTexCoord(coords[1], coords[2], coords[3], coords[4])
texture:Show()
else
texture:SetTexture(nil)
texture:Hide()
end
end
local function AcquireVersionRow(window, index)
window.versionRows = window.versionRows or {}
local row = window.versionRows[index]
if row then
return row
end
local parent = window.scrollChild
row = CreateFrame("Frame", nil, parent)
row:SetHeight(22)
row.background = row:CreateTexture(nil, "BACKGROUND")
row.background:SetAllPoints(row)
row.background:SetColorTexture(1, 1, 1, 0.03)
row.classIcon = row:CreateTexture(nil, "ARTWORK")
row.classIcon:SetSize(16, 16)
row.classIcon:SetPoint("LEFT", row, "LEFT", 4, 0)
row.nameText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
row.nameText:SetPoint("LEFT", row.classIcon, "RIGHT", 6, 0)
row.nameText:SetJustifyH("LEFT")
row.versionText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
row.versionText:SetPoint("LEFT", row, "LEFT", 250, 0)
row.versionText:SetWidth(150)
row.versionText:SetJustifyH("LEFT")
row.protocolText = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
row.protocolText:SetPoint("LEFT", row, "LEFT", 410, 0)
row.protocolText:SetWidth(100)
row.protocolText:SetJustifyH("LEFT")
window.versionRows[index] = row
return row
end
function HMGT:RefreshVersionNoticeWindow()
local window = self.versionNoticeWindow
if not window then
return
end
local roster = GetRosterRows()
local localName = NormalizeName(UnitName("player"))
for index, info in ipairs(roster) do
local row = AcquireVersionRow(window, index)
row:ClearAllPoints()
if index == 1 then
row:SetPoint("TOPLEFT", window.scrollChild, "TOPLEFT", 0, 0)
row:SetPoint("TOPRIGHT", window.scrollChild, "TOPRIGHT", 0, 0)
else
row:SetPoint("TOPLEFT", window.versionRows[index - 1], "BOTTOMLEFT", 0, -2)
row:SetPoint("TOPRIGHT", window.versionRows[index - 1], "BOTTOMRIGHT", 0, -2)
end
ApplyClassIcon(row.classIcon, info.class)
local nameLabel = tostring(info.name or UNKNOWN)
if info.isLeader then
nameLabel = string.format("%s %s", nameLabel, L["VERSION_WINDOW_LEADER_TAG"] or "(Leader)")
elseif info.isAssistant then
nameLabel = string.format("%s %s", nameLabel, L["VERSION_WINDOW_ASSISTANT_TAG"] or "(Assist)")
end
if info.isPlayer or info.name == localName then
nameLabel = string.format("%s %s", nameLabel, L["VERSION_WINDOW_SELF_TAG"] or "(You)")
end
row.nameText:SetText(nameLabel)
row.nameText:SetTextColor(1, 0.82, 0.1, 1)
local versionText, protocol, hasAddon = GetPlayerVersionText(info.name)
if hasAddon then
row.versionText:SetText(versionText or "?")
row.versionText:SetTextColor(0.9, 0.9, 0.9, 1)
row.protocolText:SetText(protocol > 0 and tostring(protocol) or "-")
row.protocolText:SetTextColor(0.75, 0.75, 0.75, 1)
else
row.versionText:SetText(L["VERSION_WINDOW_MISSING_ADDON"] or "Addon not installed")
row.versionText:SetTextColor(1, 0.25, 0.25, 1)
row.protocolText:SetText("-")
row.protocolText:SetTextColor(1, 0.25, 0.25, 1)
end
row:Show()
end
if window.versionRows then
for index = #roster + 1, #window.versionRows do
window.versionRows[index]:Hide()
end
end
local contentHeight = math.max(1, (#roster * 24))
window.scrollChild:SetHeight(contentHeight)
local known = 0
for _, info in ipairs(roster) do
local _, _, hasAddon = GetPlayerVersionText(info.name)
if hasAddon then
known = known + 1
end
end
window.messageText:SetText(L["VERSION_WINDOW_MESSAGE"] or "Hail Mary Guild Tools versions in your current group")
window.detailText:SetText(string.format(
L["VERSION_WINDOW_CURRENT"] or "Current version: %s | Protocol: %s",
tostring(HMGT.ADDON_VERSION or "dev"),
tostring(HMGT.PROTOCOL_VERSION or "?")
))
window:SetStatusText(string.format(
L["VERSION_WINDOW_STATUS"] or "Detected HMGT on %d/%d players",
tonumber(known) or 0,
tonumber(#roster) or 0
))
end
function HMGT:EnsureVersionNoticeWindow()
if self.versionNoticeWindow then
return self.versionNoticeWindow
end
self.versionNoticeWindowStatus = self.versionNoticeWindowStatus or {
width = 640,
height = 420,
}
local window = self:CreateAceWindow("versionNotice", {
title = L["VERSION_WINDOW_TITLE"] or "HMGT Version Check",
statusText = "",
statusTable = self.versionNoticeWindowStatus,
width = self.versionNoticeWindowStatus.width or 640,
height = self.versionNoticeWindowStatus.height or 420,
backgroundTexture = "Interface\\AddOns\\HailMaryGuildTools\\Media\\HailMaryLogo.png",
backgroundWidth = 220,
backgroundHeight = 120,
backgroundOffsetY = -8,
backgroundAlpha = 0.08,
strata = "FULLSCREEN_DIALOG",
})
if not window then
return nil
end
local content = window:GetContent()
local messageText = content:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge")
messageText:SetPoint("TOPLEFT", content, "TOPLEFT", 24, -22)
messageText:SetPoint("TOPRIGHT", content, "TOPRIGHT", -24, -22)
messageText:SetJustifyH("LEFT")
messageText:SetTextColor(1, 0.82, 0.1, 1)
window.messageText = messageText
local detailText = content:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
detailText:SetPoint("TOPLEFT", messageText, "BOTTOMLEFT", 0, -8)
detailText:SetPoint("TOPRIGHT", messageText, "BOTTOMRIGHT", 0, -8)
detailText:SetJustifyH("LEFT")
detailText:SetTextColor(0.9, 0.9, 0.9, 1)
window.detailText = detailText
local refreshButton = AceGUI and AceGUI:Create("Button") or nil
if refreshButton then
refreshButton:SetText(L["VERSION_WINDOW_REFRESH"] or "Refresh")
refreshButton:SetWidth(120)
refreshButton:SetCallback("OnClick", function()
HMGT:RequestSync("VersionWindow")
HMGT:RefreshVersionNoticeWindow()
end)
refreshButton.frame:SetParent(window.frame)
refreshButton.frame:ClearAllPoints()
refreshButton.frame:SetPoint("TOPRIGHT", content, "TOPRIGHT", -24, -68)
refreshButton.frame:Show()
window.refreshButton = refreshButton
end
local header = CreateFrame("Frame", nil, content)
header:SetPoint("TOPLEFT", detailText, "BOTTOMLEFT", 0, -14)
header:SetPoint("TOPRIGHT", content, "TOPRIGHT", -24, -96)
header:SetHeight(18)
window.header = header
local nameHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormal")
nameHeader:SetPoint("LEFT", header, "LEFT", 24, 0)
nameHeader:SetText(L["VERSION_WINDOW_COLUMN_PLAYER"] or "Player")
local versionHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormal")
versionHeader:SetPoint("LEFT", header, "LEFT", 250, 0)
versionHeader:SetText(L["VERSION_WINDOW_COLUMN_VERSION"] or "Version")
local protocolHeader = header:CreateFontString(nil, "OVERLAY", "GameFontNormal")
protocolHeader:SetPoint("LEFT", header, "LEFT", 410, 0)
protocolHeader:SetText(L["VERSION_WINDOW_COLUMN_PROTOCOL"] or "Protocol")
local scrollFrame = CreateFrame("ScrollFrame", nil, content, "UIPanelScrollFrameTemplate")
scrollFrame:SetPoint("TOPLEFT", header, "BOTTOMLEFT", 0, -6)
scrollFrame:SetPoint("BOTTOMRIGHT", content, "BOTTOMRIGHT", -28, 24)
window.scrollFrame = scrollFrame
local scrollChild = CreateFrame("Frame", nil, scrollFrame)
scrollChild:SetSize(1, 1)
scrollFrame:SetScrollChild(scrollChild)
window.scrollChild = scrollChild
self.versionNoticeWindow = window
return window
end
function HMGT:ShowVersionMismatchPopup(playerName, detail, sourceTag, opts)
opts = opts or {}
if playerName or detail or sourceTag then
self.latestVersionMismatch = {
playerName = playerName,
detail = detail,
sourceTag = sourceTag,
}
end
local window = self:EnsureVersionNoticeWindow()
if not window then
return
end
self:RefreshVersionNoticeWindow()
self:DevTrace("Version", "window_show", {
player = playerName,
source = sourceTag,
detail = detail,
})
window:Show()
window:Raise()
end