Philipp Hörist pushed to branch master at gajim / gajim
Commits:
-
fa21ba4d
by wurstsalat at 2023-05-14T14:42:34+00:00
-
5784aa4a
by wurstsalat at 2023-05-14T14:42:34+00:00
-
16618479
by wurstsalat at 2023-05-14T14:42:34+00:00
5 changed files:
- gajim/common/storage/archive.py
- gajim/gtk/control.py
- gajim/gtk/conversation/view.py
- test/dialogs/__init__.py
- + test/dialogs/conversation_view.py
Changes:
| ... | ... | @@ -162,10 +162,11 @@ class MessageExportRow(NamedTuple): |
| 162 | 162 | |
| 163 | 163 | |
| 164 | 164 | class MessageArchiveStorage(SqliteStorage):
|
| 165 | - def __init__(self):
|
|
| 165 | + def __init__(self, in_memory: bool = False):
|
|
| 166 | + path = None if in_memory else configpaths.get('LOG_DB')
|
|
| 166 | 167 | SqliteStorage.__init__(self,
|
| 167 | 168 | log,
|
| 168 | - configpaths.get('LOG_DB'),
|
|
| 169 | + path,
|
|
| 169 | 170 | ARCHIVE_SQL_STATEMENT)
|
| 170 | 171 | |
| 171 | 172 | self._jid_ids: dict[JID, JidsTableRow] = {}
|
| ... | ... | @@ -456,7 +457,7 @@ def get_conversation_around(self, |
| 456 | 457 | jids = [jid]
|
| 457 | 458 | account_id = self.get_account_id(account)
|
| 458 | 459 | kinds = map(str, [KindConstant.ERROR])
|
| 459 | - n_lines = 20
|
|
| 460 | + n_lines = 50
|
|
| 460 | 461 | |
| 461 | 462 | sql_before = '''
|
| 462 | 463 | SELECT contact_name, time, kind, show, message, subject,
|
| ... | ... | @@ -161,6 +161,7 @@ def switch_contact(self, contact: Union[BareContact, |
| 161 | 161 | |
| 162 | 162 | self._jump_to_end_button.switch_contact(contact)
|
| 163 | 163 | self._scrolled_view.switch_contact(contact)
|
| 164 | + self._request_history(None, True)
|
|
| 164 | 165 | self._groupchat_state.switch_contact(contact)
|
| 165 | 166 | self._roster.switch_contact(contact)
|
| 166 | 167 | |
| ... | ... | @@ -590,17 +591,18 @@ def scroll_to_message(self, log_line_id: int, timestamp: float) -> None: |
| 590 | 591 | row = self._scrolled_view.get_row_by_log_line_id(log_line_id)
|
| 591 | 592 | if row is None:
|
| 592 | 593 | # Clear view and reload conversation around timestamp
|
| 594 | + self._scrolled_view.reset()
|
|
| 593 | 595 | self._scrolled_view.block_signals(True)
|
| 594 | - self.reset_view()
|
|
| 595 | 596 | before, at_after = app.storage.archive.get_conversation_around(
|
| 596 | 597 | self.contact.account, self.contact.jid, timestamp)
|
| 597 | 598 | self.add_messages(before)
|
| 598 | 599 | self.add_messages(at_after)
|
| 600 | + self._scrolled_view.set_history_complete(False, False)
|
|
| 599 | 601 | |
| 602 | + GLib.idle_add(self._scrolled_view.block_signals, False)
|
|
| 600 | 603 | GLib.idle_add(
|
| 601 | 604 | self._scrolled_view.scroll_to_message_and_highlight,
|
| 602 | 605 | log_line_id)
|
| 603 | - GLib.idle_add(self._scrolled_view.block_signals, False)
|
|
| 604 | 606 | |
| 605 | 607 | def _request_messages(self, before: bool) -> list[ConversationRow]:
|
| 606 | 608 | if before:
|
| ... | ... | @@ -638,7 +640,7 @@ def _request_events(self, before: bool) -> list[events.ApplicationEvent]: |
| 638 | 640 | REQUEST_LINES_COUNT)
|
| 639 | 641 | |
| 640 | 642 | def _request_history(self,
|
| 641 | - _scrolled: Gtk.ScrolledWindow,
|
|
| 643 | + _widget: Any,
|
|
| 642 | 644 | before: bool
|
| 643 | 645 | ) -> None:
|
| 644 | 646 |
| ... | ... | @@ -244,7 +244,6 @@ def switch_contact(self, contact: ChatContactT) -> None: |
| 244 | 244 | |
| 245 | 245 | self._block_signals = False
|
| 246 | 246 | self._enable_signal_handlers(True)
|
| 247 | - self._emit('request-history', True)
|
|
| 248 | 247 | |
| 249 | 248 | def get_autoscroll(self) -> bool:
|
| 250 | 249 | return self._autoscroll
|
| ... | ... | @@ -3,12 +3,13 @@ |
| 3 | 3 | |
| 4 | 4 | def require_versions():
|
| 5 | 5 | gi.require_versions({'Gdk': '3.0',
|
| 6 | - 'GLib': '2.0',
|
|
| 7 | 6 | 'Gio': '2.0',
|
| 7 | + 'GLib': '2.0',
|
|
| 8 | + 'GObject': '2.0',
|
|
| 8 | 9 | 'Gtk': '3.0',
|
| 9 | 10 | 'GtkSource': '4',
|
| 10 | - 'GObject': '2.0',
|
|
| 11 | - 'Pango': '1.0'})
|
|
| 11 | + 'Pango': '1.0',
|
|
| 12 | + 'PangoCairo': '1.0'})
|
|
| 12 | 13 | |
| 13 | 14 | |
| 14 | 15 | require_versions() |
| 1 | +import tempfile
|
|
| 2 | +from unittest.mock import MagicMock
|
|
| 3 | + |
|
| 4 | +from gi.repository import Gdk
|
|
| 5 | +from gi.repository import Gtk
|
|
| 6 | +from nbxmpp.protocol import JID
|
|
| 7 | + |
|
| 8 | +from gajim.common import app
|
|
| 9 | +from gajim.common import configpaths
|
|
| 10 | +from gajim.common.const import AvatarSize
|
|
| 11 | +from gajim.common.const import KindConstant
|
|
| 12 | +from gajim.common.modules.contacts import BareContact
|
|
| 13 | +from gajim.common.modules.contacts import ContactSettings
|
|
| 14 | +from gajim.common.preview import PreviewManager
|
|
| 15 | +from gajim.common.settings import Settings
|
|
| 16 | +from gajim.common.storage.archive import MessageArchiveStorage
|
|
| 17 | +from gajim.common.storage.events import EventStorage
|
|
| 18 | + |
|
| 19 | +from gajim.gtk.avatar import generate_default_avatar
|
|
| 20 | +from gajim.gtk.control import ChatControl
|
|
| 21 | + |
|
| 22 | +ACCOUNT = 'me@test.tld'
|
|
| 23 | +FROM_JID = 'contact@test.tld'
|
|
| 24 | +BASE_TIMESTAMP = 1672531200
|
|
| 25 | + |
|
| 26 | + |
|
| 27 | +class ConversationViewTest(Gtk.ApplicationWindow):
|
|
| 28 | + def __init__(self) -> None:
|
|
| 29 | + Gtk.ApplicationWindow.__init__(self)
|
|
| 30 | + self.set_position(Gtk.WindowPosition.CENTER)
|
|
| 31 | + self.set_size_request(800, 800)
|
|
| 32 | + self.set_title('Test ConversationView')
|
|
| 33 | + |
|
| 34 | + self._chat_control = ChatControl()
|
|
| 35 | + app.settings.set('hide_groupchat_occupants_list', True)
|
|
| 36 | + |
|
| 37 | + contact = self._get_contact()
|
|
| 38 | + self._chat_control.switch_contact(contact)
|
|
| 39 | + |
|
| 40 | + jump_to_button = Gtk.Button(label='Jump to 500')
|
|
| 41 | + jump_to_button.connect('clicked', self._on_jump_to_clicked)
|
|
| 42 | + button_box = Gtk.Box(
|
|
| 43 | + spacing=6,
|
|
| 44 | + halign=Gtk.Align.CENTER,
|
|
| 45 | + margin_bottom=6)
|
|
| 46 | + button_box.add(jump_to_button)
|
|
| 47 | + |
|
| 48 | + box = Gtk.Box(spacing=6, orientation=Gtk.Orientation.VERTICAL)
|
|
| 49 | + box.add(self._chat_control.widget)
|
|
| 50 | + box.add(button_box)
|
|
| 51 | + self.add(box)
|
|
| 52 | + |
|
| 53 | + self.show_all()
|
|
| 54 | + self.connect('key-press-event', self._on_key_press_event)
|
|
| 55 | + |
|
| 56 | + def _get_contact(self) -> BareContact:
|
|
| 57 | + contact = MagicMock(spec='BareContact')
|
|
| 58 | + contact.connect = MagicMock()
|
|
| 59 | + contact.account = ACCOUNT
|
|
| 60 | + contact.jid = FROM_JID
|
|
| 61 | + contact.name = 'Test Contact'
|
|
| 62 | + contact.is_groupchat = False
|
|
| 63 | + avatar = generate_default_avatar(
|
|
| 64 | + 'T',
|
|
| 65 | + (0.2, 0.1, 0.7),
|
|
| 66 | + AvatarSize.ROSTER,
|
|
| 67 | + 1)
|
|
| 68 | + contact.get_avatar = MagicMock(return_value=avatar)
|
|
| 69 | + contact.settings = ContactSettings(ACCOUNT, JID.from_string(ACCOUNT))
|
|
| 70 | + return contact
|
|
| 71 | + |
|
| 72 | + def _on_key_press_event(self,
|
|
| 73 | + _widget: Gtk.Widget,
|
|
| 74 | + event: Gdk.EventKey
|
|
| 75 | + ) -> None:
|
|
| 76 | + |
|
| 77 | + if event.keyval == Gdk.KEY_Escape:
|
|
| 78 | + self.destroy()
|
|
| 79 | + |
|
| 80 | + def _on_jump_to_clicked(self, _button: Gtk.Button) -> None:
|
|
| 81 | + self._chat_control.scroll_to_message(500, BASE_TIMESTAMP + 500)
|
|
| 82 | + |
|
| 83 | + |
|
| 84 | +def add_archive_messages() -> None:
|
|
| 85 | + timestamp = BASE_TIMESTAMP
|
|
| 86 | + for num in range(1000):
|
|
| 87 | + app.storage.archive.insert_into_logs(
|
|
| 88 | + ACCOUNT,
|
|
| 89 | + FROM_JID,
|
|
| 90 | + timestamp,
|
|
| 91 | + KindConstant.CHAT_MSG_RECV,
|
|
| 92 | + message=num,
|
|
| 93 | + stanza_id=num,
|
|
| 94 | + message_id=num)
|
|
| 95 | + timestamp += 1
|
|
| 96 | + |
|
| 97 | + |
|
| 98 | +app.get_client = MagicMock()
|
|
| 99 | +app.window = MagicMock()
|
|
| 100 | + |
|
| 101 | +app.settings = Settings(in_memory=True)
|
|
| 102 | +app.settings.init()
|
|
| 103 | +app.settings.add_account(ACCOUNT)
|
|
| 104 | + |
|
| 105 | +app.storage.events = EventStorage()
|
|
| 106 | +app.storage.events.init()
|
|
| 107 | + |
|
| 108 | +app.storage.archive = MessageArchiveStorage(in_memory=True)
|
|
| 109 | +app.storage.archive.init()
|
|
| 110 | +add_archive_messages()
|
|
| 111 | + |
|
| 112 | +configpaths.set_separation(True)
|
|
| 113 | +configpaths.set_config_root(tempfile.gettempdir())
|
|
| 114 | +configpaths.init()
|
|
| 115 | + |
|
| 116 | +app.preview_manager = PreviewManager()
|
|
| 117 | + |
|
| 118 | +win = ConversationViewTest()
|
|
| 119 | +win.connect('destroy', Gtk.main_quit)
|
|
| 120 | +win.show_all()
|
|
| 121 | + |
|
| 122 | +Gtk.main() |