diff --git a/libdino/src/service/chat_interaction.vala b/libdino/src/service/chat_interaction.vala index 9d5c19e7..88ddbd19 100644 --- a/libdino/src/service/chat_interaction.vala +++ b/libdino/src/service/chat_interaction.vala @@ -4,6 +4,7 @@ using Xmpp; using Dino.Entities; namespace Dino { + public class ChatInteraction : StreamInteractionModule, Object { private const string id = "chat_interaction"; @@ -37,40 +38,33 @@ public class ChatInteraction : StreamInteractionModule, Object { } } - public void window_focus_in(Conversation? conversation) { - on_conversation_selected(selected_conversation); + public void on_window_focus_in(Conversation? conversation) { + on_conversation_focused(conversation); } - public void window_focus_out(Conversation? conversation) { - focus_in = false; + public void on_window_focus_out(Conversation? conversation) { + on_conversation_unfocused(conversation); } - public void on_message_entered(Conversation conversation) { - if (Settings.instance().send_read) { - if (!last_input_interaction.has_key(conversation) && conversation.type_ != Conversation.Type.GROUPCHAT) { - send_chat_state_notification(conversation, Xep.ChatStateNotifications.STATE_COMPOSING); - } + public void on_message_entered(Conversation? conversation) { + if (!last_input_interaction.has_key(conversation)) { + send_chat_state_notification(conversation, Xep.ChatStateNotifications.STATE_COMPOSING); } last_input_interaction[conversation] = new DateTime.now_utc(); last_interface_interaction[conversation] = new DateTime.now_utc(); } - public void on_message_cleared(Conversation conversation) { + public void on_message_cleared(Conversation? conversation) { if (last_input_interaction.has_key(conversation)) { last_input_interaction.unset(conversation); - last_interface_interaction.unset(conversation); send_chat_state_notification(conversation, Xep.ChatStateNotifications.STATE_ACTIVE); } } public void on_conversation_selected(Conversation? conversation) { + on_conversation_unfocused(selected_conversation); selected_conversation = conversation; - focus_in = true; - if (conversation != null) { - conversation_read(selected_conversation); - check_send_read(); - selected_conversation.read_up_to = MessageManager.get_instance(stream_interactor).get_last_message(conversation); - } + on_conversation_focused(conversation); } internal string get_id() { @@ -81,6 +75,29 @@ public class ChatInteraction : StreamInteractionModule, Object { return (ChatInteraction) stream_interactor.get_module(id); } + private void on_message_sent(Entities.Message message, Conversation conversation) { + last_input_interaction.unset(conversation); + last_interface_interaction.unset(conversation); + conversation.read_up_to = message; + } + + private void on_conversation_focused(Conversation? conversation) { + focus_in = true; + if (conversation == null) return; + conversation_read(selected_conversation); + check_send_read(); + selected_conversation.read_up_to = MessageManager.get_instance(stream_interactor).get_last_message(conversation); + } + + private void on_conversation_unfocused(Conversation? conversation) { + focus_in = false; + if (conversation == null) return; + if (last_input_interaction.has_key(conversation)) { + send_chat_state_notification(conversation, Xep.ChatStateNotifications.STATE_PAUSED); + last_input_interaction.unset(conversation); + } + } + private void check_send_read() { if (selected_conversation == null || selected_conversation.type_ == Conversation.Type.GROUPCHAT) return; Entities.Message? message = MessageManager.get_instance(stream_interactor).get_last_message(selected_conversation); @@ -92,24 +109,24 @@ public class ChatInteraction : StreamInteractionModule, Object { } private bool update_interactions() { - ArrayList remove_input = new ArrayList(Conversation.equals_func); - ArrayList remove_interface = new ArrayList(Conversation.equals_func); - foreach (Conversation conversation in last_input_interaction.keys) { + for (MapIterator iter = last_input_interaction.map_iterator(); iter.has_next(); iter.next()) { + if (!iter.valid && iter.has_next()) iter.next(); + Conversation conversation = iter.get_key(); if (last_input_interaction.has_key(conversation) && (new DateTime.now_utc()).difference(last_input_interaction[conversation]) >= 15 * TimeSpan.SECOND) { - remove_input.add(conversation); + iter.unset(); send_chat_state_notification(conversation, Xep.ChatStateNotifications.STATE_PAUSED); } } - foreach (Conversation conversation in last_interface_interaction.keys) { + for (MapIterator iter = last_interface_interaction.map_iterator(); iter.has_next(); iter.next()) { + if (!iter.valid && iter.has_next()) iter.next(); + Conversation conversation = iter.get_key(); if (last_interface_interaction.has_key(conversation) && (new DateTime.now_utc()).difference(last_interface_interaction[conversation]) >= 1.5 * TimeSpan.MINUTE) { - remove_interface.add(conversation); + iter.unset(); send_chat_state_notification(conversation, Xep.ChatStateNotifications.STATE_GONE); } } - foreach (Conversation conversation in remove_input) last_input_interaction.unset(conversation); - foreach (Conversation conversation in remove_interface) last_interface_interaction.unset(conversation); return true; } @@ -123,24 +140,21 @@ public class ChatInteraction : StreamInteractionModule, Object { } } - private void on_message_sent(Entities.Message message, Conversation conversation) { - last_input_interaction.unset(conversation); - last_interface_interaction.unset(conversation); - conversation.read_up_to = message; - } - private void send_chat_marker(Conversation conversation, Entities.Message message, string marker) { Core.XmppStream stream = stream_interactor.get_stream(conversation.account); - if (stream != null && Settings.instance().send_read && Xep.ChatMarkers.Module.requests_marking(message.stanza)) { + if (stream != null && Settings.instance().send_read && + Xep.ChatMarkers.Module.requests_marking(message.stanza)) { stream.get_module(Xep.ChatMarkers.Module.IDENTITY).send_marker(stream, message.stanza.from, message.stanza_id, message.get_type_string(), marker); } } private void send_chat_state_notification(Conversation conversation, string state) { Core.XmppStream stream = stream_interactor.get_stream(conversation.account); - if (stream != null && Settings.instance().send_read) { + if (stream != null && Settings.instance().send_read && + conversation.type_ != Conversation.Type.GROUPCHAT) { stream.get_module(Xep.ChatStateNotifications.Module.IDENTITY).send_state(stream, conversation.counterpart.to_string(), state); } } } + } \ No newline at end of file diff --git a/main/src/ui/chat_input.vala b/main/src/ui/chat_input.vala index 209869a8..2079d747 100644 --- a/main/src/ui/chat_input.vala +++ b/main/src/ui/chat_input.vala @@ -38,23 +38,21 @@ public class ChatInput : Box { this.stream_interactor = stream_interactor; scrolled.get_vscrollbar().get_preferred_height(out vscrollbar_min_height, null); scrolled.vadjustment.notify["upper"].connect_after(on_upper_notify); + text_input.key_press_event.connect(on_text_input_key_press); + text_input.buffer.changed.connect(on_text_input_changed); } public void initialize_for_conversation(Conversation conversation) { - if (this.conversation != null) { - if (text_input.buffer.text != "") { - entry_cache[this.conversation] = text_input.buffer.text; - } else { - entry_cache.unset(this.conversation); - } - } + if (this.conversation != null) entry_cache[this.conversation] = text_input.buffer.text; this.conversation = conversation; + + text_input.buffer.changed.disconnect(on_text_input_changed); text_input.buffer.text = ""; if (entry_cache.has_key(conversation)) { text_input.buffer.text = entry_cache[conversation]; } - text_input.key_press_event.connect(on_text_input_key_press); - text_input.key_release_event.connect(on_text_input_key_release); + text_input.buffer.changed.connect(on_text_input_changed); + text_input.grab_focus(); } @@ -117,13 +115,12 @@ public class ChatInput : Box { } } - private bool on_text_input_key_release(EventKey event) { + private void on_text_input_changed() { if (text_input.buffer.text != "") { ChatInteraction.get_instance(stream_interactor).on_message_entered(conversation); } else { ChatInteraction.get_instance(stream_interactor).on_message_cleared(conversation); } - return false; } } diff --git a/main/src/ui/unified_window.vala b/main/src/ui/unified_window.vala index 269799c2..0f33450d 100644 --- a/main/src/ui/unified_window.vala +++ b/main/src/ui/unified_window.vala @@ -68,12 +68,12 @@ public class UnifiedWindow : Window { } private bool on_focus_in_event() { - ChatInteraction.get_instance(stream_interactor).window_focus_in(conversation); + ChatInteraction.get_instance(stream_interactor).on_window_focus_in(conversation); return false; } private bool on_focus_out_event() { - ChatInteraction.get_instance(stream_interactor).window_focus_out(conversation); + ChatInteraction.get_instance(stream_interactor).on_window_focus_out(conversation); return false; } } diff --git a/plugins/openpgp/src/manager.vala b/plugins/openpgp/src/manager.vala index 4fe50939..0941362e 100644 --- a/plugins/openpgp/src/manager.vala +++ b/plugins/openpgp/src/manager.vala @@ -67,12 +67,14 @@ namespace Dino.Plugins.OpenPgp { } private void on_jid_key_received(Account account, Jid jid, string key_id) { - if (!pgp_key_ids.has_key(jid) || pgp_key_ids[jid] != key_id) { - if (!MucManager.get_instance(stream_interactor).is_groupchat_occupant(jid, account)) { - db.set_contact_key(jid.bare_jid, key_id); + lock (pgp_key_ids) { + if (!pgp_key_ids.has_key(jid) || pgp_key_ids[jid] != key_id) { + if (!MucManager.get_instance(stream_interactor).is_groupchat_occupant(jid, account)) { + db.set_contact_key(jid.bare_jid, key_id); + } } + pgp_key_ids[jid] = key_id; } - pgp_key_ids[jid] = key_id; } } } \ No newline at end of file