persist some muc configurations

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/entities/Conversation.java          | 12 
src/main/java/eu/siacs/conversations/entities/MucOptions.java            | 59 
src/main/java/eu/siacs/conversations/services/XmppConnectionService.java |  8 
3 files changed, 48 insertions(+), 31 deletions(-)

Detailed changes

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

@@ -56,6 +56,10 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 	private static final String ATTRIBUTE_NEXT_MESSAGE_TIMESTAMP = "next_message_timestamp";
 	private static final String ATTRIBUTE_CRYPTO_TARGETS = "crypto_targets";
 	private static final String ATTRIBUTE_NEXT_ENCRYPTION = "next_encryption";
+	public static final String ATTRIBUTE_ALLOW_PM = "allow_pm";
+	public static final String ATTRIBUTE_MEMBERS_ONLY = "members_only";
+	public static final String ATTRIBUTE_MODERATED = "moderated";
+	public static final String ATTRIBUTE_NON_ANONYMOUS = "non_anonymous";
 	protected final ArrayList<Message> messages = new ArrayList<>();
 	public AtomicBoolean messagesLoaded = new AtomicBoolean(true);
 	protected Account account = null;
@@ -725,6 +729,12 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 		return mode == MODE_SINGLE || getBooleanAttribute(ATTRIBUTE_ALWAYS_NOTIFY, Config.ALWAYS_NOTIFY_BY_DEFAULT || isPrivateAndNonAnonymous());
 	}
 
+	public boolean setAttribute(String key, boolean value) {
+		boolean prev = getBooleanAttribute(key,false);
+		setAttribute(key,Boolean.toString(value));
+		return prev != value;
+	}
+
 	private boolean setAttribute(String key, long value) {
 		return setAttribute(key, Long.toString(value));
 	}
@@ -811,7 +821,7 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 		}
 	}
 
