diff --git a/src/application/main-window.vala b/src/application/main-window.vala index d580c3e..40934e5 100644 --- a/src/application/main-window.vala +++ b/src/application/main-window.vala @@ -6,6 +6,9 @@ public class MainWindow : Adw.ApplicationWindow private ConversationListView conversation_list_view; private TranscriptContainerView transcript_container_view; + private EventControllerMotion _motion_controller = new EventControllerMotion(); + private bool _motion_queued = false; + public MainWindow () { Object (title: "Kordophone"); @@ -20,14 +23,59 @@ public class MainWindow : Adw.ApplicationWindow split_view.sidebar = conversation_list_page; transcript_container_view = new TranscriptContainerView (); - transcript_container_view.on_send.connect (on_transcript_send); - var transcript_page = new NavigationPage (transcript_container_view, "Transcript"); split_view.content = transcript_page; var show_settings_action = new SimpleAction ("settings", null); show_settings_action.activate.connect(show_settings); add_action(show_settings_action); + + _motion_controller.motion.connect((x, y) => { + queue_motion(); + }); + _motion_controller.set_propagation_phase(PropagationPhase.CAPTURE); + split_view.add_controller(_motion_controller); + } + + private void queue_motion() { + if (_motion_queued) { + return; + } + + if (!is_active) { + return; + } + + _motion_queued = true; + GLib.Timeout.add(500, () => { + _motion_queued = false; + on_motion(); + return false; + }); + } + + private void on_motion() { + var selected_conversation = transcript_container_view.transcript_view.model?.conversation; + if (selected_conversation == null) { + return; + } + + var list_model = conversation_list_view.conversation_model; + var conversation_in_list = list_model.get_conversation(selected_conversation.guid); + if (conversation_in_list == null) { + return; + } + + if (conversation_in_list.unread_count == 0) { + return; + } + + try { + GLib.message("Marking conversation as read on motion: %s", selected_conversation.guid); + Repository.get_instance().mark_conversation_as_read(selected_conversation.guid); + } catch (Error e) { + GLib.warning("Failed to mark conversation as read: %s", e.message); + } } private void show_settings () { @@ -40,8 +88,8 @@ public class MainWindow : Adw.ApplicationWindow if (conversation == null) { transcript_view.model = null; } else { - if (transcript_view.model == null || transcript_view.model.conversation_guid != conversation.guid) { - transcript_view.model = new MessageListModel (conversation.guid); + if (transcript_view.model == null || transcript_view.model.conversation.guid != conversation.guid) { + transcript_view.model = new MessageListModel (conversation); transcript_view.title = conversation.display_name; try { @@ -53,29 +101,4 @@ public class MainWindow : Adw.ApplicationWindow } } } - - private void on_transcript_send(TranscriptContainerView view) { - var body = view.message_body; - var attachment_guids = view.attachment_guids; - - // Strip empty space at the beginning and end of the body - body = body.strip(); - - if (transcript_container_view.transcript_view.model == null) { - GLib.warning("No conversation selected"); - return; - } - - var selected_conversation = transcript_container_view.transcript_view.model.conversation_guid; - if (selected_conversation == null) { - GLib.warning("No conversation selected"); - return; - } - - try { - Repository.get_instance().send_message(selected_conversation, body, attachment_guids.to_array()); - } catch (Error e) { - GLib.warning("Failed to send message: %s", e.message); - } - } } diff --git a/src/conversation-list/conversation-list-view.vala b/src/conversation-list/conversation-list-view.vala index 7cdf069..06bc6ce 100644 --- a/src/conversation-list/conversation-list-view.vala +++ b/src/conversation-list/conversation-list-view.vala @@ -3,13 +3,13 @@ using Gtk; public class ConversationListView : Adw.Bin { + public ConversationListModel conversation_model { get; private set; } public signal void conversation_selected(Conversation conversation); private Adw.ToolbarView container; private ListBox list_box; private ScrolledWindow scrolled_window; private Adw.HeaderBar header_bar; - private ConversationListModel conversation_model; private string? selected_conversation_guid = null; private bool selection_update_queued = false; diff --git a/src/transcript/message-list-model.vala b/src/transcript/message-list-model.vala index 445f6a3..b4cf6ec 100644 --- a/src/transcript/message-list-model.vala +++ b/src/transcript/message-list-model.vala @@ -15,16 +15,16 @@ public class MessageListModel : Object, ListModel } } - public string conversation_guid { get; private set; } + public Conversation conversation { get; private set; } private ArrayList _messages; private HashSet participants = new HashSet(); private ulong update_handler_id = 0; private ulong reconnected_handler_id = 0; - public MessageListModel(string conversation_guid) { + public MessageListModel(Conversation conversation) { _messages = new ArrayList(); - this.conversation_guid = conversation_guid; + this.conversation = conversation; } ~MessageListModel() { @@ -69,7 +69,7 @@ public class MessageListModel : Object, ListModel try { bool first_load = _messages.size == 0; - Message[] messages = Repository.get_instance().get_messages(conversation_guid); + Message[] messages = Repository.get_instance().get_messages(conversation.guid); // Clear existing set uint old_count = _messages.size; @@ -108,8 +108,16 @@ public class MessageListModel : Object, ListModel messages_changed(); } + public void mark_as_read() { + try { + Repository.get_instance().mark_conversation_as_read(conversation.guid); + } catch (Error e) { + warning("Failed to mark conversation as read: %s", e.message); + } + } + private void got_messages_updated(string conversation_guid) { - if (conversation_guid == this.conversation_guid) { + if (conversation_guid == this.conversation.guid) { load_messages(); } } diff --git a/src/transcript/transcript-container-view.vala b/src/transcript/transcript-container-view.vala index be9e08a..4d1bef6 100644 --- a/src/transcript/transcript-container-view.vala +++ b/src/transcript/transcript-container-view.vala @@ -7,7 +7,6 @@ using GLib; class TranscriptContainerView : Adw.Bin { public TranscriptView transcript_view; - public signal void on_send(TranscriptContainerView view); private Box container; private Button send_button; @@ -225,7 +224,7 @@ class TranscriptContainerView : Adw.Bin private void on_request_send() { if (can_send) { - on_send(this); + on_send(); // Clear the message text message_buffer.set_text(""); @@ -240,6 +239,30 @@ class TranscriptContainerView : Adw.Bin } } + private void on_send() { + var body = message_body; + + // Strip empty space at the beginning and end of the body + body = body.strip(); + + if (transcript_view.model == null) { + GLib.warning("No conversation selected"); + return; + } + + var selected_conversation = transcript_view.model.conversation; + if (selected_conversation == null) { + GLib.warning("No conversation selected"); + return; + } + + try { + Repository.get_instance().send_message(selected_conversation.guid, body, attachment_guids.to_array()); + } catch (Error e) { + GLib.warning("Failed to send message: %s", e.message); + } + } + private void on_attach_button_clicked() { var dialog = new Gtk.FileDialog(); dialog.set_title("Select attachment"); diff --git a/src/transcript/transcript-drawing-area.vala b/src/transcript/transcript-drawing-area.vala index 2169cde..52a84e8 100644 --- a/src/transcript/transcript-drawing-area.vala +++ b/src/transcript/transcript-drawing-area.vala @@ -25,6 +25,8 @@ private class TranscriptDrawingArea : Widget private GestureClick _click_gesture = new GestureClick(); private Gdk.Rectangle? _click_bounding_box = null; + private EventControllerMotion _motion_controller = new EventControllerMotion(); + private const bool debug_viewport = false; private uint? _tick_callback_id = null; private HashMap _animations = new HashMap(); @@ -40,6 +42,22 @@ private class TranscriptDrawingArea : Widget }); add_controller(_click_gesture); + _motion_controller.motion.connect((x, y) => { + if (self == null) { + return; + } + + // Only print motion events if window is active/focused + var window = self.get_native() as Gtk.Window; + if (window == null || !window.is_active) { + return; + } + + self.on_mouse_motion(x, y); + }); + _motion_controller.set_propagation_phase(PropagationPhase.CAPTURE); + add_controller(_motion_controller); + SimpleAction copy_action = new SimpleAction("copy", null); copy_action.activate.connect(() => { if (_click_bounding_box != null) { @@ -172,6 +190,10 @@ private class TranscriptDrawingArea : Widget animation_tick(); } + private void on_mouse_motion(double x, double y) { + // TODO: Will be making temporary text views here. + } + private void on_right_click() { var menu_model = new Menu(); menu_model.append("Copy", "transcript.copy");