Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/gajim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilipp Hörist <philipp@hoerist.com>2023-11-14 23:06:58 +0300
committerPhilipp Hörist <philipp@hoerist.com>2023-11-14 23:06:58 +0300
commite21fe0558de49425573fd3bf72386af73f6af3fc (patch)
treeb19b26ba8b36b8d611b1b7e99fd78231dd108df8
parentf6cfa352d2a32fe2b5311f735a6c836ebe62770c (diff)
feat: Add shortcuts for quoting previous messages
-rw-r--r--gajim/data/gui/shortcuts_window.ui14
-rw-r--r--gajim/data/other/shortcuts.json4
-rw-r--r--gajim/gtk/chat_stack.py26
-rw-r--r--gajim/gtk/const.py2
-rw-r--r--gajim/gtk/control.py3
-rw-r--r--gajim/gtk/conversation/view.py49
-rw-r--r--gajim/gtk/message_actions_box.py11
7 files changed, 105 insertions, 4 deletions
diff --git a/gajim/data/gui/shortcuts_window.ui b/gajim/data/gui/shortcuts_window.ui
index 649934843..ed88ed604 100644
--- a/gajim/data/gui/shortcuts_window.ui
+++ b/gajim/data/gui/shortcuts_window.ui
@@ -111,6 +111,20 @@
<child>
<object class="GtkShortcutsShortcut">
<property name="visible">1</property>
+ <property name="accelerator">&lt;primary&gt;&lt;shift&gt;Up</property>
+ <property name="title" translatable="yes">Quote previous message</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkShortcutsShortcut">
+ <property name="visible">1</property>
+ <property name="accelerator">&lt;primary&gt;&lt;shift&gt;Down</property>
+ <property name="title" translatable="yes">Quote next message</property>
+ </object>
+ </child>
+ <child>
+ <object class="GtkShortcutsShortcut">
+ <property name="visible">1</property>
<property name="accelerator">&lt;shift&gt;Return &lt;primary&gt;Return</property>
<property name="title" translatable="yes">Add new line</property>
</object>
diff --git a/gajim/data/other/shortcuts.json b/gajim/data/other/shortcuts.json
index 4f26e891f..3139358fd 100644
--- a/gajim/data/other/shortcuts.json
+++ b/gajim/data/other/shortcuts.json
@@ -43,5 +43,7 @@
"win.reset-app-font-size": ["<Primary>0", "<Primary>KP_0"],
"win.toggle-chat-list": ["<Primary>R"],
"win.scroll-view-up": ["<Shift>Page_Up"],
- "win.scroll-view-down": ["<Shift>Page_Down"]
+ "win.scroll-view-down": ["<Shift>Page_Down"],
+ "win.quote-prev": ["<Primary><Shift>Up"],
+ "win.quote-next": ["<Primary><Shift>Down"]
}
diff --git a/gajim/gtk/chat_stack.py b/gajim/gtk/chat_stack.py
index b8050cedc..7ef7bf57b 100644
--- a/gajim/gtk/chat_stack.py
+++ b/gajim/gtk/chat_stack.py
@@ -65,6 +65,7 @@ class ChatStack(Gtk.Stack, EventHelper):
self.set_hexpand(True)
self._current_contact: ChatContactT | None = None
+ self._last_quoted_id: int | None = None
self.add_named(ChatPlaceholderBox(), 'empty')
@@ -185,6 +186,8 @@ class ChatStack(Gtk.Stack, EventHelper):
clipboard = Gtk.Clipboard.get(Gdk.SELECTION_PRIMARY)
old_primary_clipboard = clipboard.wait_for_text()
+ self._last_quoted_id = None
+
if self._current_contact is not None:
self._current_contact.disconnect_all_from_obj(self)
@@ -483,6 +486,8 @@ class ChatStack(Gtk.Stack, EventHelper):
'muc-change-role',
'muc-change-affiliation',
'muc-request-voice',
+ 'quote-next',
+ 'quote-prev',
]
for action in actions:
@@ -556,9 +561,14 @@ class ChatStack(Gtk.Stack, EventHelper):
action: Gio.SimpleAction,
param: GLib.Variant | None) -> None:
+ if self.get_visible_child_name() != 'controls':
+ return
+
action_name = action.get_name()
contact = self._current_contact
- assert contact is not None
+ if contact is None:
+ return
+
account = contact.account
client = app.get_client(account)
jid = contact.jid
@@ -648,6 +658,18 @@ class ChatStack(Gtk.Stack, EventHelper):
elif action_name == 'muc-request-voice':
client.get_module('MUC').request_voice(contact.jid)
+ elif action_name.startswith('quote-'):
+ view = self._chat_control.get_conversation_view()
+ if action_name == 'quote-prev':
+ row = view.get_prev_message_row(self._last_quoted_id)
+ else:
+ row = view.get_next_message_row(self._last_quoted_id)
+
+ if row is not None:
+ self._last_quoted_id = row.log_line_id
+ self._message_action_box.insert_as_quote(
+ row.get_text(), clear=True)
+
def _on_drag_data_received(self,
_widget: Gtk.Widget,
_context: Gdk.DragContext,
@@ -788,6 +810,7 @@ class ChatStack(Gtk.Stack, EventHelper):
client.send_message(message_)
self._message_action_box.msg_textview.clear()
+ self._last_quoted_id = None
app.storage.drafts.set(contact, '')
def get_last_message_id(self, contact: ChatContactT) -> str | None:
@@ -805,6 +828,7 @@ class ChatStack(Gtk.Stack, EventHelper):
if self._current_contact is not None:
self._current_contact.disconnect_all_from_obj(self)
+ self._last_quoted_id = None
self.set_visible_child_name('empty')
self._chat_banner.clear()
self._message_action_box.clear()
diff --git a/gajim/gtk/const.py b/gajim/gtk/const.py
index 085eb449e..dd17857a0 100644
--- a/gajim/gtk/const.py
+++ b/gajim/gtk/const.py
@@ -223,6 +223,8 @@ MAIN_WIN_ACTIONS = [
('copy-message', 's', True),
('retract-message', 'a{sv}', False),
('quote', 's', False),
+ ('quote-next', None, True),
+ ('quote-prev', None, True),
('mention', 's', False),
('send-file-httpupload', 'as', False),
('send-file-jingle', 'as', False),
diff --git a/gajim/gtk/control.py b/gajim/gtk/control.py
index 7480f32bb..ef2ddbbce 100644
--- a/gajim/gtk/control.py
+++ b/gajim/gtk/control.py
@@ -144,6 +144,9 @@ class ChatControl(EventHelper):
def get_group_chat_roster(self) -> GroupchatRoster:
return self._roster
+ def get_conversation_view(self) -> ConversationView:
+ return self._scrolled_view
+
def add_command_output(self, text: str, is_error: bool) -> None:
self._scrolled_view.add_command_output(text, is_error)
diff --git a/gajim/gtk/conversation/view.py b/gajim/gtk/conversation/view.py
index d7cc32dff..fdbe85e4b 100644
--- a/gajim/gtk/conversation/view.py
+++ b/gajim/gtk/conversation/view.py
@@ -37,6 +37,7 @@ from nbxmpp.structs import MucSubject
from gajim.common import app
from gajim.common import events
from gajim.common import types
+from gajim.common.const import Direction
from gajim.common.helpers import AdditionalDataDict
from gajim.common.helpers import get_start_of_day
from gajim.common.helpers import to_user_string
@@ -390,8 +391,7 @@ class ConversationView(Gtk.ScrolledWindow):
return None
def get_last_message_row(self) -> MessageRow | None:
- children = self._list_box.get_children()
- children.reverse()
+ children = reversed(self._list_box.get_children())
for row in children:
if isinstance(row, MessageRow):
return row
@@ -710,6 +710,51 @@ class ConversationView(Gtk.ScrolledWindow):
def _get_row_by_message_id(self, id_: str) -> MessageRow | None:
return self._message_id_row_map.get(id_)
+ def _get_message_row_by_direction(
+ self,
+ log_line_id: int,
+ direction: Direction | None = None
+ ) -> MessageRow | None:
+
+ row = self.get_row_by_log_line_id(log_line_id)
+ if row is None:
+ return None
+
+ if direction is None:
+ return row
+
+ index = row.get_index()
+ while True:
+ if direction == Direction.PREV:
+ index -= 1
+ else:
+ index += 1
+
+ row = self._list_box.get_row_at_index(index)
+ if row is None:
+ return None
+
+ if isinstance(row, MessageRow):
+ return row
+
+ def get_prev_message_row(
+ self,
+ log_line_id: int | None
+ ) -> MessageRow | None:
+ if log_line_id is None:
+ return self.get_last_message_row()
+ return self._get_message_row_by_direction(
+ log_line_id, direction=Direction.PREV)
+
+ def get_next_message_row(
+ self,
+ log_line_id: int | None
+ ) -> MessageRow | None:
+ if log_line_id is None:
+ return None
+ return self._get_message_row_by_direction(
+ log_line_id, direction=Direction.NEXT)
+
def get_row_by_log_line_id(self, log_line_id: int) -> MessageRow | None:
for row in cast(list[BaseRow], self._list_box.get_children()):
if not isinstance(row, MessageRow):
diff --git a/gajim/gtk/message_actions_box.py b/gajim/gtk/message_actions_box.py
index dc9031e57..a377c5ecd 100644
--- a/gajim/gtk/message_actions_box.py
+++ b/gajim/gtk/message_actions_box.py
@@ -218,6 +218,17 @@ class MessageActionsBox(Gtk.Grid):
def is_correcting(self) -> bool:
return self.msg_textview.is_correcting
+ def insert_as_quote(self, text: str, *, clear: bool = False) -> None:
+ if self._contact is None:
+ return
+
+ if not self.msg_textview.is_sensitive():
+ return
+
+ if clear:
+ self.msg_textview.clear()
+ self.msg_textview.insert_as_quote(text)
+
def toggle_message_correction(self) -> None:
self.msg_textview.toggle_message_correction()