Improve when to send chat state notifications
This commit is contained in:
parent
af49a47cf6
commit
6f3eee1430
|
@ -4,6 +4,7 @@ using Xmpp;
|
||||||
using Dino.Entities;
|
using Dino.Entities;
|
||||||
|
|
||||||
namespace Dino {
|
namespace Dino {
|
||||||
|
|
||||||
public class ChatInteraction : StreamInteractionModule, Object {
|
public class ChatInteraction : StreamInteractionModule, Object {
|
||||||
private const string id = "chat_interaction";
|
private const string id = "chat_interaction";
|
||||||
|
|
||||||
|
@ -37,40 +38,33 @@ public class ChatInteraction : StreamInteractionModule, Object {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void window_focus_in(Conversation? conversation) {
|
public void on_window_focus_in(Conversation? conversation) {
|
||||||
on_conversation_selected(selected_conversation);
|
on_conversation_focused(conversation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void window_focus_out(Conversation? conversation) {
|
public void on_window_focus_out(Conversation? conversation) {
|
||||||
focus_in = false;
|
on_conversation_unfocused(conversation);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void on_message_entered(Conversation conversation) {
|
public void on_message_entered(Conversation? conversation) {
|
||||||
if (Settings.instance().send_read) {
|
if (!last_input_interaction.has_key(conversation)) {
|
||||||
if (!last_input_interaction.has_key(conversation) && conversation.type_ != Conversation.Type.GROUPCHAT) {
|
send_chat_state_notification(conversation, Xep.ChatStateNotifications.STATE_COMPOSING);
|
||||||
send_chat_state_notification(conversation, Xep.ChatStateNotifications.STATE_COMPOSING);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
last_input_interaction[conversation] = new DateTime.now_utc();
|
last_input_interaction[conversation] = new DateTime.now_utc();
|
||||||
last_interface_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)) {
|
if (last_input_interaction.has_key(conversation)) {
|
||||||
last_input_interaction.unset(conversation);
|
last_input_interaction.unset(conversation);
|
||||||
last_interface_interaction.unset(conversation);
|
|
||||||
send_chat_state_notification(conversation, Xep.ChatStateNotifications.STATE_ACTIVE);
|
send_chat_state_notification(conversation, Xep.ChatStateNotifications.STATE_ACTIVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void on_conversation_selected(Conversation? conversation) {
|
public void on_conversation_selected(Conversation? conversation) {
|
||||||
|
on_conversation_unfocused(selected_conversation);
|
||||||
selected_conversation = conversation;
|
selected_conversation = conversation;
|
||||||
focus_in = true;
|
on_conversation_focused(conversation);
|
||||||
if (conversation != null) {
|
|
||||||
conversation_read(selected_conversation);
|
|
||||||
check_send_read();
|
|
||||||
selected_conversation.read_up_to = MessageManager.get_instance(stream_interactor).get_last_message(conversation);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
internal string get_id() {
|
internal string get_id() {
|
||||||
|
@ -81,6 +75,29 @@ public class ChatInteraction : StreamInteractionModule, Object {
|
||||||
return (ChatInteraction) stream_interactor.get_module(id);
|
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() {
|
private void check_send_read() {
|
||||||
if (selected_conversation == null || selected_conversation.type_ == Conversation.Type.GROUPCHAT) return;
|
if (selected_conversation == null || selected_conversation.type_ == Conversation.Type.GROUPCHAT) return;
|
||||||
Entities.Message? message = MessageManager.get_instance(stream_interactor).get_last_message(selected_conversation);
|
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() {
|
private bool update_interactions() {
|
||||||
ArrayList<Conversation> remove_input = new ArrayList<Conversation>(Conversation.equals_func);
|
for (MapIterator<Conversation, DateTime> iter = last_input_interaction.map_iterator(); iter.has_next(); iter.next()) {
|
||||||
ArrayList<Conversation> remove_interface = new ArrayList<Conversation>(Conversation.equals_func);
|
if (!iter.valid && iter.has_next()) iter.next();
|
||||||
foreach (Conversation conversation in last_input_interaction.keys) {
|
Conversation conversation = iter.get_key();
|
||||||
if (last_input_interaction.has_key(conversation) &&
|
if (last_input_interaction.has_key(conversation) &&
|
||||||
(new DateTime.now_utc()).difference(last_input_interaction[conversation]) >= 15 * TimeSpan.SECOND) {
|
(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);
|
send_chat_state_notification(conversation, Xep.ChatStateNotifications.STATE_PAUSED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach (Conversation conversation in last_interface_interaction.keys) {
|
for (MapIterator<Conversation, DateTime> 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) &&
|
if (last_interface_interaction.has_key(conversation) &&
|
||||||
(new DateTime.now_utc()).difference(last_interface_interaction[conversation]) >= 1.5 * TimeSpan.MINUTE) {
|
(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);
|
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;
|
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) {
|
private void send_chat_marker(Conversation conversation, Entities.Message message, string marker) {
|
||||||
Core.XmppStream stream = stream_interactor.get_stream(conversation.account);
|
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);
|
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) {
|
private void send_chat_state_notification(Conversation conversation, string state) {
|
||||||
Core.XmppStream stream = stream_interactor.get_stream(conversation.account);
|
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);
|
stream.get_module(Xep.ChatStateNotifications.Module.IDENTITY).send_state(stream, conversation.counterpart.to_string(), state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -38,23 +38,21 @@ public class ChatInput : Box {
|
||||||
this.stream_interactor = stream_interactor;
|
this.stream_interactor = stream_interactor;
|
||||||
scrolled.get_vscrollbar().get_preferred_height(out vscrollbar_min_height, null);
|
scrolled.get_vscrollbar().get_preferred_height(out vscrollbar_min_height, null);
|
||||||
scrolled.vadjustment.notify["upper"].connect_after(on_upper_notify);
|
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) {
|
public void initialize_for_conversation(Conversation conversation) {
|
||||||
if (this.conversation != null) {
|
if (this.conversation != null) entry_cache[this.conversation] = text_input.buffer.text;
|
||||||
if (text_input.buffer.text != "") {
|
|
||||||
entry_cache[this.conversation] = text_input.buffer.text;
|
|
||||||
} else {
|
|
||||||
entry_cache.unset(this.conversation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.conversation = conversation;
|
this.conversation = conversation;
|
||||||
|
|
||||||
|
text_input.buffer.changed.disconnect(on_text_input_changed);
|
||||||
text_input.buffer.text = "";
|
text_input.buffer.text = "";
|
||||||
if (entry_cache.has_key(conversation)) {
|
if (entry_cache.has_key(conversation)) {
|
||||||
text_input.buffer.text = entry_cache[conversation];
|
text_input.buffer.text = entry_cache[conversation];
|
||||||
}
|
}
|
||||||
text_input.key_press_event.connect(on_text_input_key_press);
|
text_input.buffer.changed.connect(on_text_input_changed);
|
||||||
text_input.key_release_event.connect(on_text_input_key_release);
|
|
||||||
text_input.grab_focus();
|
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 != "") {
|
if (text_input.buffer.text != "") {
|
||||||
ChatInteraction.get_instance(stream_interactor).on_message_entered(conversation);
|
ChatInteraction.get_instance(stream_interactor).on_message_entered(conversation);
|
||||||
} else {
|
} else {
|
||||||
ChatInteraction.get_instance(stream_interactor).on_message_cleared(conversation);
|
ChatInteraction.get_instance(stream_interactor).on_message_cleared(conversation);
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -68,12 +68,12 @@ public class UnifiedWindow : Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool on_focus_in_event() {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool on_focus_out_event() {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,12 +67,14 @@ namespace Dino.Plugins.OpenPgp {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void on_jid_key_received(Account account, Jid jid, string key_id) {
|
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) {
|
lock (pgp_key_ids) {
|
||||||
if (!MucManager.get_instance(stream_interactor).is_groupchat_occupant(jid, account)) {
|
if (!pgp_key_ids.has_key(jid) || pgp_key_ids[jid] != key_id) {
|
||||||
db.set_contact_key(jid.bare_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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue