diff --git a/src/main/java/eu/siacs/conversations/entities/Conversation.java b/src/main/java/eu/siacs/conversations/entities/Conversation.java index 2626b202b..24f2a2ed7 100644 --- a/src/main/java/eu/siacs/conversations/entities/Conversation.java +++ b/src/main/java/eu/siacs/conversations/entities/Conversation.java @@ -193,7 +193,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl } public boolean setOutgoingChatState(ChatState state) { - if (mode == MODE_MULTI) { + if (mode == MODE_MULTI && getNextCounterpart() != null) { return false; } if (this.mOutgoingChatState != state) { diff --git a/src/main/java/eu/siacs/conversations/entities/MucOptions.java b/src/main/java/eu/siacs/conversations/entities/MucOptions.java index 3b1b64f98..9f9ba0a6b 100644 --- a/src/main/java/eu/siacs/conversations/entities/MucOptions.java +++ b/src/main/java/eu/siacs/conversations/entities/MucOptions.java @@ -7,8 +7,10 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.xml.Namespace; +import eu.siacs.conversations.xmpp.chatstate.ChatState; import eu.siacs.conversations.xmpp.forms.Data; import eu.siacs.conversations.xmpp.forms.Field; import eu.siacs.conversations.xmpp.jid.InvalidJidException; @@ -49,6 +51,18 @@ public class MucOptions { return mAutoPushConfiguration; } + public boolean isSelf(Jid counterpart) { + return counterpart.getResourcepart().equals(getActualNick()); + } + + public void resetChatState() { + synchronized (users) { + for(User user : users) { + user.chatState = Config.DEFAULT_CHATSTATE; + } + } + } + public enum Affiliation { OWNER("owner", 4, R.string.owner), ADMIN("admin", 3, R.string.admin), @@ -154,6 +168,7 @@ public class MucOptions { private long pgpKeyId = 0; private Avatar avatar; private MucOptions options; + private ChatState chatState = Config.DEFAULT_CHATSTATE; public User(MucOptions options, Jid from) { this.options = options; @@ -319,6 +334,14 @@ public class MucOptions { public Jid getRealJid() { return realJid; } + + public boolean setChatState(ChatState chatState) { + if (this.chatState == chatState) { + return false; + } + this.chatState = chatState; + return true; + } } private Account account; @@ -521,6 +544,18 @@ public class MucOptions { } } + public ArrayList getUsersWithChatState(ChatState state) { + synchronized (users) { + ArrayList list = new ArrayList<>(); + for(User user : users) { + if (user.chatState == state) { + list.add(user); + } + } + return list; + } + } + public List getUsers(int max) { ArrayList subset = new ArrayList<>(); HashSet jids = new HashSet<>(); diff --git a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java index ec0922baa..bbe645504 100644 --- a/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java +++ b/src/main/java/eu/siacs/conversations/generator/MessageGenerator.java @@ -155,7 +155,7 @@ public class MessageGenerator extends AbstractGenerator { public MessagePacket generateChatState(Conversation conversation) { final Account account = conversation.getAccount(); MessagePacket packet = new MessagePacket(); - packet.setType(MessagePacket.TYPE_CHAT); + packet.setType(conversation.getMode() == Conversation.MODE_MULTI ? MessagePacket.TYPE_GROUPCHAT : MessagePacket.TYPE_CHAT); packet.setTo(conversation.getJid().toBareJid()); packet.setFrom(account.getJid()); packet.addChild(ChatState.toElement(conversation.getOutgoingChatState())); diff --git a/src/main/java/eu/siacs/conversations/parser/MessageParser.java b/src/main/java/eu/siacs/conversations/parser/MessageParser.java index 620750956..1e9856bc5 100644 --- a/src/main/java/eu/siacs/conversations/parser/MessageParser.java +++ b/src/main/java/eu/siacs/conversations/parser/MessageParser.java @@ -47,20 +47,29 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece super(service); } - private boolean extractChatState(Conversation conversation, final MessagePacket packet) { + private boolean extractChatState(Conversation c, final boolean isTypeGroupChat, final MessagePacket packet) { ChatState state = ChatState.parse(packet); - if (state != null && conversation != null) { - final Account account = conversation.getAccount(); + if (state != null && c != null) { + final Account account = c.getAccount(); Jid from = packet.getFrom(); if (from.toBareJid().equals(account.getJid().toBareJid())) { - conversation.setOutgoingChatState(state); + c.setOutgoingChatState(state); if (state == ChatState.ACTIVE || state == ChatState.COMPOSING) { - mXmppConnectionService.markRead(conversation); + mXmppConnectionService.markRead(c); activateGracePeriod(account); } return false; } else { - return conversation.setIncomingChatState(state); + if (isTypeGroupChat) { + MucOptions.User user = c.getMucOptions().findUserByFullJid(from); + if (user != null) { + return user.setChatState(state); + } else { + return false; + } + } else { + return c.setIncomingChatState(state); + } } } return false; @@ -396,9 +405,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece return; } - if (!isTypeGroupChat - && query == null - && extractChatState(mXmppConnectionService.find(account, counterpart.toBareJid()), packet)) { + if (query == null && extractChatState(mXmppConnectionService.find(account, counterpart.toBareJid()), isTypeGroupChat, packet)) { mXmppConnectionService.updateConversationUi(); } @@ -411,7 +418,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece } if (isTypeGroupChat) { - if (counterpart.getResourcepart().equals(conversation.getMucOptions().getActualNick())) { + if (conversation.getMucOptions().isSelf(counterpart)) { status = Message.STATUS_SEND_RECEIVED; isCarbon = true; //not really carbon but received from another resource if (mXmppConnectionService.markMessage(conversation, remoteMsgId, status, serverMsgId)) { diff --git a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java index aa8618adb..e19d84903 100644 --- a/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/XmppConnectionService.java @@ -2138,7 +2138,11 @@ public class XmppConnectionService extends Service { private void switchToForeground() { final boolean broadcastLastActivity = broadcastLastActivity(); for (Conversation conversation : getConversations()) { - conversation.setIncomingChatState(ChatState.ACTIVE); + if (conversation.getMode() == Conversation.MODE_MULTI) { + conversation.getMucOptions().resetChatState(); + } else { + conversation.setIncomingChatState(Config.DEFAULT_CHATSTATE); + } } for (Account account : getAccounts()) { if (account.getStatus() == Account.State.ONLINE) { diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java index 43fad234f..0b91e26c1 100644 --- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java +++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java @@ -828,7 +828,10 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa } protected void privateMessageWith(final Jid counterpart) { - this.mEditMessage.setText(""); + if (conversation.setOutgoingChatState(Config.DEFAULT_CHATSTATE)) { + activity.xmppConnectionService.sendChatState(conversation); + } + this.mEditMessage.getEditableText().clear(); this.conversation.setNextCounterpart(counterpart); updateChatMsgHint(); updateSendButton();