basic affiliation changes in muc

Daniel Gultsch created

Change summary

src/main/java/eu/siacs/conversations/entities/MucOptions.java            | 48 
src/main/java/eu/siacs/conversations/generator/IqGenerator.java          | 11 
src/main/java/eu/siacs/conversations/services/XmppConnectionService.java | 22 
src/main/java/eu/siacs/conversations/ui/ConferenceDetailsActivity.java   | 76 
src/main/res/menu/muc_details_context.xml                                | 23 
src/main/res/values/strings.xml                                          |  6 
6 files changed, 160 insertions(+), 26 deletions(-)

Detailed changes

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

@@ -17,40 +17,64 @@ import android.annotation.SuppressLint;
 public class MucOptions {
 
 	public enum Affiliation {
-		OWNER(R.string.owner),
-		ADMIN(R.string.admin),
-		MEMBER(R.string.member),
-		OUTCAST(R.string.outcast),
-		NONE(R.string.no_affiliation);
-
-		private Affiliation(int resId) {
+		OWNER("owner", 4, R.string.owner),
+		ADMIN("admin", 3, R.string.admin),
+		MEMBER("member", 2, R.string.member),
+		OUTCAST("outcast", 0, R.string.outcast),
+		NONE("none", 1, R.string.no_affiliation);
+
+		private Affiliation(String string, int rank, int resId) {
+			this.string = string;
 			this.resId = resId;
+			this.rank = rank;
 		}
 
+		private String string;
 		private int resId;
+		private int rank;
 
 		public int getResId() {
 			return resId;
 		}
+
+		@Override
+		public String toString() {
+			return this.string;
+		}
+
+		public boolean outranks(Affiliation affiliation) {
+			return rank > affiliation.rank;
+		}
+
+		public boolean ranks(Affiliation affiliation) {
+			return rank >= affiliation.rank;
+		}
 	}
 
 	;
 
 	public enum Role {
-		MODERATOR(R.string.moderator),
-		VISITOR(R.string.visitor),
-		PARTICIPANT(R.string.participant),
-		NONE(R.string.no_role);
+		MODERATOR("moderator", R.string.moderator),
+		VISITOR("visitor", R.string.visitor),
+		PARTICIPANT("participant", R.string.participant),
+		NONE("none", R.string.no_role);
 
-		private Role(int resId) {
+		private Role(String string, int resId) {
+			this.string = string;
 			this.resId = resId;
 		}
 
+		private String string;
 		private int resId;
 
 		public int getResId() {
 			return resId;
 		}
+
+		@Override
+		public String toString() {
+			return this.string;
+		}
 	}
 
 	public static final int ERROR_NO_ERROR = 0;

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

@@ -5,6 +5,7 @@ import java.util.Collections;
 import java.util.List;
 
 import eu.siacs.conversations.entities.Account;
+import eu.siacs.conversations.entities.Conversation;
 import eu.siacs.conversations.services.MessageArchiveService;
 import eu.siacs.conversations.services.XmppConnectionService;
 import eu.siacs.conversations.utils.Xmlns;
@@ -148,4 +149,14 @@ public class IqGenerator extends AbstractGenerator {
 		query.addChild("password").setContent(newPassword);
 		return packet;
 	}
+
+	public IqPacket changeAffiliation(Conversation conference, Jid jid, String affiliation) {
+		IqPacket packet = new IqPacket(IqPacket.TYPE.SET);
+		packet.setTo(conference.getJid().toBareJid());
+		packet.setFrom(conference.getAccount().getJid());
+		Element item = packet.query("http://jabber.org/protocol/muc#admin").addChild("item");
+		item.setAttribute("jid", jid.toString());
+		item.setAttribute("affiliation", affiliation);
+		return packet;
+	}
 }

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

@@ -1516,6 +1516,28 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa
 		});
 	}
 
