use room name (if available and != localpart) as group name

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/entities/Conversation.java          | 22 
src/main/java/eu/siacs/conversations/entities/MucOptions.java            | 60 
src/main/java/eu/siacs/conversations/services/XmppConnectionService.java | 19 
src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java   | 21 
4 files changed, 70 insertions(+), 52 deletions(-)

Detailed changes

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

@@ -55,7 +55,6 @@ 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";
@@ -478,10 +477,13 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 
 	public @NonNull CharSequence getName() {
 		if (getMode() == MODE_MULTI) {
+			final String roomName = getMucOptions().getName();
 			final String subject = getMucOptions().getSubject();
 			final Bookmark bookmark = getBookmark();
 			final String bookmarkName = bookmark != null ? bookmark.getBookmarkName() : null;
-			if (printableValue(subject)) {
+			if (printableValue(roomName)) {
+				return roomName;
+			} else if (printableValue(subject)) {
 				return subject;
 			} else if (printableValue(bookmarkName, false)) {
 				return bookmarkName;
@@ -739,10 +741,20 @@ public class Conversation extends AbstractEntity implements Blockable, Comparabl
 	public boolean setAttribute(String key, String value) {
 		synchronized (this.attributes) {
 			try {
-				this.attributes.put(key, value == null ? "" : value);
-				return true;
+				if (value == null) {
+					if (this.attributes.has(key)) {
+						this.attributes.remove(key);
+						return true;
+					} else {
+						return false;
+					}
+				} else {
+					String prev = this.attributes.getString(key);
+					this.attributes.put(key, value);
+					return !value.equals(prev);
+				}
 			} catch (JSONException e) {
-				return false;
+				throw new AssertionError(e);
 			}
 		}
 	}

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

@@ -1,9 +1,10 @@
 package eu.siacs.conversations.entities;
 
 import android.annotation.SuppressLint;
-import android.util.Log;
+import android.support.annotation.NonNull;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -323,7 +324,7 @@ public class MucOptions {
 		}
 
 		@Override
-		public int compareTo(User another) {
+		public int compareTo(@NonNull User another) {
 			if (another.getAffiliation().outranks(getAffiliation())) {
 				return 1;
 			} else if (getAffiliation().outranks(another.getAffiliation())) {
@@ -359,8 +360,7 @@ public class MucOptions {
 
 	private Account account;
 	private final Set<User> users = new HashSet<>();
-	private final List<String> features = new ArrayList<>();
-	private Data form = new Data();
+	private ServiceDiscoveryResult serviceDiscoveryResult;
 	private final Conversation conversation;
 	private boolean isOnline = false;
 	private Error error = Error.NONE;
@@ -374,34 +374,40 @@ public class MucOptions {
 		this.self = new User(this, createJoinJid(getProposedNick()));
 	}
 
-	public boolean updateConfiguration(List<String> features, String name, 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()));
+	public boolean updateConfiguration(ServiceDiscoveryResult serviceDiscoveryResult) {
+		this.serviceDiscoveryResult = serviceDiscoveryResult;
+		String name;
+		Field roomInfoName = getRoomInfoForm().getFieldByName("muc#roominfo_name");
+		if (roomInfoName != null) {
+			name = roomInfoName.getValue();
+		} else {
+			List<ServiceDiscoveryResult.Identity> identities = serviceDiscoveryResult.getIdentities();
+			String identityName = identities.size() > 0 ? identities.get(0).getName() : null;
+			if (!conversation.getJid().getEscapedLocal().equals(identityName)) {
+				name = identityName;
+			} else {
+				name = null;
+			}
+		}
+		boolean changed = conversation.setAttribute("muc_name", name);
 		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"));
-		changed |= setName(name);
 		return changed;
 	}
 
-	private void updateFeatures(List<String> features) {
-		this.features.clear();
-		this.features.addAll(features);
+
+	private Data getRoomInfoForm() {
+		final List<Data> forms = serviceDiscoveryResult == null ? Collections.emptyList() : serviceDiscoveryResult.forms;
+		return forms.size() == 0 ? new Data() : forms.get(0);
 	}
 
 	public String getAvatar() {
 		return account.getRoster().getContact(conversation.getJid()).getAvatar();
 	}
 
-	private void updateFormData(Data form) {
-		this.form = form;
-	}
-
 	public boolean hasFeature(String feature) {
-		return this.features.contains(feature);
+		return this.serviceDiscoveryResult != null && this.serviceDiscoveryResult.features.contains(feature);
 	}
 
 	public boolean hasVCards() {
@@ -409,17 +415,18 @@ public class MucOptions {
     }
 
 	public boolean canInvite() {
-		Field field = this.form.getFieldByName("muc#roomconfig_allowinvites");
+		Field field = getRoomInfoForm().getFieldByName("muc#roominfo_allowinvites");
 		return !membersOnly() || self.getRole().ranks(Role.MODERATOR) || (field != null && "1".equals(field.getValue()));
 	}
 
 	public boolean canChangeSubject() {
-		Field field = this.form.getFieldByName("muc#roomconfig_changesubject");
+		Field field = getRoomInfoForm().getFieldByName("muc#roominfo_changesubject");
 		return self.getRole().ranks(Role.MODERATOR) || (field != null && "1".equals(field.getValue()));
 	}
 
 	public boolean allowPm() {
-		return conversation.getBooleanAttribute(Conversation.ATTRIBUTE_ALLOW_PM, false);
+		Field field = getRoomInfoForm().getFieldByName("muc#roominfo_allowpm");
+		return field != null && "1".equals(field.getValue());
 	}
 
 	public boolean participating() {
@@ -694,15 +701,12 @@ public class MucOptions {
 		return this.conversation.getAttribute("subject");
 	}
 
-	private boolean setName(String name) {
-		return this.conversation.setAttribute("muc_name", name);
-	}
-
 	public String getName() {
-		return this.conversation.getAttribute("muc_name");
+		String mucName = this.conversation.getAttribute("muc_name");
+		return conversation.getJid().getEscapedLocal().equals(mucName) ? null : mucName;
 	}
 
-	public List<User> getFallbackUsersFromCryptoTargets() {
+	private List<User> getFallbackUsersFromCryptoTargets() {
 		List<User> users = new ArrayList<>();
 		for (Jid jid : conversation.getAcceptedCryptoTargets()) {
 			User user = new User(this, null);

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

@@ -2447,23 +2447,8 @@ public class XmppConnectionService extends Service {
 		sendIqPacket(conversation.getAccount(), request, new OnIqPacketReceived() {
 			@Override
 			public void onIqPacketReceived(Account account, IqPacket packet) {
-				Element query = packet.findChild("query", "http://jabber.org/protocol/disco#info");
-				if (packet.getType() == IqPacket.TYPE.RESULT && query != null) {
-					String name = null;
-					ArrayList<String> features = new ArrayList<>();
-					for (Element child : query.getChildren()) {
-						if (child.getName().equals("feature")) {
-							String var = child.getAttribute("var");
-							if (var != null) {
-								features.add(var);
-							}
-						} else if (child.getName().equals("identity")) {
-							name = child.getAttribute("name");
-						}
-					}
-					Element form = query.findChild("x", Namespace.DATA);
-					Data data = form == null ? null : Data.parse(form);
-					if (conversation.getMucOptions().updateConfiguration(features, name, data)) {
+				if (packet.getType() == IqPacket.TYPE.RESULT) {
+					if (conversation.getMucOptions().updateConfiguration(new ServiceDiscoveryResult(packet))) {
 						Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": muc configuration changed for " + conversation.getJid().asBareJid());
 						updateConversation(conversation);
 					}

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

@@ -50,6 +50,8 @@ import eu.siacs.conversations.utils.UIHelper;
 import eu.siacs.conversations.utils.XmppUri;
 import rocks.xmpp.addr.Jid;
 
+import static eu.siacs.conversations.entities.Bookmark.printableValue;
+
 public class ConferenceDetailsActivity extends XmppActivity implements OnConversationUpdate, OnMucRosterUpdate, XmppConnectionService.OnAffiliationChanged, XmppConnectionService.OnRoleChanged, XmppConnectionService.OnConfigurationPushed {
 	public static final String ACTION_VIEW_MUC = "view_muc";
 
@@ -533,8 +535,23 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
 		this.binding.detailsAccount.setText(getString(R.string.using_account, account));
 		this.binding.jid.setText(mConversation.getJid().asBareJid().toEscapedString());
 		this.binding.yourPhoto.setImageBitmap(avatarService().get(mConversation, getPixel(72)));
-		this.binding.mucTitle.setText(mucOptions.getName());
-		this.binding.mucSubject.setText(mucOptions.getSubject());
+		String roomName = mucOptions.getName();
+		String subject = mucOptions.getSubject();
+		if (printableValue(roomName)) {
+			this.binding.mucTitle.setText(roomName);
+			this.binding.mucTitle.setVisibility(View.VISIBLE);
+		} else if (!printableValue(subject)) {
+			this.binding.mucTitle.setText(mConversation.getName());
+			this.binding.mucTitle.setVisibility(View.VISIBLE);
+		} else {
+			this.binding.mucTitle.setVisibility(View.GONE);
+		}
+		if (printableValue(subject)) {
+			this.binding.mucSubject.setText(mucOptions.getSubject());
+			this.binding.mucSubject.setVisibility(View.VISIBLE);
+		} else {
+			this.binding.mucSubject.setVisibility(View.GONE);
+		}
 		this.binding.mucYourNick.setText(mucOptions.getActualNick());
 		if (mucOptions.online()) {
 			this.binding.mucMoreDetails.setVisibility(View.VISIBLE);