Philipp Hörist pushed to branch sort-chat-list at gajim / gajim
Commits: 909bae91 by mjk at 2023-05-13T13:45:12+00:00 imprv: ACE: Make descriptions selectable and copyable
- - - - - ff08ac13 by mjk at 2023-05-13T13:54:14+00:00 fix: ACE: Handle invalid numeric values gracefully
- - - - - 63eb1041 by wurstsalat at 2023-05-13T22:33:58+02:00 imprv: Make contact details/settings available when offline
- - - - - 1128a3db by Philipp Hörist at 2023-05-14T13:37:45+02:00 new: MAM: Add sync state signals
- - - - - e205b303 by Philipp Hörist at 2023-05-14T11:38:57+00:00 imprv: ChatList: Improve sorting
The sort of the chat list is inhibited when the mouse is over the chat list. This makes sure the sorting is invalidated once the mouse exits the chat list.
- - - - -
9 changed files:
- gajim/common/modules/mam.py - gajim/data/gui/advanced_configuration.ui - gajim/data/gui/groupchat_details.ui - gajim/gtk/advanced_config.py - gajim/gtk/chat_list.py - gajim/gtk/chat_list_row.py - gajim/gtk/chat_stack.py - gajim/gtk/const.py - gajim/gtk/groupchat_details.py
Changes:
===================================== gajim/common/modules/mam.py ===================================== @@ -464,12 +464,16 @@ def request_archive_on_muc_join(self, jid: JID): if threshold == SyncThreshold.NO_SYNC: return
+ contact = self._get_contact(jid, groupchat=True) + contact.notify('mam-sync-started') + mam_id, start_date = self._get_muc_query_params(jid, threshold)
result = yield self._execute_query(jid, mam_id, start_date) if is_error(result): if result.condition != 'item-not-found': self._log.warning(result) + contact.notify('mam-sync-error', result.get_text()) return
app.storage.archive.reset_archive_infos(result.jid) @@ -477,6 +481,7 @@ def request_archive_on_muc_join(self, jid: JID): result = yield self._execute_query(result.jid, None, start_date) if is_error(result): self._log.warning(result) + contact.notify('mam-sync-error', result.get_text()) return
if result.rsm.last is not None: @@ -488,6 +493,8 @@ def request_archive_on_muc_join(self, jid: JID): last_mam_id=result.rsm.last, last_muc_timestamp=time.time())
+ contact.notify('mam-sync-finished') + @as_task def _execute_query(self, jid: JID,
===================================== gajim/data/gui/advanced_configuration.ui ===================================== @@ -96,7 +96,7 @@ <object class="GtkLabel" id="description"> <property name="height_request">40</property> <property name="visible">True</property> - <property name="can_focus">False</property> + <property name="selectable">True</property> <property name="wrap">True</property> <property name="max_width_chars">60</property> <property name="xalign">0</property>
===================================== gajim/data/gui/groupchat_details.ui ===================================== @@ -55,9 +55,10 @@ <child> <object class="GtkToggleButton" id="edit_name_button"> <property name="visible">True</property> + <property name="sensitive">False</property> <property name="can-focus">True</property> <property name="receives-default">True</property> - <property name="tooltip-text" translatable="yes">Edit Name…</property> + <property name="tooltip-text" translatable="yes">Not connected</property> <property name="valign">center</property> <signal name="toggled" handler="_on_edit_name_toggled" swapped="no"/> <child>
===================================== gajim/gtk/advanced_config.py ===================================== @@ -201,7 +201,10 @@ def _on_config_edited(self,
value = text if modelrow[Column.TYPE] == SETTING_TYPES[int]: - value = int(text) + try: + value = int(text) + except ValueError: + return
app.settings.set(setting, value) modelrow[Column.VALUE] = text
===================================== gajim/gtk/chat_list.py ===================================== @@ -71,7 +71,9 @@ def __init__(self, workspace_id: str) -> None: self.set_sort_func(self._sort_func) self._set_placeholder()
- self._mouseover: bool = False + self._rows_need_sort = False + self._context_menu_visible = False + self._mouseover = False self._pinned_order_change = False self.connect('enter-notify-event', self._on_mouse_focus_changed) self.connect('leave-notify-event', self._on_mouse_focus_changed) @@ -206,6 +208,8 @@ def add_chat(self,
row.connect('drag-begin', self._on_row_drag_begin) row.connect('unread-changed', self._on_row_unread_changed) + row.connect('context-menu-state-changed', + self._on_context_menu_state_changed)
self.add(row)
@@ -371,6 +375,14 @@ def _on_row_drag_begin(self, def _on_row_unread_changed(self, row: ChatListRow) -> None: self._emit_unread_changed()
+ def _on_context_menu_state_changed(self, + row: ChatListRow, + menu_is_visible: bool + ) -> None: + + self._context_menu_visible = menu_is_visible + self._schedule_check_sort_inhibit() + def _on_drag_data_received(self, _widget: Gtk.Widget, _drag_context: Gdk.DragContext, @@ -478,8 +490,9 @@ def _header_func(row: ChatListRow, before: ChatListRow | None) -> None: row.set_header_type(None)
def _sort_func(self, row1: ChatListRow, row2: ChatListRow) -> int: - if self._mouseover and not self._pinned_order_change: - log.debug('Mouseover active, don’t sort rows') + if self._is_sort_inhibited(): + self._rows_need_sort = True + log.debug('Sort inhibited') return 0
# Sort pinned rows according to stored order @@ -497,6 +510,33 @@ def _sort_func(self, row1: ChatListRow, row2: ChatListRow) -> int: # Sort by timestamp return -1 if row1.timestamp > row2.timestamp else 1
+ def invalidate_sort(self) -> None: + if self._is_sort_inhibited(): + return + + self._rows_need_sort = False + log.debug('Sort Chatlist') + Gtk.ListBox.invalidate_sort(self) + + def _is_sort_inhibited(self) -> bool: + if self._pinned_order_change: + return False + return self._mouseover or self._context_menu_visible + + def _schedule_check_sort_inhibit(self) -> None: + if self._is_sort_inhibited(): + return + GLib.timeout_add(100, self._check_sort_inhibit) + + def _check_sort_inhibit(self) -> None: + if self._is_sort_inhibited(): + return + + if not self._rows_need_sort: + return + + self.invalidate_sort() + def _on_mouse_focus_changed(self, _widget: Gtk.ListBox, event: Gdk.EventCrossing @@ -510,6 +550,8 @@ def _on_mouse_focus_changed(self, # Not hovering a Gtk.ListBoxRow (row is INFERIOR) self._mouseover = False
+ self._schedule_check_sort_inhibit() + @staticmethod def _on_start_chat_clicked(_button: Gtk.Button) -> None: app.app.activate_action('start-chat', GLib.Variant('as', ['', '']))
===================================== gajim/gtk/chat_list_row.py ===================================== @@ -63,6 +63,10 @@ class ChatListRow(Gtk.ListBoxRow): GObject.SignalFlags.RUN_LAST, None, ()), + 'context-menu-state-changed': ( + GObject.SignalFlags.RUN_LAST, + None, + (bool,)), }
def __init__(self, @@ -437,14 +441,14 @@ def _on_row_button_press_event(self, ) -> None:
if event.button == Gdk.BUTTON_SECONDARY: - self._popup_menu(event) + self._raise_context_popover(event)
elif event.button == Gdk.BUTTON_MIDDLE: app.window.activate_action( 'remove-chat', GLib.Variant('as', [self.account, str(self.jid)]))
- def _popup_menu(self, event: Gdk.EventButton): + def _raise_context_popover(self, event: Gdk.EventButton): menu = get_chat_list_row_menu( self.workspace_id, self.account, self.jid, self._pinned)
@@ -460,8 +464,13 @@ def _popup_menu(self, event: Gdk.EventButton):
popover = GajimPopover(menu, relative_to=self) popover.set_pointing_to_coord(x=x, y=event.y) + popover.connect('closed', self._on_context_popover_closed) + self.emit('context-menu-state-changed', True) popover.popup()
+ def _on_context_popover_closed(self, _popover: Gtk.Popover) -> None: + self.emit('context-menu-state-changed', False) + def _on_drag_begin(self, row: ChatListRow, drag_context: Gdk.DragContext
===================================== gajim/gtk/chat_stack.py ===================================== @@ -507,7 +507,6 @@ def _update_base_actions(self, contact: ChatContactT) -> None: jingle.get_enabled() or httpupload.get_enabled())
- app.window.get_action('show-contact-info').set_enabled(online) app.window.get_action('correct-message').set_enabled(online)
def _update_chat_actions(self, contact: BareContact) -> None:
===================================== gajim/gtk/const.py ===================================== @@ -232,7 +232,7 @@ def __str__(self): ('add-to-roster', None, True), ('start-voice-call', None, False), ('start-video-call', None, False), - ('show-contact-info', None, False), + ('show-contact-info', None, True), ('send-message', None, False), ('muc-change-nickname', None, False), ('muc-invite', None, False),
===================================== gajim/gtk/groupchat_details.py ===================================== @@ -22,7 +22,9 @@
from gajim.common import app from gajim.common import ged +from gajim.common import types from gajim.common.const import AvatarSize +from gajim.common.const import SimpleClientState from gajim.common.events import MucDiscoUpdate from gajim.common.i18n import _ from gajim.common.modules.contacts import GroupchatContact @@ -55,6 +57,9 @@ def __init__(self,
self.account = contact.account self._client = app.get_client(contact.account) + self._client.connect_signal( + 'state-changed', self._on_client_state_changed) + self._contact = contact self._contact.connect('avatar-update', self._on_avatar_update)
@@ -62,7 +67,7 @@ def __init__(self, self._ui.connect_signals(self)
self._switcher = SideBarSwitcher(width=250) - self._switcher.set_stack(self._ui.main_stack) + self._switcher.set_stack(self._ui.main_stack, rows_visible=False) self._ui.main_grid.attach(self._switcher, 0, 0, 1, 1) self._ui.main_stack.connect('notify::visible-child-name', self._on_stack_child_changed) @@ -73,10 +78,14 @@ def __init__(self, self._add_groupchat_info() self._add_groupchat_settings() self._add_groupchat_encryption() - self._add_groupchat_manage() - self._add_affiliations() - self._add_outcasts() - self._add_configuration() + + if self._client.state.is_available: + self._ui.edit_name_button.set_sensitive(True) + self._ui.edit_name_button.set_tooltip_text(_('Edit Name…')) + self._add_groupchat_manage() + self._add_affiliations() + self._add_outcasts() + self._add_configuration()
self._load_avatar() self._ui.name_entry.set_text(contact.name) @@ -92,6 +101,16 @@ def __init__(self,
self.show_all()
+ def _on_client_state_changed(self, + _client: types.Client, + _signal_name: str, + state: SimpleClientState + ) -> None: + + self._ui.edit_name_button.set_sensitive(state.is_connected) + self._ui.edit_name_button.set_tooltip_text( + _('Not connected') if not state.is_connected else _('Edit Name…')) + def _on_muc_disco_update(self, event: MucDiscoUpdate) -> None: if event.jid != self._contact.jid: return @@ -138,6 +157,7 @@ def _add_groupchat_manage(self) -> None: self._groupchat_manage = GroupchatManage(self.account, self._contact) self._ui.manage_box.add(self._groupchat_manage) + self._switcher.set_row_visible('manage', True)
def _add_groupchat_info(self) -> None: self._groupchat_info = GroupChatInfoScrolled( @@ -148,6 +168,7 @@ def _add_groupchat_info(self) -> None: self._groupchat_info.set_from_disco_info(disco_info) self._groupchat_info.set_subject(self._contact.subject) self._ui.info_box.add(self._groupchat_info) + self._switcher.set_row_visible('information', True)
def _add_groupchat_settings(self) -> None: main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=24) @@ -174,6 +195,7 @@ def _add_groupchat_settings(self) -> None: scrolled_window.add(main_box)
self._ui.settings_box.add(scrolled_window) + self._switcher.set_row_visible('settings', True)
def _add_groupchat_encryption(self) -> None: if (self._contact.is_groupchat and @@ -184,18 +206,22 @@ def _add_groupchat_encryption(self) -> None:
self._ui.encryption_box.add( OMEMOTrustManager(self._contact.account, self._contact)) + self._switcher.set_row_visible('encryption-omemo', True)
def _add_affiliations(self) -> None: affiliations = GroupchatAffiliation(self._client, self._contact) self._ui.affiliation_box.add(affiliations) + self._switcher.set_row_visible('affiliations', True)
def _add_outcasts(self) -> None: affiliations = GroupchatOutcasts(self._client, self._contact) self._ui.outcasts_box.add(affiliations) + self._switcher.set_row_visible('outcasts', True)
def _add_configuration(self) -> None: config = GroupchatConfig(self._client, self._contact) self._ui.configuration_box.add(config) + self._switcher.set_row_visible('config', True)
def _on_key_press(self, _widget: GroupchatDetails,
View it on GitLab: https://dev.gajim.org/gajim/gajim/-/compare/e5094ec0c349e8288675cfc7ea0c969c...