+	public void changeAffiliationInConference(final Conversation conference, Jid user, MucOptions.Affiliation affiliation, final OnAffiliationChanged callback) {
+		final Jid jid = user.toBareJid();
+		IqPacket request = this.mIqGenerator.changeAffiliation(conference, jid, affiliation.toString());
+		Log.d(Config.LOGTAG,request.toString());
+		sendIqPacket(conference.getAccount(),request,new OnIqPacketReceived() {
+			@Override
+			public void onIqPacketReceived(Account account, IqPacket packet) {
+				Log.d(Config.LOGTAG,packet.toString());
+				if (packet.getType() == IqPacket.TYPE.RESULT) {
+					callback.onAffiliationChangedSuccessful(jid);
+				} else {
+					callback.onAffiliationChangeFailed(jid,R.string.could_not_change_affiliation);
+				}
+			}
+		});
+	}
+
+	public interface OnAffiliationChanged {
+		public void onAffiliationChangedSuccessful(Jid jid);
+		public void onAffiliationChangeFailed(Jid jid, int resId);
+	}
+
 	public void disconnect(Account account, boolean force) {
 		if ((account.getStatus() == Account.State.ONLINE)
 				|| (account.getStatus() == Account.State.DISABLED)) {

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

@@ -33,11 +33,13 @@ import eu.siacs.conversations.entities.Contact;
 import eu.siacs.conversations.entities.Conversation;
 import eu.siacs.conversations.entities.MucOptions;
 import eu.siacs.conversations.entities.MucOptions.User;
+import eu.siacs.conversations.services.XmppConnectionService;
 import eu.siacs.conversations.services.XmppConnectionService.OnMucRosterUpdate;
 import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdate;
+import eu.siacs.conversations.xmpp.jid.Jid;
 import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
 
-public class ConferenceDetailsActivity extends XmppActivity implements OnConversationUpdate, OnMucRosterUpdate {
+public class ConferenceDetailsActivity extends XmppActivity implements OnConversationUpdate, OnMucRosterUpdate, XmppConnectionService.OnAffiliationChanged {
 	public static final String ACTION_VIEW_MUC = "view_muc";
 	private Conversation mConversation;
 	private OnClickListener inviteListener = new OnClickListener() {
@@ -222,21 +224,44 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
 		if (tag instanceof User) {
 			getMenuInflater().inflate(R.menu.muc_details_context,menu);
 			final User user = (User) tag;
+			final User self = mConversation.getMucOptions().getSelf();
 			this.mSelectedUser = user;
 			String name;
-			final Contact contact = user.getContact();
-			if (contact != null) {
-				name = contact.getDisplayName();
-			} else if (user.getJid() != null) {
-				name = user.getJid().toBareJid().toString();
-			} else {
-				name = user.getName();
-			}
-			menu.setHeaderTitle(name);
-			MenuItem startConversation = menu.findItem(R.id.start_conversation);
-			if (user.getJid() == null) {
-				startConversation.setVisible(false);
+			if (user.getJid() != null) {
+				final Contact contact = user.getContact();
+				if (contact != null) {
+					name = contact.getDisplayName();
+				} else if (user.getJid() != null) {
+					name = user.getJid().toBareJid().toString();
+				} else {
+					name = user.getName();
+				}
+				menu.setHeaderTitle(name);
+				MenuItem startConversation = menu.findItem(R.id.start_conversation);
+				MenuItem giveMembership = menu.findItem(R.id.give_membership);
+				MenuItem removeMembership = menu.findItem(R.id.remove_membership);
+				MenuItem giveAdminPrivileges = menu.findItem(R.id.give_admin_privileges);
+				MenuItem removeAdminPrivileges = menu.findItem(R.id.remove_admin_privileges);
+				MenuItem removeFromRoom = menu.findItem(R.id.remove_from_room);
+				startConversation.setVisible(true);
+				if (self.getAffiliation().ranks(MucOptions.Affiliation.ADMIN) &&
+						self.getAffiliation().outranks(user.getAffiliation())) {
+					if (mAdvancedMode) {
+						if (user.getAffiliation() == MucOptions.Affiliation.NONE) {
+							giveMembership.setVisible(true);
+						} else {
+							removeMembership.setVisible(true);
+						}
+					}
+					if (user.getAffiliation() != MucOptions.Affiliation.ADMIN) {
+						giveAdminPrivileges.setVisible(true);
+					} else {
+						removeAdminPrivileges.setVisible(true);
+					}
+					removeFromRoom.setVisible(true);
+				}
 			}
+
 		}
 		super.onCreateContextMenu(menu,v,menuInfo);
 	}
@@ -247,6 +272,21 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
 			case R.id.start_conversation:
 				startConversation(mSelectedUser);
 				return true;
+			case R.id.give_admin_privileges:
+				xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.ADMIN,this);
+				return true;
+			case R.id.give_membership:
+				xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.MEMBER,this);
+				return true;
+			case R.id.remove_membership:
+				xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.NONE,this);
+				return true;
+			case R.id.remove_admin_privileges:
+				xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.MEMBER,this);
+				return true;
+			case R.id.remove_from_room:
+				xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.OUTCAST,this);
+				return true;
 			default:
 				return super.onContextItemSelected(item);
 		}
@@ -399,4 +439,14 @@ public class ConferenceDetailsActivity extends XmppActivity implements OnConvers
 			}
 		}
 	}
+
+	@Override
+	public void onAffiliationChangedSuccessful(Jid jid) {
+
+	}
+
+	@Override
+	public void onAffiliationChangeFailed(Jid jid, int resId) {
+
+	}
 }

src/main/res/menu/muc_details_context.xml 🔗

@@ -3,5 +3,26 @@
     <item
         android:id="@+id/start_conversation"
         android:title="@string/start_conversation"
-        />
+        android:visible="false" />
+	<item
+		android:id="@+id/give_membership"
+        android:title="@string/grant_membership"
+		android:visible="false" />
+	<item
+		android:id="@+id/give_admin_privileges"
+        android:title="@string/grant_admin_privileges"
+		android:visible="false"/>
+	<item
+		android:id="@+id/remove_admin_privileges"
+        android:title="@string/remove_admin_privileges"
+		android:visible="false"/>
+
+	<item
+		android:id="@+id/remove_membership"
+		android:title="@string/remove_membership"
+		android:visible="false"/>
+	<item
+		android:id="@+id/remove_from_room"
+        android:title="@string/remove_from_room"
+		android:visible="false"/>
 </menu>

src/main/res/values/strings.xml 🔗

@@ -411,4 +411,10 @@
 	<string name="outcast">Outcast</string>
 	<string name="member">Member</string>
 	<string name="advanced_mode">Advanced mode</string>
+	<string name="grant_membership">Grant membership</string>
+	<string name="remove_membership">Remove membership</string>
+	<string name="grant_admin_privileges">Grant admin privileges</string>
+	<string name="remove_admin_privileges">Remove admin privileges</string>
+	<string name="remove_from_room">Remove from room</string>
+	<string name="could_not_change_affiliation">Could not change affiliation</string>
 </resources>