make chat markers opportunistic in private mucs

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java  |  5 
src/main/java/eu/siacs/conversations/entities/Conversation.java          | 28 
src/main/java/eu/siacs/conversations/entities/MucOptions.java            |  4 
src/main/java/eu/siacs/conversations/generator/MessageGenerator.java     |  3 
src/main/java/eu/siacs/conversations/parser/PresenceParser.java          |  2 
src/main/java/eu/siacs/conversations/services/XmppConnectionService.java | 10 
src/main/java/eu/siacs/conversations/ui/ConversationFragment.java        |  2 
7 files changed, 29 insertions(+), 25 deletions(-)

Detailed changes

src/main/java/eu/siacs/conversations/crypto/axolotl/AxolotlService.java 🔗

@@ -788,12 +788,11 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
 	}
 
 	public boolean isConversationAxolotlCapable(Conversation conversation) {
-		return conversation.getMode() == Conversation.MODE_SINGLE || (conversation.getMucOptions().nonanonymous() && conversation.getMucOptions().membersOnly());
+		return conversation.isSingleOrPrivateAndNonAnonymous();
 	}
 
 	public Pair<AxolotlCapability, Jid> isConversationAxolotlCapableDetailed(Conversation conversation) {
-		if (conversation.getMode() == Conversation.MODE_SINGLE
-				|| (conversation.getMucOptions().membersOnly() && conversation.getMucOptions().nonanonymous())) {
+		if (conversation.isSingleOrPrivateAndNonAnonymous()) {
 			final List<Jid> jids = getCryptoTargets(conversation);
 			for (Jid jid : jids) {
 				if (!hasAny(jid) && (!deviceIds.containsKey(jid) || deviceIds.get(jid).isEmpty())) {

src/main/java/eu/siacs/conversations/entities/Conversation.java 🔗

@@ -194,15 +194,13 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 	}
 
 	public boolean setOutgoingChatState(ChatState state) {
-		if (mode == MODE_MULTI && (getNextCounterpart() != null || !isPnNA())) {
-			return false;
-		}
-		if (this.mOutgoingChatState != state) {
-			this.mOutgoingChatState = state;
-			return true;
-		} else {
-			return false;
+		if (mode == MODE_SINGLE || (isPrivateAndNonAnonymous() && getNextCounterpart() == null)) {
+			if (this.mOutgoingChatState != state) {
+				this.mOutgoingChatState = state;
+				return true;
+			}
 		}
+		return false;
 	}
 
 	public ChatState getOutgoingChatState() {
@@ -466,12 +464,12 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 		return unread;
 	}
 
-	public Message getLatestMarkableMessage() {
+	public Message getLatestMarkableMessage(boolean isPrivateAndNonAnonymousMuc) {
 		synchronized (this.messages) {
 			for (int i = this.messages.size() - 1; i >= 0; --i) {
 				final Message message = this.messages.get(i);
 				if (message.getStatus() <= Message.STATUS_RECEIVED
-						&& message.markable
+						&& (message.markable || isPrivateAndNonAnonymousMuc)
 						&& message.getType() != Message.TYPE_PRIVATE) {
 					return message.isRead() ? null : message;
 				}
@@ -697,8 +695,12 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 	/**
 	 * short for is Private and Non-anonymous
 	 */
-	private boolean isPnNA() {
-		return mode == MODE_SINGLE || (getMucOptions().membersOnly() && getMucOptions().nonanonymous());
+	public boolean isSingleOrPrivateAndNonAnonymous() {
+		return mode == MODE_SINGLE || isPrivateAndNonAnonymous();
+	}
+
+	public boolean isPrivateAndNonAnonymous() {
+		return getMucOptions().isPrivateAndNonAnonymous();
 	}
 
 	public synchronized MucOptions getMucOptions() {
@@ -866,7 +868,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 	}
 
 	public boolean alwaysNotify() {
-		return mode == MODE_SINGLE || getBooleanAttribute(ATTRIBUTE_ALWAYS_NOTIFY, Config.ALWAYS_NOTIFY_BY_DEFAULT || isPnNA());
+		return mode == MODE_SINGLE || getBooleanAttribute(ATTRIBUTE_ALWAYS_NOTIFY, Config.ALWAYS_NOTIFY_BY_DEFAULT || isPrivateAndNonAnonymous());
 	}
 
 	public boolean setAttribute(String key, String value) {

src/main/java/eu/siacs/conversations/generator/MessageGenerator.java 🔗

@@ -53,8 +53,7 @@ public class MessageGenerator extends AbstractGenerator {
 			packet.setTo(message.getCounterpart().toBareJid());
 			packet.setType(MessagePacket.TYPE_GROUPCHAT);
 		}
-		if (conversation.getMode() == Conversation.MODE_SINGLE ||
-				(conversation.getMucOptions().nonanonymous() && conversation.getMucOptions().membersOnly() && message.getType() != Message.TYPE_PRIVATE)) {
+		if (conversation.isSingleOrPrivateAndNonAnonymous() && message.getType() != Message.TYPE_PRIVATE) {
 			packet.addChild("markable", "urn:xmpp:chat-markers:0");
 		}
 		packet.setFrom(account.getJid());

src/main/java/eu/siacs/conversations/parser/PresenceParser.java 🔗

@@ -78,7 +78,7 @@ public class PresenceParser extends AbstractParser implements
 						}
 						boolean isNew = mucOptions.updateUser(user);
 						final AxolotlService axolotlService = conversation.getAccount().getAxolotlService();
-						if (isNew && user.getRealJid() != null && mucOptions.membersOnly() && mucOptions.nonanonymous() && axolotlService.hasEmptyDeviceList(user.getRealJid())) {
+						if (isNew && user.getRealJid() != null && mucOptions.isPrivateAndNonAnonymous() && axolotlService.hasEmptyDeviceList(user.getRealJid())) {
 							axolotlService.fetchDeviceIds(user.getRealJid());
 						}
 						if (codes.contains(MucOptions.STATUS_CODE_ROOM_CREATED) && mucOptions.autoPushConfiguration()) {

src/main/java/eu/siacs/conversations/services/XmppConnectionService.java 🔗

@@ -2271,7 +2271,7 @@ public class XmppConnectionService extends Service {
 					if (mucOptions.mamSupport()) {
 						getMessageArchiveService().catchupMUC(conversation);
 					}
-					if (mucOptions.membersOnly() && mucOptions.nonanonymous()) {
+					if (mucOptions.isPrivateAndNonAnonymous()) {
 						fetchConferenceMembers(conversation);
 						if (followedInvite && conversation.getBookmark() == null) {
 							saveConversationAsBookmark(conversation, null);
@@ -3432,15 +3432,15 @@ public class XmppConnectionService extends Service {
 	}
 
 	public void sendReadMarker(final Conversation conversation) {
-		final Message markable = conversation.getLatestMarkableMessage();
+		final boolean isPrivateAndNonAnonymousMuc = conversation.getMode() == Conversation.MODE_MULTI && conversation.isPrivateAndNonAnonymous();
+		final Message markable = conversation.getLatestMarkableMessage(isPrivateAndNonAnonymousMuc);
 		if (this.markRead(conversation)) {
 			updateConversationUi();
 		}
 		if (confirmMessages()
 				&& markable != null
-				&& markable.trusted()
-				&& markable.getRemoteMsgId() != null
-				&& markable.getType() != Message.TYPE_PRIVATE) {
+				&& (markable.trusted() || isPrivateAndNonAnonymousMuc)
+				&& markable.getRemoteMsgId() != null) {
 			Log.d(Config.LOGTAG, conversation.getAccount().getJid().toBareJid() + ": sending read marker to " + markable.getCounterpart().toString());
 			Account account = conversation.getAccount();
 			final Jid to = markable.getCounterpart();

src/main/java/eu/siacs/conversations/ui/ConversationFragment.java 🔗

@@ -1385,7 +1385,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
 					state = ChatState.PAUSED;
 					users = conversation.getMucOptions().getUsersWithChatState(state, 5);
 				}
-				if (mucOptions.membersOnly() && mucOptions.nonanonymous()) {
+				if (mucOptions.isPrivateAndNonAnonymous()) {
 					for (int i = this.messageList.size() - 1; i >= 0; --i) {
 						final Set<ReadByMarker> markersForMessage = messageList.get(i).getReadByMarkers();
 						final List<MucOptions.User> shownMarkers = new ArrayList<>();