home · contact · privacy
Show received nickname changes in all windows affected.
authorChristian Heller <c.heller@plomlompom.de>
Fri, 5 Sep 2025 11:50:30 +0000 (13:50 +0200)
committerChristian Heller <c.heller@plomlompom.de>
Fri, 5 Sep 2025 11:50:30 +0000 (13:50 +0200)
ircplom/client.py
ircplom/client_tui.py

index e26dd0a1460f4fa248ad9f574977a930a84c07cb..e11b1e773ac60cfe91010aa284d7d68b709a53a2 100644 (file)
@@ -286,6 +286,7 @@ class LogScope(Enum):
     SERVER = auto()
     RAW = auto()
     CHAT = auto()
+    NICKNAME = auto()
     SAME = auto()
 
 
index ae0da1208c5cda8bd922d8c8d7d34f27c5d6de96..0b14b9c5e7eca18dea990b5dd04f4604bba35d4d 100644 (file)
@@ -80,6 +80,10 @@ class _UpdatingNode(AutoAttrMixin):
 
 class _UpdatingDict(Dict[DictItem], _UpdatingNode):
 
+    def items(self) -> tuple[tuple[str, DictItem], ...]:
+        'Key-value pairs of item registrations.'
+        return tuple((k, v) for k, v in self._dict.items())
+
     def _get(self, key: str):
         if key not in self._dict:
             self._dict[key] = self._item_cls()
@@ -210,12 +214,23 @@ class _UpdatingChannel(_UpdatingNode):
         if super().set_and_check_for_change(update):
             if update.path == ('topic',):
                 msg = f'raw:{self.topic.who} set topic to: {self.topic.what}'
-            return (self._scope(update.path), msg)
+            return self._scope(update.path), msg
         return None
 
 
 class _UpdatingNickUserHost(_UpdatingNode, NickUserHost):
-    pass
+    log_scopes = {('nick',): LogScope.NICKNAME}
+    prev_nick = '?'
+
+    @property
+    def prev(self) -> str:
+        'Return .nickuserhost with .prev_nick as .nick.'
+        return str(NickUserHost(self.prev_nick, self.user, self.host))
+
+    def __setattr__(self, key: str, value) -> None:
+        if key == 'nick':
+            self.prev_nick = self.nick
+        super().__setattr__(key, value)
 
 
 class _UpdatingServerCapability(_UpdatingNode, ServerCapability):
@@ -266,6 +281,21 @@ class _ClientWindowsManager:
             return win
         return self._new_win(scope=scope, chatname=chatname)
 
+    def windows_for_userid(self, user_id: str) -> list[_ClientWindow]:
+        'Return windows interacting with userid (all if "me").'
+        if user_id == 'me':
+            return self.windows[:]
+        chan_names = [c for c, v in self.db.channels.items()
+                      if user_id in v.user_ids]
+        return [w for w in self.windows
+                if isinstance(w, _ChatWindow)
+                and ((isinstance(w, _ChannelWindow)
+                      and w.chatname in chan_names)
+                     or (not isinstance(w, _ChannelWindow)
+                         and w.chatname in {
+                             self.db.users[user_id].nick,
+                             self.db.users[user_id].prev_nick}))]
+
     def log(self, msg: str, scope: LogScope, **kwargs) -> None:
         'From parsing scope, kwargs, build prefix before sending to logger.'
         first_char = '$'
@@ -294,10 +324,13 @@ class _ClientWindowsManager:
         scope, value = result
         log_path = ':'.join(update.path)
         log_kwargs: dict[str, Any] = {'scope': scope}
-        if scope is LogScope.CHAT:
+        if scope in {LogScope.CHAT, LogScope.NICKNAME}:
             log_kwargs |= {'target': update.path[1]}
         if value is None:
             self.log(f'{log_path} cleared', **log_kwargs)
+        elif scope is LogScope.NICKNAME:
+            self.log(f'{self.db.users[update.path[1]].prev} renames {value}',
+                     **log_kwargs)
         elif isinstance(value, dict):
             for verb, item in [(k, v) for k, v in value.items() if v]:
                 toks = verb.split(':', maxsplit=1)
@@ -344,6 +377,8 @@ class ClientTui(BaseTui):
                             if kwargs['target'] != m.db.users['me'].nick
                             else kwargs['sender'])
                 return [m.window(LogScope.CHAT, chatname=chatname)]
+            if scope == LogScope.NICKNAME:
+                return m.windows_for_userid(kwargs['target'])
             return [m.window(scope)]
         return super()._log_target_wins(**kwargs)