-	private boolean getBooleanAttribute(String key, boolean defaultValue) {
+	public boolean getBooleanAttribute(String key, boolean defaultValue) {
 		String value = this.getAttribute(key);
 		if (value == null) {
 			return defaultValue;

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

@@ -58,7 +58,7 @@ public class MucOptions {
 
 	public void resetChatState() {
 		synchronized (users) {
-			for(User user : users) {
+			for (User user : users) {
 				user.chatState = Config.DEFAULT_CHATSTATE;
 			}
 		}
@@ -100,10 +100,10 @@ public class MucOptions {
 	}
 
 	public enum Role {
-		MODERATOR("moderator", R.string.moderator,3),
-		VISITOR("visitor", R.string.visitor,1),
-		PARTICIPANT("participant", R.string.participant,2),
-		NONE("none", R.string.no_role,0);
+		MODERATOR("moderator", R.string.moderator, 3),
+		VISITOR("visitor", R.string.visitor, 1),
+		PARTICIPANT("participant", R.string.participant, 2),
+		NONE("none", R.string.no_role, 0);
 
 		Role(String string, int resId, int rank) {
 			this.string = string;
@@ -256,7 +256,7 @@ public class MucOptions {
 		public Contact getContact() {
 			if (fullJid != null) {
 				return getAccount().getRoster().getContactFromRoster(realJid);
-			} else if (realJid != null){
+			} else if (realJid != null) {
 				return getAccount().getRoster().getContact(realJid);
 			} else {
 				return null;
@@ -314,7 +314,7 @@ public class MucOptions {
 
 		@Override
 		public String toString() {
-			return "[fulljid:"+String.valueOf(fullJid)+",realjid:"+String.valueOf(realJid)+",affiliation"+affiliation.toString()+"]";
+			return "[fulljid:" + String.valueOf(fullJid) + ",realjid:" + String.valueOf(realJid) + ",affiliation" + affiliation.toString() + "]";
 		}
 
 		public boolean realJidMatchesAccount() {
@@ -370,15 +370,27 @@ public class MucOptions {
 	public MucOptions(Conversation conversation) {
 		this.account = conversation.getAccount();
 		this.conversation = conversation;
-		this.self = new User(this,createJoinJid(getProposedNick()));
+		this.self = new User(this, createJoinJid(getProposedNick()));
+	}
+
+	public boolean updateConfiguration(List<String> features, Data data) {
+		updateFeatures(features);
+		updateFormData(data == null ? new Data() : data);
+		Field allowPmField = this.form.getFieldByName("muc#roomconfig_allowpm");
+		boolean changed = false;
+		changed |= conversation.setAttribute(Conversation.ATTRIBUTE_ALLOW_PM, allowPmField == null || "1".equals(allowPmField.getValue()));
+		changed |= conversation.setAttribute(Conversation.ATTRIBUTE_MEMBERS_ONLY, this.hasFeature("muc_membersonly"));
+		changed |= conversation.setAttribute(Conversation.ATTRIBUTE_MODERATED, this.hasFeature("muc_moderated"));
+		changed |= conversation.setAttribute(Conversation.ATTRIBUTE_NON_ANONYMOUS, this.hasFeature("muc_nonanonymous"));
+		return changed;
 	}
 
-	public void updateFeatures(ArrayList<String> features) {
+	private void updateFeatures(List<String> features) {
 		this.features.clear();
 		this.features.addAll(features);
 	}
 
-	public void updateFormData(Data form) {
+	private void updateFormData(Data form) {
 		this.form = form;
 	}
 
@@ -397,8 +409,7 @@ public class MucOptions {
 	}
 
 	public boolean allowPm() {
-		Field field = this.form.getFieldByName("muc#roomconfig_allowpm");
-		return field == null || "1".equals(field.getValue());
+		return conversation.getBooleanAttribute(Conversation.ATTRIBUTE_ALLOW_PM, false);
 	}
 
 	public boolean participating() {
@@ -408,7 +419,7 @@ public class MucOptions {
 	}
 
 	public boolean membersOnly() {
-		return hasFeature("muc_membersonly");
+		return conversation.getBooleanAttribute(Conversation.ATTRIBUTE_MEMBERS_ONLY, false);
 	}
 
 	public boolean mamSupport() {
@@ -420,19 +431,15 @@ public class MucOptions {
 	}
 
 	public boolean nonanonymous() {
-		return hasFeature("muc_nonanonymous");
+		return conversation.getBooleanAttribute(Conversation.ATTRIBUTE_NON_ANONYMOUS, false);
 	}
 
 	public boolean isPrivateAndNonAnonymous() {
 		return membersOnly() && nonanonymous();
 	}
 
-	public boolean persistent() {
-		return hasFeature("muc_persistent");
-	}
-
 	public boolean moderated() {
-		return hasFeature("muc_moderated");
+		return conversation.getBooleanAttribute(Conversation.ATTRIBUTE_MODERATED, false);
 	}
 
 	public User deleteUser(Jid jid) {
@@ -497,7 +504,7 @@ public class MucOptions {
 			boolean fullJidIsSelf = isOnline && user.getFullJid() != null && user.getFullJid().equals(self.getFullJid());
 			if ((!membersOnly() || user.getAffiliation().ranks(Affiliation.MEMBER))
 					&& user.getAffiliation().outranks(Affiliation.OUTCAST)
-					&& !fullJidIsSelf){
+					&& !fullJidIsSelf) {
 				this.users.add(user);
 				return !realJidFound && user.realJid != null;
 			}
@@ -537,7 +544,7 @@ public class MucOptions {
 		if (readByMarker.getRealJid() != null) {
 			User user = findUserByRealJid(readByMarker.getRealJid().asBareJid());
 			if (user == null) {
-				user = new User(this,readByMarker.getFullJid());
+				user = new User(this, readByMarker.getFullJid());
 				user.setRealJid(readByMarker.getRealJid());
 			}
 			return user;
@@ -590,7 +597,7 @@ public class MucOptions {
 	public ArrayList<User> getUsersWithChatState(ChatState state, int max) {
 		synchronized (users) {
 			ArrayList<User> list = new ArrayList<>();
-			for(User user : users) {
+			for (User user : users) {
 				if (user.chatState == state) {
 					list.add(user);
 					if (list.size() >= max) {
@@ -607,7 +614,7 @@ public class MucOptions {
 		HashSet<Jid> jids = new HashSet<>();
 		jids.add(account.getJid().asBareJid());
 		synchronized (users) {
-			for(User user : users) {
+			for (User user : users) {
 				if (user.getRealJid() == null || jids.add(user.getRealJid())) {
 					subset.add(user);
 				}
@@ -670,7 +677,7 @@ public class MucOptions {
 	}
 
 	public boolean setSubject(String subject) {
-		return this.conversation.setAttribute("subject",subject);
+		return this.conversation.setAttribute("subject", subject);
 	}
 
 	public String getSubject() {
@@ -679,8 +686,8 @@ public class MucOptions {
 
 	public List<User> getFallbackUsersFromCryptoTargets() {
 		List<User> users = new ArrayList<>();
-		for(Jid jid : conversation.getAcceptedCryptoTargets()) {
-			User user = new User(this,null);
+		for (Jid jid : conversation.getAcceptedCryptoTargets()) {
+			User user = new User(this, null);
 			user.setRealJid(jid);
 			users.add(user);
 		}

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

@@ -2510,14 +2510,14 @@ public class XmppConnectionService extends Service {
 						}
 					}
 					Element form = query.findChild("x", Namespace.DATA);
-					if (form != null) {
-						conversation.getMucOptions().updateFormData(Data.parse(form));
+					Data data = form == null ? null : Data.parse(form);
+					if (conversation.getMucOptions().updateConfiguration(features, data)) {
+						Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": muc configuration changed for " + conversation.getJid().asBareJid());
+						updateConversation(conversation);
 					}
-					conversation.getMucOptions().updateFeatures(features);
 					if (callback != null) {
 						callback.onConferenceConfigurationFetched(conversation);
 					}
-					Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": fetched muc configuration for " + conversation.getJid().asBareJid() + " - " + features.toString());
 					updateConversationUi();
 				} else if (packet.getType() == IqPacket.TYPE.ERROR) {
 					if (callback != null) {