diff --git a/libdino/src/service/chat_interaction.vala b/libdino/src/service/chat_interaction.vala index e273cc32..77176d93 100644 --- a/libdino/src/service/chat_interaction.vala +++ b/libdino/src/service/chat_interaction.vala @@ -171,9 +171,13 @@ public class ChatInteraction : StreamInteractionModule, Object { private void send_chat_state_notification(Conversation conversation, string state) { XmppStream stream = stream_interactor.get_stream(conversation.account); - if (stream != null && conversation.get_send_typing_setting() == Conversation.Setting.ON && - conversation.type_ != Conversation.Type.GROUPCHAT) { - stream.get_module(Xep.ChatStateNotifications.Module.IDENTITY).send_state(stream, conversation.counterpart, state); + if (stream != null && conversation.get_send_typing_setting() == Conversation.Setting.ON) { + if (conversation.type_ != Conversation.Type.GROUPCHAT) { + stream.get_module(Xep.ChatStateNotifications.Module.IDENTITY).send_state(stream, conversation.counterpart, Xmpp.MessageStanza.TYPE_CHAT, state); + } + if (stream_interactor.get_module(MucManager.IDENTITY).is_private_room(conversation.account, conversation.counterpart)) { + stream.get_module(Xep.ChatStateNotifications.Module.IDENTITY).send_state(stream, conversation.counterpart, Xmpp.MessageStanza.TYPE_GROUPCHAT, state); + } } } } diff --git a/libdino/src/service/counterpart_interaction_manager.vala b/libdino/src/service/counterpart_interaction_manager.vala index 68589003..7da65650 100644 --- a/libdino/src/service/counterpart_interaction_manager.vala +++ b/libdino/src/service/counterpart_interaction_manager.vala @@ -52,6 +52,14 @@ public class CounterpartInteractionManager : StreamInteractionModule, Object { Conversation? conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(message); if (conversation == null) return; + // Don't show our own typing notification in MUCs + if (conversation.type_ == Conversation.Type.GROUPCHAT) { + Jid? own_muc_jid = stream_interactor.get_module(MucManager.IDENTITY).get_own_jid(jid.bare_jid, account); + if (own_muc_jid != null && own_muc_jid.equals(jid)) { + return; + } + } + if (!chat_states.has_key(conversation)) { chat_states[conversation] = new HashMap(Jid.hash_func, Jid.equals_func); } diff --git a/libdino/src/service/muc_manager.vala b/libdino/src/service/muc_manager.vala index 534f9d75..c376a5d9 100644 --- a/libdino/src/service/muc_manager.vala +++ b/libdino/src/service/muc_manager.vala @@ -111,6 +111,10 @@ public class MucManager : StreamInteractionModule, Object { return flag.has_room_feature(jid, Xep.Muc.Feature.NON_ANONYMOUS) && flag.has_room_feature(jid, Xep.Muc.Feature.MEMBERS_ONLY); } + public bool is_public_room(Account account, Jid jid) { + return is_groupchat(jid, account) && !is_private_room(account, jid); + } + public Gee.List? get_occupants(Jid jid, Account account) { if (is_groupchat(jid, account)) { Gee.List ret = new ArrayList(Jid.equals_func); diff --git a/main/src/ui/contact_details/settings_provider.vala b/main/src/ui/contact_details/settings_provider.vala index 2f5d31a0..aa397814 100644 --- a/main/src/ui/contact_details/settings_provider.vala +++ b/main/src/ui/contact_details/settings_provider.vala @@ -9,25 +9,33 @@ public class SettingsProvider : Plugins.ContactDetailsProvider, Object { private StreamInteractor stream_interactor; + private string DETAILS_HEADLINE_CHAT = _("Settings"); + private string DETAILS_HEADLINE_ROOM = _("Local Settings"); + public SettingsProvider(StreamInteractor stream_interactor) { this.stream_interactor = stream_interactor; } public void populate(Conversation conversation, Plugins.ContactDetails contact_details, Plugins.WidgetType type) { if (type != Plugins.WidgetType.GTK) return; - if (conversation.type_ == Conversation.Type.CHAT) { + + if (!stream_interactor.get_module(MucManager.IDENTITY).is_public_room(conversation.account, conversation.counterpart)) { + string details_headline = conversation.type_ == Conversation.Type.GROUPCHAT ? DETAILS_HEADLINE_ROOM : DETAILS_HEADLINE_CHAT; + ComboBoxText combobox_typing = get_combobox(Dino.Application.get_default().settings.send_typing); combobox_typing.active_id = get_setting_id(conversation.send_typing); combobox_typing.changed.connect(() => { conversation.send_typing = get_setting(combobox_typing.active_id); } ); - contact_details.add(_("Settings"), _("Send typing notifications"), "", combobox_typing); + contact_details.add(details_headline, _("Send typing notifications"), "", combobox_typing); + } + if (conversation.type_ == Conversation.Type.CHAT) { ComboBoxText combobox_marker = get_combobox(Dino.Application.get_default().settings.send_marker); - contact_details.add(_("Settings"), _("Send read receipts"), "", combobox_marker); + contact_details.add(DETAILS_HEADLINE_CHAT, _("Send read receipts"), "", combobox_marker); combobox_marker.active_id = get_setting_id(conversation.send_marker); combobox_marker.changed.connect(() => { conversation.send_marker = get_setting(combobox_marker.active_id); } ); ComboBoxText combobox_notifications = get_combobox(Dino.Application.get_default().settings.notifications); - contact_details.add(_("Settings"), _("Notifications"), "", combobox_notifications); + contact_details.add(DETAILS_HEADLINE_CHAT, _("Notifications"), "", combobox_notifications); combobox_notifications.active_id = get_notify_setting_id(conversation.notify_setting); combobox_notifications.changed.connect(() => { conversation.notify_setting = get_notify_setting(combobox_notifications.active_id); } ); } else if (conversation.type_ == Conversation.Type.GROUPCHAT) { @@ -36,7 +44,7 @@ public class SettingsProvider : Plugins.ContactDetailsProvider, Object { combobox.append("highlight", get_notify_setting_string(Conversation.NotifySetting.HIGHLIGHT)); combobox.append("on", get_notify_setting_string(Conversation.NotifySetting.ON)); combobox.append("off", get_notify_setting_string(Conversation.NotifySetting.OFF)); - contact_details.add(_("Local Settings"), _("Notifications"), "", combobox); + contact_details.add(DETAILS_HEADLINE_ROOM, _("Notifications"), "", combobox); combobox.active_id = get_notify_setting_id(conversation.notify_setting); combobox.changed.connect(() => { conversation.notify_setting = get_notify_setting(combobox.active_id); } ); } diff --git a/xmpp-vala/CMakeLists.txt b/xmpp-vala/CMakeLists.txt index fba9966d..faff9e79 100644 --- a/xmpp-vala/CMakeLists.txt +++ b/xmpp-vala/CMakeLists.txt @@ -68,6 +68,7 @@ SOURCES "src/module/xep/0280_message_carbons.vala" "src/module/xep/0313_message_archive_management.vala" "src/module/xep/0333_chat_markers.vala" + "src/module/xep/0334_message_processing_hints.vala" "src/module/xep/0363_http_file_upload.vala" "src/module/xep/0368_srv_records_tls.vala" "src/module/xep/0380_explicit_encryption.vala" diff --git a/xmpp-vala/src/module/xep/0085_chat_state_notifications.vala b/xmpp-vala/src/module/xep/0085_chat_state_notifications.vala index e1106597..5a9b0914 100644 --- a/xmpp-vala/src/module/xep/0085_chat_state_notifications.vala +++ b/xmpp-vala/src/module/xep/0085_chat_state_notifications.vala @@ -21,11 +21,12 @@ public class Module : XmppStreamModule { /** * "A message stanza that does not contain standard messaging content [...] SHOULD be a state other than " (0085, 5.6) */ - public void send_state(XmppStream stream, Jid jid, string state) { - MessageStanza message = new MessageStanza(); - message.to = jid; - message.type_ = MessageStanza.TYPE_CHAT; + public void send_state(XmppStream stream, Jid jid, string message_type, string state) { + MessageStanza message = new MessageStanza() { to=jid, type_=message_type }; message.stanza.put_node(new StanzaNode.build(state, NS_URI).add_self_xmlns()); + + MessageProcessingHints.set_message_hint(message, MessageProcessingHints.HINT_NO_STORE); + stream.get_module(MessageModule.IDENTITY).send_message(stream, message); } diff --git a/xmpp-vala/src/module/xep/0334_message_processing_hints.vala b/xmpp-vala/src/module/xep/0334_message_processing_hints.vala new file mode 100644 index 00000000..352e03ac --- /dev/null +++ b/xmpp-vala/src/module/xep/0334_message_processing_hints.vala @@ -0,0 +1,15 @@ +namespace Xmpp.Xep.MessageProcessingHints { + +private const string NS_URI = "urn:xmpp:hints"; + +private const string HINT_NO_PERMANENT_STORE = "no-permanent-store"; +private const string HINT_NO_STORE = "no-store"; +private const string HINT_NO_COPY = "no-copy"; +private const string HINT_STORE = "store"; + +public static void set_message_hint(MessageStanza message, string message_hint) { + StanzaNode hint_node = (new StanzaNode.build(message_hint, NS_URI)).add_self_xmlns(); + message.stanza.put_node(hint_node); +} + +}