Daniel Brötzmann pushed to branch newcontrol at gajim / gajim
Commits: bcb64411 by wurstsalat at 2022-07-08T18:24:17+02:00 Adapt ChatActionProcessor and GroupChatNickCompletion
- - - - -
5 changed files:
- gajim/gtk/chat_action_processor.py - gajim/gtk/groupchat_nick_completion.py - gajim/gtk/message_actions_box.py - gajim/gtk/message_input.py - test/no_gui/test_nick_completion.py
Changes:
===================================== gajim/gtk/chat_action_processor.py ===================================== @@ -38,11 +38,7 @@
class ChatActionProcessor(Gtk.Popover): - def __init__(self, - account: str, - contact: types.ChatContactT, - message_input: MessageInputTextView - ) -> None: + def __init__(self, message_input: MessageInputTextView) -> None: Gtk.Popover.__init__(self) self._menu = Gio.Menu() self.bind_model(self._menu) @@ -53,23 +49,28 @@ def __init__(self, self.connect('closed', self._on_popover_closed) self.connect('destroy', self._on_destroy)
+ self._account: Optional[str] = None + self._contact: Optional[types.ChatContactT] = None + self._message_input = message_input self._message_input.connect('key-press-event', self._on_key_press)
self._buf = message_input.get_buffer() self._buf.connect('changed', self._on_changed)
- self._nick_completion: Optional[GroupChatNickCompletion] = None - if contact.is_groupchat: - assert isinstance(contact, GroupchatContact) - self._nick_completion = GroupChatNickCompletion( - account, contact, message_input) + self._nick_completion = GroupChatNickCompletion()
self._start_mark: Optional[Gtk.TextMark] = None self._current_iter: Optional[Gtk.TextIter] = None
self._active = False
+ def switch_contact(self, contact: types.ChatContactT) -> None: + self._account = contact.account + self._contact = contact + if isinstance(contact, GroupchatContact): + self._nick_completion.switch_contact(contact) + def _on_destroy(self, _popover: Gtk.Popover) -> None: app.check_finalize(self)
@@ -77,7 +78,7 @@ def _on_key_press(self, textview: MessageInputTextView, event: Gdk.EventKey ) -> bool: - if self._nick_completion is not None: + if isinstance(self._contact, GroupchatContact): res = self._nick_completion.process_key_press(textview, event) if res: return True @@ -122,8 +123,9 @@ def _replace_text(self, selected_action: str) -> None:
def _get_commands(self) -> list[str]: commands: list[str] = [] - control = app.window.get_control( - self._message_input.account, self._message_input.contact.jid) + assert self._account + assert self._contact + control = app.window.get_control(self._account, self._contact.jid) assert control is not None for command in control.list_commands(): for name in command.names: @@ -325,6 +327,9 @@ def _item_has_focus(item: Gtk.ModelButton) -> bool: flags = item.get_state_flags() return 'GTK_STATE_FLAG_FOCUSED' in str(flags)
- def process_outgoing_message(self, contact: str, highlight: bool) -> None: - if self._nick_completion is not None: - self._nick_completion.record_message(contact, highlight) + def process_outgoing_message(self, + contact_name: str, + highlight: bool + ) -> None: + if isinstance(self._contact, GroupchatContact): + self._nick_completion.process_message(contact_name, highlight)
===================================== gajim/gtk/groupchat_nick_completion.py ===================================== @@ -14,6 +14,7 @@
from __future__ import annotations
+from typing import Optional from typing import TYPE_CHECKING
import logging @@ -33,22 +34,38 @@
class GroupChatNickCompletion: - def __init__(self, - account: str, - contact: types.GroupchatContactT, - message_input: MessageInputTextView - ) -> None: - self._account = account - - self._contact = contact - self._contact.connect( - 'user-nickname-changed', self._on_user_nickname_changed) + def __init__(self) -> None: + self._account: Optional[str] = None + self._contact: Optional[types.GroupchatContactT] = None
self._sender_list: list[str] = [] - self._attention_list: list[str] = [] + self._highlight_list: list[str] = [] self._nick_hits: list[str] = [] self._last_key_tab = False
+ self._nick_data: dict[str, tuple[list[str], list[str]]] = {} + + def switch_contact(self, contact: types.GroupchatContactT) -> None: + self._nick_hits.clear() + self._last_key_tab = False + + if self._contact is not None: + self._contact.disconnect_all_from_obj(self) + self._nick_data[str(self._contact.jid)] = ( + self._sender_list, self._highlight_list) + + nick_data = self._nick_data.get(str(contact.jid)) + if nick_data is None: + self._sender_list.clear() + self._highlight_list.clear() + else: + self._sender_list, self._highlight_list = nick_data + + self._account = contact.account + self._contact = contact + self._contact.connect( + 'user-nickname-changed', self._on_user_nickname_changed) + def _on_user_nickname_changed(self, _contact: types.GroupchatContact, _signal_name: str, @@ -63,12 +80,13 @@ def _on_user_nickname_changed(self, new_name = properties.muc_user.nick assert new_name is not None log.debug('Contact %s renamed to %s', old_name, new_name) - for lst in (self._attention_list, self._sender_list): + for lst in (self._highlight_list, self._sender_list): for idx, contact in enumerate(lst): if contact == old_name: lst[idx] = new_name
- def record_message(self, contact_name: str, highlight: bool) -> None: + def process_message(self, contact_name: str, highlight: bool) -> None: + assert self._contact if contact_name == self._contact.nickname: return
@@ -78,12 +96,12 @@ def record_message(self, contact_name: str, highlight: bool) -> None:
if highlight: try: - self._attention_list.remove(contact_name) + self._highlight_list.remove(contact_name) except ValueError: pass - if len(self._attention_list) > 6: - self._attention_list.pop(0) # remove older - self._attention_list.append(contact_name) + if len(self._highlight_list) > 6: + self._highlight_list.pop(0) # remove older + self._highlight_list.append(contact_name)
# TODO implement it in a more efficient way # Currently it's O(n*m + n*s), where n is the number of participants and @@ -111,12 +129,13 @@ def _generate_suggestions(self, `beginning` is the text already typed by the user """ def _nick_matching(nick: str) -> bool: + assert self._contact return (nick != self._contact.nickname and nick.lower().startswith(beginning.lower()))
if beginning == '': # empty message, so just suggest recent mentions - potential_matches = self._attention_list + potential_matches = self._highlight_list else: # nick partially typed, try completing it potential_matches = self._sender_list @@ -179,6 +198,7 @@ def process_key_press(self, self._nick_hits.append(self._nick_hits[0]) begin = self._nick_hits.pop(0) else: + assert self._contact list_nick = self._contact.get_user_nicknames() list_nick = list(filter(self._jid_not_blocked, list_nick))
@@ -215,6 +235,7 @@ def process_key_press(self, else: start_iter.backward_chars(len(begin))
+ assert self._account client = app.get_client(self._account) client.get_module('Chatstate').block_chatstates( self._contact, True) @@ -255,6 +276,8 @@ def process_key_press(self, return True
def _jid_not_blocked(self, resource: str) -> bool: + assert self._account + assert self._contact resource_contact = self._contact.get_resource(resource) return not jid_is_blocked( self._account, str(resource_contact.jid))
===================================== gajim/gtk/message_actions_box.py ===================================== @@ -173,6 +173,7 @@ def switch_contact(self, contact: ChatContactT) -> None: self._set_spell_checker_language(contact) self._set_chatstate()
+ self.msg_textview.switch_contact(contact) self._security_label_selector.switch_contact(contact)
def _set_chatstate(self) -> None:
===================================== gajim/gtk/message_input.py ===================================== @@ -57,9 +57,6 @@ class MessageInputTextView(Gtk.TextView): """ def __init__(self) -> None: Gtk.TextView.__init__(self) - # self.account = account - # self.contact = contact - self.set_border_width(3) self.set_accepts_tab(True) self.set_editable(True) @@ -76,8 +73,7 @@ def __init__(self) -> None: self._undo_list: list[str] = [] self.undo_pressed: bool = False
- # self._chat_action_processor = ChatActionProcessor( - # account, contact, self) + self._chat_action_processor = ChatActionProcessor(self)
self.get_buffer().create_tag('strong', weight=Pango.Weight.BOLD) self.get_buffer().create_tag('emphasis', style=Pango.Style.ITALIC) @@ -91,6 +87,9 @@ def __init__(self) -> None: self.connect('destroy', self._on_destroy) self.connect('populate-popup', self._on_populate_popup)
+ def switch_contact(self, contact: ChatContactT) -> None: + self._chat_action_processor.switch_contact(contact) + def _on_destroy(self, _widget: Gtk.Widget) -> None: # We restore the TextView’s drag destination to avoid a GTK warning # when closing the control. BaseControl.shutdown() calls destroy() @@ -323,9 +322,8 @@ def process_outgoing_message(self, contact_name: str, highlight: bool ) -> None: - # self._chat_action_processor.process_outgoing_message( - # contact_name, highlight) - pass + self._chat_action_processor.process_outgoing_message( + contact_name, highlight)
def _on_populate_popup(self, _textview: MessageInputTextView,
===================================== test/no_gui/test_nick_completion.py ===================================== @@ -10,13 +10,12 @@ class Test(unittest.TestCase):
def test_generate_suggestions(self): - contact = MagicMock() message_input = MagicMock() - gen = GroupChatNickCompletion('testacc', contact, message_input) + gen = GroupChatNickCompletion(message_input)
l = ['aaaa', 'fooo', 'xxxxz', 'xaaaz'] for n in l: - gen.record_message(n, False) + gen.process_message(n, False) l2 = ['xxx'] + l r = gen._generate_suggestions(nicks=l2, beginning='x') self.assertEqual(r, ['xaaaz', 'xxxxz', 'xxx']) @@ -28,7 +27,7 @@ def test_generate_suggestions(self): self.assertEqual(r, [])
for n in ['xaaaz', 'xxxxz']: - gen.record_message(n, True) + gen.process_message(n, True)
r = gen._generate_suggestions( nicks=l2,
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/commit/bcb6441175405bf4b71b05326946ff6f2...