irc: channel-aware membership; scope QUIT/NOTICE to relevant buffers; update titlebar reliably

Signed-off-by: Slendi <slendi@socopon.com>
This commit is contained in:
2025-09-20 01:43:11 +03:00
parent 8aae63b93d
commit a7a8a19d9c

View File

@@ -95,6 +95,12 @@ function IrcChatView:ensureBuffer(target)
if self._unread[target] == nil then
self._unread[target] = 0
end
if target:sub(1,1) == "#" then
self._members = self._members or {}
if not self._members[target] then
self._members[target] = {}
end
end
end
function IrcChatView:switchTarget(target)
@@ -335,6 +341,11 @@ function IrcChatView:handleLine(line)
local nick = prefix:match("^([^!]+)!") or prefix
if target:sub(1,1) == "#" then
self:appendLine(string.format("<%s> %s", nick, msg), target)
-- track speaker as member
self:ensureBuffer(target)
self._members = self._members or {}
self._members[target] = self._members[target] or {}
self._members[target][nick] = true
else
-- PM to us
self:appendLine(string.format("[%s -> you] %s", nick, msg), nick)
@@ -345,7 +356,8 @@ function IrcChatView:handleLine(line)
local target, msg = rest:match("^(%S+)%s+:(.+)$")
if msg then
local nick = prefix and (prefix:match("^([^!]+)!") or prefix) or "*"
self:appendLine(string.format("-%s- %s", nick, msg))
local tgt = (target and target:sub(1,1) == "#") and target or nil
self:appendLine(string.format("-%s- %s", nick, msg), tgt)
return
end
elseif command == "JOIN" then
@@ -359,6 +371,10 @@ function IrcChatView:handleLine(line)
self:switchTarget(ch)
end
end
self:ensureBuffer(ch)
self._members = self._members or {}
self._members[ch] = self._members[ch] or {}
self._members[ch][nick] = true
end
return
elseif command == "PART" then
@@ -366,16 +382,36 @@ function IrcChatView:handleLine(line)
local ch, msg = rest:match("^(%S+)%s*:?(.*)$")
if ch then
self:appendLine(string.format("* %s left %s %s", nick, ch, msg or ""), ch)
if self._members and self._members[ch] then
self._members[ch][nick] = nil
end
end
return
elseif command == "QUIT" then
local nick = prefix:match("^([^!]+)!") or prefix
local msg = rest:match("^:(.+)$") or ""
self:appendLine(string.format("* %s quit %s", nick, msg))
local shown = false
if self._members then
for ch, set in pairs(self._members) do
if set[nick] then
self:appendLine(string.format("* %s quit %s", nick, msg), ch)
set[nick] = nil
shown = true
end
end
end
-- If not shown anywhere, drop it to avoid cross-channel noise
return
elseif command == "353" then -- RPL_NAMREPLY
local nickmode, chan, names = rest:match("^(%S+)%s+=%s+(%S+)%s+:(.+)$")
if names then
self:ensureBuffer(chan)
self._members = self._members or {}
self._members[chan] = self._members[chan] or {}
for name in names:gmatch("%S+") do
local clean = name:gsub("^[~&@%+%%]", "")
self._members[chan][clean] = true
end
self:appendLine(T(_("Users: %1"), names), chan)
end
return
@@ -392,6 +428,22 @@ function IrcChatView:handleLine(line)
self:sendRaw(string.format("JOIN %s\r\n", self._pending_join))
end
return
elseif command == "NICK" then -- self or others changed nick
local newnick = rest:match("^:(.+)$") or rest
local oldnick = prefix:match("^([^!]+)!") or prefix
if oldnick == self._nick and newnick and #newnick > 0 then
self._nick = newnick
self:appendLine(T(_("You are now known as %1"), newnick))
end
if self._members and newnick and #newnick > 0 then
for ch, set in pairs(self._members) do
if set[oldnick] then
set[oldnick] = nil
set[newnick] = true
end
end
end
return
elseif command == "NICK" then -- someone changed nick; update ours if it's us
local newnick = rest:match("^:(.+)$") or rest
local oldnick = prefix:match("^([^!]+)!") or prefix