mirror of
https://github.com/Lacustat/Freewood-OctoWoW-Core.git
synced 2026-11-03 18:57:02 +00:00
0.1.227: Reiter Kanaele im Core (Kanaele und Mitglieder, Suche, Fluestern/Einladen/Ignorieren), Testbefehl /fwchans [ungeprueft]
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016onJCSHLwhs9udhC9ZLzk9
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
44ec52c0aa
commit
9d458c6659
@@ -0,0 +1,338 @@
|
||||
-- Freewood-OctoWoW-Core: Kanaele und ihre Mitglieder (nur lesen, alles UNGEPRUEFT im Spiel)
|
||||
-- Datenquelle: GetChannelList() + ListChannelByName(n) -> Ereignis CHAT_MSG_CHANNEL_LIST (arg1 = Namensliste).
|
||||
-- Alle Aufrufe laufen geschuetzt (pcall). /fwchans zeigt Rohdaten zur Pruefung.
|
||||
|
||||
local ADDON, FW = ...
|
||||
|
||||
local G = _G
|
||||
local Ch = {}
|
||||
FW.Channels = Ch
|
||||
|
||||
Ch.list = {} -- { {num=, name=, members={...}, count=, stamp=} }
|
||||
Ch.byNum = {}
|
||||
Ch.queue = {}
|
||||
Ch.current = nil
|
||||
Ch.lastSend = 0
|
||||
Ch.probe = false
|
||||
Ch.version = 0 -- steigt bei jeder Aenderung, die UI prueft das
|
||||
|
||||
local SPACING = 0.8 -- Sekunden zwischen zwei Abfragen
|
||||
local TIMEOUT = 4 -- Sekunden bis eine Abfrage als verloren gilt
|
||||
local SUPPRESS = 5 -- so lange nach einer Abfrage wird die Chatausgabe der Liste unterdrueckt
|
||||
|
||||
local function P(t)
|
||||
if G.DEFAULT_CHAT_FRAME then
|
||||
G.DEFAULT_CHAT_FRAME:AddMessage("|cff66ccffFWChans|r " .. tostring(t))
|
||||
end
|
||||
end
|
||||
|
||||
local function Short(s, n)
|
||||
s = tostring(s)
|
||||
n = n or 160
|
||||
if string.len(s) > n then return string.sub(s, 1, n) .. "..." end
|
||||
return s
|
||||
end
|
||||
|
||||
-- Kanalliste lesen: 1.12 liefert num, name, num, name ... (spaeter evtl. mit Zusatzwert)
|
||||
function Ch.ReadList()
|
||||
local out = {}
|
||||
if type(G.GetChannelList) ~= "function" then return out end
|
||||
local res = { pcall(G.GetChannelList) }
|
||||
if not res[1] then return out end
|
||||
local i = 2
|
||||
local n = table.getn(res)
|
||||
local lastNum
|
||||
while i <= n do
|
||||
local v = res[i]
|
||||
if type(v) == "number" then
|
||||
lastNum = v
|
||||
elseif type(v) == "string" and lastNum then
|
||||
out[table.getn(out) + 1] = { num = lastNum, name = v }
|
||||
lastNum = nil
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
-- eigenes Entfernen (table.remove zusammen mit table.getn verhaelt sich auf dem Client eigenartig)
|
||||
local function RemoveAt(t, idx)
|
||||
local n = table.getn(t)
|
||||
local k = idx
|
||||
while k < n do t[k] = t[k + 1]; k = k + 1 end
|
||||
t[n] = nil
|
||||
end
|
||||
|
||||
local function Bump() Ch.version = Ch.version + 1 end
|
||||
|
||||
-- Liste neu einlesen, bekannte Mitglieder behalten
|
||||
function Ch.Rescan()
|
||||
local fresh = Ch.ReadList()
|
||||
local old = Ch.byNum
|
||||
Ch.byNum = {}
|
||||
Ch.list = {}
|
||||
local k = 1
|
||||
while k <= table.getn(fresh) do
|
||||
local e = fresh[k]
|
||||
local prev = old[e.num]
|
||||
if prev and prev.name == e.name then
|
||||
e.members = prev.members
|
||||
e.count = prev.count
|
||||
e.stamp = prev.stamp
|
||||
else
|
||||
e.members = {}
|
||||
e.count = 0
|
||||
end
|
||||
Ch.byNum[e.num] = e
|
||||
Ch.list[table.getn(Ch.list) + 1] = e
|
||||
k = k + 1
|
||||
end
|
||||
Bump()
|
||||
end
|
||||
|
||||
-- Mitglieder aller Kanaele abfragen (nacheinander)
|
||||
function Ch.RefreshAll()
|
||||
Ch.Rescan()
|
||||
Ch.queue = {}
|
||||
local k = 1
|
||||
while k <= table.getn(Ch.list) do
|
||||
Ch.queue[table.getn(Ch.queue) + 1] = Ch.list[k].num
|
||||
k = k + 1
|
||||
end
|
||||
end
|
||||
|
||||
function Ch.RefreshOne(num)
|
||||
Ch.queue[table.getn(Ch.queue) + 1] = num
|
||||
end
|
||||
|
||||
function Ch.Pending()
|
||||
return table.getn(Ch.queue) + (Ch.current and 1 or 0)
|
||||
end
|
||||
|
||||
local function Send(num)
|
||||
Ch.current = num
|
||||
Ch.sentAt = (G.GetTime and G.GetTime()) or 0
|
||||
Ch.lastSend = Ch.sentAt
|
||||
local ok, err = pcall(G.ListChannelByName, num)
|
||||
if not ok and Ch.probe then P("ListChannelByName(" .. tostring(num) .. ") Fehler: " .. Short(err)) end
|
||||
end
|
||||
|
||||
local pump = CreateFrame("Frame")
|
||||
pump:SetScript("OnUpdate", function()
|
||||
local now = (G.GetTime and G.GetTime()) or 0
|
||||
if Ch.current and now - Ch.sentAt > TIMEOUT then
|
||||
Ch.current = nil
|
||||
Ch.timeouts = (Ch.timeouts or 0) + 1
|
||||
end
|
||||
if not Ch.current and table.getn(Ch.queue) > 0 and now - Ch.lastSend >= SPACING then
|
||||
local num = Ch.queue[1]
|
||||
RemoveAt(Ch.queue, 1)
|
||||
if Ch.byNum[num] then Send(num) end
|
||||
Bump()
|
||||
end
|
||||
end)
|
||||
|
||||
-- Namensliste aus arg1 zerlegen: "Name1, Name2*, Name3" -> Liste (Markierungen entfernt)
|
||||
function Ch.ParseNames(text)
|
||||
local out = {}
|
||||
if type(text) ~= "string" then return out end
|
||||
local rest = text
|
||||
-- evtl. Kopf "Players in channel ...:" abtrennen
|
||||
local pos = string.find(rest, ":", 1, true)
|
||||
if pos and pos < 60 and string.find(string.sub(rest, 1, pos), " ", 1, true) then
|
||||
rest = string.sub(rest, pos + 1)
|
||||
end
|
||||
local iter = string.gmatch or string.gfind
|
||||
for part in iter(rest, "[^,]+") do
|
||||
local name = string.gsub(part, "^%s+", "")
|
||||
name = string.gsub(name, "%s+$", "")
|
||||
name = string.gsub(name, "%*", "")
|
||||
name = string.gsub(name, "|c%x%x%x%x%x%x%x%x", "")
|
||||
name = string.gsub(name, "|r", "")
|
||||
if name ~= "" then out[table.getn(out) + 1] = name end
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
local function OnList(a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
||||
if Ch.probe then
|
||||
P("CHAT_MSG_CHANNEL_LIST arg1=" .. Short(a1) .. " | arg2=" .. tostring(a2) .. " arg4=" .. tostring(a4) ..
|
||||
" arg7=" .. tostring(a7) .. " arg8=" .. tostring(a8) .. " arg9=" .. tostring(a9))
|
||||
end
|
||||
local num = tonumber(a8)
|
||||
local e = num and Ch.byNum[num]
|
||||
if not e and Ch.current then e = Ch.byNum[Ch.current] end
|
||||
if not e and a9 then
|
||||
local k = 1
|
||||
while k <= table.getn(Ch.list) do
|
||||
if Ch.list[k].name == a9 then e = Ch.list[k] end
|
||||
k = k + 1
|
||||
end
|
||||
end
|
||||
if not e then return end
|
||||
e.members = Ch.ParseNames(a1)
|
||||
e.count = table.getn(e.members)
|
||||
e.stamp = (G.GetTime and G.GetTime()) or 0
|
||||
if Ch.current == e.num then Ch.current = nil end
|
||||
Bump()
|
||||
end
|
||||
|
||||
local function OnJoin(a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
||||
if Ch.probe then P("CHANNEL_JOIN arg2=" .. tostring(a2) .. " arg8=" .. tostring(a8) .. " arg9=" .. tostring(a9)) end
|
||||
local e = tonumber(a8) and Ch.byNum[tonumber(a8)]
|
||||
if e and type(a2) == "string" and a2 ~= "" then
|
||||
local k = 1
|
||||
while k <= table.getn(e.members) do
|
||||
if e.members[k] == a2 then return end
|
||||
k = k + 1
|
||||
end
|
||||
e.members[table.getn(e.members) + 1] = a2
|
||||
e.count = table.getn(e.members)
|
||||
Bump()
|
||||
end
|
||||
end
|
||||
|
||||
local function OnLeave(a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
||||
if Ch.probe then P("CHANNEL_LEAVE arg2=" .. tostring(a2) .. " arg8=" .. tostring(a8) .. " arg9=" .. tostring(a9)) end
|
||||
local e = tonumber(a8) and Ch.byNum[tonumber(a8)]
|
||||
if e and type(a2) == "string" then
|
||||
local k = 1
|
||||
while k <= table.getn(e.members) do
|
||||
if e.members[k] == a2 then
|
||||
RemoveAt(e.members, k)
|
||||
e.count = table.getn(e.members)
|
||||
Bump()
|
||||
return
|
||||
end
|
||||
k = k + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function OnNotice(a1, a2, a3, a4, a5, a6, a7, a8, a9)
|
||||
if Ch.probe then P("CHANNEL_NOTICE arg1=" .. tostring(a1) .. " arg4=" .. tostring(a4) .. " arg8=" .. tostring(a8) .. " arg9=" .. tostring(a9)) end
|
||||
if a1 == "YOU_JOINED" or a1 == "YOU_LEFT" or a1 == "YOU_CHANGED" then
|
||||
Ch.dirty = true
|
||||
end
|
||||
end
|
||||
|
||||
FW:RegisterEvent("CHAT_MSG_CHANNEL_LIST", OnList, Ch)
|
||||
FW:RegisterEvent("CHAT_MSG_CHANNEL_JOIN", OnJoin, Ch)
|
||||
FW:RegisterEvent("CHAT_MSG_CHANNEL_LEAVE", OnLeave, Ch)
|
||||
FW:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE", OnNotice, Ch)
|
||||
|
||||
-- Die Listenausgabe des Spiels soll nicht im Chat landen, solange wir selbst abfragen
|
||||
if type(G.ChatFrame_AddMessageEventFilter) == "function" then
|
||||
local function Hide()
|
||||
if Ch.probe then return false end
|
||||
local now = (G.GetTime and G.GetTime()) or 0
|
||||
if Ch.current or (now - Ch.lastSend) < SUPPRESS then return true end
|
||||
return false
|
||||
end
|
||||
pcall(G.ChatFrame_AddMessageEventFilter, "CHAT_MSG_CHANNEL_LIST", Hide)
|
||||
Ch.filter = true
|
||||
end
|
||||
|
||||
-- Aktionen (geschuetzt)
|
||||
function Ch.Whisper(name)
|
||||
if type(G.ChatFrame_SendTell) == "function" then pcall(G.ChatFrame_SendTell, name) end
|
||||
end
|
||||
function Ch.Invite(name)
|
||||
if type(G.InviteByName) == "function" then pcall(G.InviteByName, name)
|
||||
elseif type(G.InviteUnit) == "function" then pcall(G.InviteUnit, name) end
|
||||
end
|
||||
function Ch.Ignore(name)
|
||||
if type(G.AddIgnore) == "function" then pcall(G.AddIgnore, name) end
|
||||
end
|
||||
|
||||
-- Suche ueber alle Kanaele: Liste { {name=, chans={Kanalnamen}} } (Teiltreffer, ohne Gross/Klein)
|
||||
function Ch.Find(text, limit)
|
||||
local out = {}
|
||||
text = string.lower(text or "")
|
||||
if text == "" then return out end
|
||||
local byName = {}
|
||||
local k = 1
|
||||
while k <= table.getn(Ch.list) do
|
||||
local e = Ch.list[k]
|
||||
local m = 1
|
||||
while m <= table.getn(e.members) do
|
||||
local nm = e.members[m]
|
||||
if string.find(string.lower(nm), text, 1, true) then
|
||||
local r = byName[nm]
|
||||
if not r then
|
||||
if limit and table.getn(out) >= limit then
|
||||
Ch.moreFound = true
|
||||
else
|
||||
r = { name = nm, chans = {} }
|
||||
byName[nm] = r
|
||||
out[table.getn(out) + 1] = r
|
||||
end
|
||||
end
|
||||
if r then r.chans[table.getn(r.chans) + 1] = e.num .. ". " .. e.name end
|
||||
end
|
||||
m = m + 1
|
||||
end
|
||||
k = k + 1
|
||||
end
|
||||
table.sort(out, function(a, b) return a.name < b.name end)
|
||||
return out
|
||||
end
|
||||
|
||||
-- /fwchans [find <name>|probe|list]
|
||||
G.SLASH_FWCHANS1 = "/fwchans"
|
||||
G.SlashCmdList = G.SlashCmdList or {}
|
||||
G.SlashCmdList["FWCHANS"] = function(msg)
|
||||
msg = msg or ""
|
||||
local cmd, rest = string.match and string.match(msg, "^(%S*)%s*(.*)$")
|
||||
if not cmd then
|
||||
local _, _, c, r = string.find(msg, "^(%S*)%s*(.*)$")
|
||||
cmd, rest = c or "", r or ""
|
||||
end
|
||||
cmd = string.lower(cmd or "")
|
||||
if cmd == "find" then
|
||||
local res = Ch.Find(rest, 20)
|
||||
if table.getn(res) == 0 then P("keine Treffer (Mitglieder bekannt: " .. Ch.TotalMembers() .. ")") end
|
||||
local k = 1
|
||||
while k <= table.getn(res) do
|
||||
P(res[k].name .. ": " .. table.concat(res[k].chans, ", "))
|
||||
k = k + 1
|
||||
end
|
||||
return
|
||||
end
|
||||
if cmd == "list" then
|
||||
Ch.Rescan()
|
||||
local k = 1
|
||||
while k <= table.getn(Ch.list) do
|
||||
local e = Ch.list[k]
|
||||
P(e.num .. ". " .. e.name .. " - " .. e.count .. " Mitglieder" .. (e.stamp and "" or " (noch nicht abgefragt)"))
|
||||
k = k + 1
|
||||
end
|
||||
return
|
||||
end
|
||||
-- Standard: Rohdaten zeigen und Abfrage mit Rohausgabe starten
|
||||
Ch.probe = true
|
||||
local raw = { pcall(G.GetChannelList) }
|
||||
local parts = {}
|
||||
local i = 2
|
||||
while i <= table.getn(raw) do parts[table.getn(parts) + 1] = type(raw[i]) .. ":" .. tostring(raw[i]); i = i + 1 end
|
||||
P("GetChannelList: " .. table.concat(parts, " | "))
|
||||
P("Filter=" .. tostring(Ch.filter) .. " ListChannelByName=" .. type(G.ListChannelByName))
|
||||
Ch.RefreshAll()
|
||||
P("Abfrage laeuft (" .. Ch.Pending() .. " Kanaele). Rohdaten erscheinen unten. '/fwchans list' zeigt danach die Zahlen, '/fwchans find <Name>' sucht.")
|
||||
Ch.probeUntil = (G.GetTime and G.GetTime() or 0) + 60
|
||||
end
|
||||
|
||||
function Ch.TotalMembers()
|
||||
local n, k = 0, 1
|
||||
while k <= table.getn(Ch.list) do n = n + Ch.list[k].count; k = k + 1 end
|
||||
return n
|
||||
end
|
||||
|
||||
-- Rohausgabe nach 60 s wieder abschalten
|
||||
local off = CreateFrame("Frame")
|
||||
off:SetScript("OnUpdate", function()
|
||||
if Ch.probe and Ch.probeUntil and G.GetTime and G.GetTime() > Ch.probeUntil then
|
||||
Ch.probe = false
|
||||
P("Rohausgabe aus.")
|
||||
end
|
||||
end)
|
||||
@@ -3,7 +3,7 @@
|
||||
## Notes: Base addon of the Freewood family: data storage, UI kit, export/import and the main window.
|
||||
## Notes-deDE: Basis-Addon der Freewood-Familie: Datenspeicher, UI-Bausteine, Export/Import und Hauptfenster.
|
||||
## Author: Lacustat
|
||||
## Version: 0.1.226
|
||||
## Version: 0.1.227
|
||||
## SavedVariables: FreewoodDB
|
||||
## SavedVariablesPerCharacter: FreewoodCharDB
|
||||
|
||||
@@ -16,6 +16,8 @@ UI\Kit.lua
|
||||
UI\MainFrame.lua
|
||||
UI\MainWindow.lua
|
||||
UI\Tabs.lua
|
||||
Core\Channels.lua
|
||||
UI\ChannelsTab.lua
|
||||
Core\Tooltips.lua
|
||||
Core\TooltipInfo.lua
|
||||
Core\TooltipCompare.lua
|
||||
|
||||
+30
@@ -55,6 +55,21 @@ FW:AddLocale("enUS", {
|
||||
TAB_OVERVIEW = "Overview",
|
||||
TAB_EXCHANGE = "Exchange",
|
||||
TAB_SETTINGS = "Settings",
|
||||
TAB_CHANNELS = "Channels",
|
||||
CHAN_REFRESH = "Refresh",
|
||||
CHAN_SEARCH = "Find player in all channels...",
|
||||
CHAN_NONE = "You are not in any channel.",
|
||||
CHAN_MEMBERS = "%s members",
|
||||
CHAN_NOT_QUERIED = "not queried yet",
|
||||
CHAN_PENDING = "Querying %s channels...",
|
||||
CHAN_HIDDEN = "Freewood channel",
|
||||
CHAN_WHISPER = "Whisper",
|
||||
CHAN_INVITE = "Invite",
|
||||
CHAN_IGNORE = "Ignore",
|
||||
CHAN_SELECT = "Click a player for actions.",
|
||||
CHAN_NO_HITS = "No player found.",
|
||||
CHAN_MORE = "More hits than shown. Narrow the search.",
|
||||
CHAN_EMPTY_LIST = "No members received yet. Press Refresh.",
|
||||
|
||||
MONEY_G = "g",
|
||||
MONEY_S = "s",
|
||||
@@ -156,6 +171,21 @@ FW:AddLocale("deDE", {
|
||||
TAB_OVERVIEW = "Übersicht",
|
||||
TAB_EXCHANGE = "Austausch",
|
||||
TAB_SETTINGS = "Einstellungen",
|
||||
TAB_CHANNELS = "Kanäle",
|
||||
CHAN_REFRESH = "Aktualisieren",
|
||||
CHAN_SEARCH = "Spieler in allen Kanälen suchen...",
|
||||
CHAN_NONE = "Du bist in keinem Kanal.",
|
||||
CHAN_MEMBERS = "%s Mitglieder",
|
||||
CHAN_NOT_QUERIED = "noch nicht abgefragt",
|
||||
CHAN_PENDING = "Frage %s Kanäle ab...",
|
||||
CHAN_HIDDEN = "Freewood-Kanal",
|
||||
CHAN_WHISPER = "Flüstern",
|
||||
CHAN_INVITE = "Einladen",
|
||||
CHAN_IGNORE = "Ignorieren",
|
||||
CHAN_SELECT = "Spieler anklicken für Aktionen.",
|
||||
CHAN_NO_HITS = "Kein Spieler gefunden.",
|
||||
CHAN_MORE = "Mehr Treffer als angezeigt. Suche eingrenzen.",
|
||||
CHAN_EMPTY_LIST = "Noch keine Mitglieder empfangen. Aktualisieren drücken.",
|
||||
|
||||
MONEY_G = "G",
|
||||
MONEY_S = "S",
|
||||
|
||||
@@ -0,0 +1,226 @@
|
||||
-- Freewood-OctoWoW-Core: Reiter "Kanaele" (Chat-Kanaele und ihre Mitglieder). UNGEPRUEFT im Spiel.
|
||||
-- Links die Kanaele, rechts die Mitglieder des gewaehlten Kanals oder die Suchtreffer ueber alle Kanaele.
|
||||
|
||||
local ADDON, FW = ...
|
||||
|
||||
local UI = FW.UI
|
||||
local Ch = FW.Channels
|
||||
|
||||
local ROW = 20
|
||||
local MAX_ROWS = 300
|
||||
|
||||
local function MakeRows(holder)
|
||||
local rows = {}
|
||||
function rows.Get(i)
|
||||
local r = rows[i]
|
||||
if not r then
|
||||
r = CreateFrame("Button", nil, holder.child)
|
||||
r:SetHeight(ROW)
|
||||
r:SetPoint("TOPLEFT", holder.child, "TOPLEFT", 0, -(i - 1) * ROW)
|
||||
r:SetPoint("TOPRIGHT", holder.child, "TOPRIGHT", 0, -(i - 1) * ROW)
|
||||
r.sel = r:CreateTexture(nil, "BACKGROUND")
|
||||
r.sel:SetAllPoints()
|
||||
r.sel:SetColorTexture(UI.Color("bronze", 0.35))
|
||||
r.sel:Hide()
|
||||
r.hl = r:CreateTexture(nil, "HIGHLIGHT")
|
||||
r.hl:SetAllPoints()
|
||||
r.hl:SetColorTexture(UI.Color("gold", 0.15))
|
||||
r.text = UI.CreateLabel(r, "", { size = 12, justify = "LEFT" })
|
||||
r.text:SetPoint("LEFT", r, "LEFT", 6, 0)
|
||||
r.text:SetPoint("RIGHT", r, "RIGHT", -4, 0)
|
||||
rows[i] = r
|
||||
end
|
||||
return r
|
||||
end
|
||||
function rows.HideFrom(i)
|
||||
local k = i
|
||||
while rows[k] do rows[k]:Hide(); k = k + 1 end
|
||||
end
|
||||
return rows
|
||||
end
|
||||
|
||||
local function BuildChannels(content)
|
||||
local L = FW.L
|
||||
local f = CreateFrame("Frame", nil, content)
|
||||
f:SetAllPoints(content)
|
||||
|
||||
local selNum, selPlayer, seenVersion = nil, nil, -1
|
||||
local search = ""
|
||||
local lastAuto = 0
|
||||
|
||||
-- links: Kanalliste
|
||||
local title = UI.CreateLabel(f, L.TAB_CHANNELS, { font = "heading", size = 15, color = "gold" })
|
||||
title:SetPoint("TOPLEFT", f, "TOPLEFT", 0, 0)
|
||||
local refresh = UI.CreateButton(f, L.CHAN_REFRESH, 110, 24, function()
|
||||
Ch.RefreshAll()
|
||||
end)
|
||||
refresh:SetPoint("TOPLEFT", f, "TOPLEFT", 100, 2)
|
||||
local left = UI.CreateScrollFrame(f)
|
||||
left:SetPoint("TOPLEFT", f, "TOPLEFT", 0, -34)
|
||||
left:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 0, 0)
|
||||
left:SetWidth(220)
|
||||
local lrows = MakeRows(left)
|
||||
|
||||
-- rechts: Suche, Status, Mitglieder, Aktionsleiste
|
||||
local box = UI.CreatePanel(f, "bgDeep", "bronze")
|
||||
box:SetHeight(26)
|
||||
box:SetPoint("TOPLEFT", f, "TOPLEFT", 236, -2)
|
||||
box:SetPoint("TOPRIGHT", f, "TOPRIGHT", 0, -2)
|
||||
local edit = CreateFrame("EditBox", nil, box)
|
||||
edit:SetAutoFocus(false)
|
||||
edit:SetPoint("TOPLEFT", box, "TOPLEFT", 8, -2)
|
||||
edit:SetPoint("BOTTOMRIGHT", box, "BOTTOMRIGHT", -8, 2)
|
||||
edit:SetMaxLetters(40)
|
||||
if not edit:SetFont(UI.GetFontPath("body"), 12, "") then
|
||||
edit:SetFont("Fonts\\FRIZQT__.TTF", 12, "")
|
||||
end
|
||||
edit:SetTextColor(UI.Color("text"))
|
||||
edit:SetScript("OnEscapePressed", function(self) self:ClearFocus() end)
|
||||
local hint = UI.CreateLabel(box, L.CHAN_SEARCH, { size = 12, color = "textDim" })
|
||||
hint:SetPoint("LEFT", box, "LEFT", 10, 0)
|
||||
|
||||
local status = UI.CreateLabel(f, "", { size = 11, color = "textDim", justify = "LEFT" })
|
||||
status:SetPoint("TOPLEFT", f, "TOPLEFT", 236, -34)
|
||||
status:SetPoint("TOPRIGHT", f, "TOPRIGHT", 0, -34)
|
||||
|
||||
local right = UI.CreateScrollFrame(f)
|
||||
right:SetPoint("TOPLEFT", f, "TOPLEFT", 236, -54)
|
||||
right:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 36)
|
||||
local rrows = MakeRows(right)
|
||||
|
||||
local selLabel = UI.CreateLabel(f, L.CHAN_SELECT, { size = 12, color = "textDim", justify = "LEFT" })
|
||||
selLabel:SetPoint("BOTTOMLEFT", f, "BOTTOMLEFT", 236, 10)
|
||||
selLabel:SetWidth(200)
|
||||
local function Act(fn)
|
||||
return function() if selPlayer then fn(selPlayer) end end
|
||||
end
|
||||
local bW = UI.CreateButton(f, L.CHAN_WHISPER, 90, 24, Act(Ch.Whisper))
|
||||
local bI = UI.CreateButton(f, L.CHAN_INVITE, 90, 24, Act(Ch.Invite))
|
||||
local bG = UI.CreateButton(f, L.CHAN_IGNORE, 90, 24, Act(Ch.Ignore))
|
||||
bG:SetPoint("BOTTOMRIGHT", f, "BOTTOMRIGHT", 0, 4)
|
||||
bI:SetPoint("RIGHT", bG, "LEFT", -6, 0)
|
||||
bW:SetPoint("RIGHT", bI, "LEFT", -6, 0)
|
||||
|
||||
local function Redraw()
|
||||
seenVersion = Ch.version
|
||||
-- Kanalliste
|
||||
local n = table.getn(Ch.list)
|
||||
local k = 1
|
||||
while k <= n do
|
||||
local e = Ch.list[k]
|
||||
local r = lrows.Get(k)
|
||||
local num = e.num
|
||||
r.text:SetText(e.num .. ". " .. e.name .. " |cff8c8a84(" .. (e.stamp and e.count or "?") .. ")|r")
|
||||
if num == selNum then r.sel:Show() else r.sel:Hide() end
|
||||
r:SetScript("OnClick", function()
|
||||
selNum = num
|
||||
selPlayer = nil
|
||||
Redraw()
|
||||
end)
|
||||
r:Show()
|
||||
k = k + 1
|
||||
end
|
||||
lrows.HideFrom(n + 1)
|
||||
left:SetContentHeight(math.max(1, n * ROW))
|
||||
|
||||
-- rechts
|
||||
local items = {} -- { name=, extra= }
|
||||
if search ~= "" then
|
||||
local hits = Ch.Find(search, MAX_ROWS)
|
||||
local h = 1
|
||||
while h <= table.getn(hits) do
|
||||
items[h] = { name = hits[h].name, extra = table.concat(hits[h].chans, ", ") }
|
||||
h = h + 1
|
||||
end
|
||||
if table.getn(items) == 0 then
|
||||
status:SetText(L.CHAN_NO_HITS)
|
||||
elseif Ch.moreFound then
|
||||
status:SetText(L.CHAN_MORE)
|
||||
else
|
||||
status:SetText("")
|
||||
end
|
||||
Ch.moreFound = nil
|
||||
else
|
||||
local e = selNum and Ch.byNum[selNum]
|
||||
if n == 0 then
|
||||
status:SetText(L.CHAN_NONE)
|
||||
elseif not e then
|
||||
status:SetText(L.CHAN_SELECT)
|
||||
else
|
||||
local txt = e.num .. ". " .. e.name
|
||||
if e.stamp then
|
||||
txt = txt .. " - " .. string.format(L.CHAN_MEMBERS, tostring(e.count))
|
||||
else
|
||||
txt = txt .. " - " .. L.CHAN_NOT_QUERIED
|
||||
end
|
||||
if string.find(e.name, "^Freewood") then txt = txt .. " (" .. L.CHAN_HIDDEN .. ")" end
|
||||
local pend = Ch.Pending()
|
||||
if pend > 0 then txt = txt .. " - " .. string.format(L.CHAN_PENDING, tostring(pend)) end
|
||||
status:SetText(txt)
|
||||
local m = 1
|
||||
while m <= table.getn(e.members) and m <= MAX_ROWS do
|
||||
items[m] = { name = e.members[m] }
|
||||
m = m + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
local cnt = table.getn(items)
|
||||
local i = 1
|
||||
while i <= cnt do
|
||||
local it = items[i]
|
||||
local r = rrows.Get(i)
|
||||
local nm = it.name
|
||||
if it.extra then
|
||||
r.text:SetText(nm .. " |cff8c8a84" .. it.extra .. "|r")
|
||||
else
|
||||
r.text:SetText(nm)
|
||||
end
|
||||
if nm == selPlayer then r.sel:Show() else r.sel:Hide() end
|
||||
r:SetScript("OnClick", function()
|
||||
selPlayer = nm
|
||||
selLabel:SetText(nm)
|
||||
Redraw()
|
||||
end)
|
||||
r:Show()
|
||||
i = i + 1
|
||||
end
|
||||
rrows.HideFrom(cnt + 1)
|
||||
right:SetContentHeight(math.max(1, cnt * ROW))
|
||||
end
|
||||
|
||||
edit:SetScript("OnTextChanged", function(self)
|
||||
search = self:GetText() or ""
|
||||
if search == "" then hint:Show() else hint:Hide() end
|
||||
right:ScrollToTop()
|
||||
Redraw()
|
||||
end)
|
||||
|
||||
f.Refresh = function()
|
||||
if Ch.dirty or table.getn(Ch.list) == 0 then
|
||||
Ch.dirty = nil
|
||||
Ch.RefreshAll()
|
||||
else
|
||||
Ch.Rescan()
|
||||
end
|
||||
if not selNum and Ch.list[1] then selNum = Ch.list[1].num end
|
||||
Redraw()
|
||||
end
|
||||
|
||||
-- Aenderungen der Datenschicht nachziehen (hoechstens 2x pro Sekunde)
|
||||
local acc = 0
|
||||
f:SetScript("OnUpdate", function(_, el)
|
||||
acc = acc + (el or arg1 or 0)
|
||||
if acc < 0.5 then return end
|
||||
acc = 0
|
||||
if f:IsShown() and seenVersion ~= Ch.version then Redraw() end
|
||||
end)
|
||||
|
||||
return f
|
||||
end
|
||||
|
||||
UI:RegisterTab("channels", {
|
||||
label = function() return FW.L.TAB_CHANNELS end,
|
||||
order = 115,
|
||||
build = BuildChannels,
|
||||
onShow = function(f) f.Refresh() end,
|
||||
})
|
||||
Reference in New Issue
Block a user