ConferenceDetailsActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.annotation.TargetApi;
  4import android.app.AlertDialog;
  5import android.app.PendingIntent;
  6import android.content.Context;
  7import android.content.DialogInterface;
  8import android.content.IntentSender.SendIntentException;
  9import android.graphics.Bitmap;
 10import android.os.Build;
 11import android.os.Bundle;
 12import android.view.ContextMenu;
 13import android.view.LayoutInflater;
 14import android.view.Menu;
 15import android.view.MenuItem;
 16import android.view.View;
 17import android.view.View.OnClickListener;
 18import android.widget.Button;
 19import android.widget.ImageButton;
 20import android.widget.ImageView;
 21import android.widget.LinearLayout;
 22import android.widget.TableLayout;
 23import android.widget.TextView;
 24import android.widget.Toast;
 25
 26import org.openintents.openpgp.util.OpenPgpUtils;
 27
 28import java.util.ArrayList;
 29import java.util.Collections;
 30import java.util.Comparator;
 31import java.util.concurrent.atomic.AtomicInteger;
 32
 33import eu.siacs.conversations.Config;
 34import eu.siacs.conversations.R;
 35import eu.siacs.conversations.crypto.PgpEngine;
 36import eu.siacs.conversations.entities.Account;
 37import eu.siacs.conversations.entities.Bookmark;
 38import eu.siacs.conversations.entities.Contact;
 39import eu.siacs.conversations.entities.Conversation;
 40import eu.siacs.conversations.entities.MucOptions;
 41import eu.siacs.conversations.entities.MucOptions.User;
 42import eu.siacs.conversations.services.XmppConnectionService;
 43import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdate;
 44import eu.siacs.conversations.services.XmppConnectionService.OnMucRosterUpdate;
 45import eu.siacs.conversations.xmpp.jid.Jid;
 46
 47public class ConferenceDetailsActivity extends XmppActivity implements OnConversationUpdate, OnMucRosterUpdate, XmppConnectionService.OnAffiliationChanged, XmppConnectionService.OnRoleChanged, XmppConnectionService.OnConferenceOptionsPushed {
 48	public static final String ACTION_VIEW_MUC = "view_muc";
 49	private Conversation mConversation;
 50	private OnClickListener inviteListener = new OnClickListener() {
 51
 52		@Override
 53		public void onClick(View v) {
 54			inviteToConversation(mConversation);
 55		}
 56	};
 57	private TextView mYourNick;
 58	private ImageView mYourPhoto;
 59	private ImageButton mEditNickButton;
 60	private TextView mRoleAffiliaton;
 61	private TextView mFullJid;
 62	private TextView mAccountJid;
 63	private LinearLayout membersView;
 64	private LinearLayout mMoreDetails;
 65	private TextView mConferenceType;
 66	private TableLayout mConferenceInfoTable;
 67	private TextView mConferenceInfoMam;
 68	private TextView mNotifyStatusText;
 69	private ImageButton mChangeConferenceSettingsButton;
 70	private ImageButton mNotifyStatusButton;
 71	private Button mInviteButton;
 72	private String uuid = null;
 73	private User mSelectedUser = null;
 74
 75	private boolean mAdvancedMode = false;
 76
 77	private UiCallback<Conversation> renameCallback = new UiCallback<Conversation>() {
 78		@Override
 79		public void success(Conversation object) {
 80			runOnUiThread(new Runnable() {
 81				@Override
 82				public void run() {
 83					Toast.makeText(ConferenceDetailsActivity.this,getString(R.string.your_nick_has_been_changed),Toast.LENGTH_SHORT).show();
 84					updateView();
 85				}
 86			});
 87
 88		}
 89
 90		@Override
 91		public void error(final int errorCode, Conversation object) {
 92			runOnUiThread(new Runnable() {
 93				@Override
 94				public void run() {
 95					Toast.makeText(ConferenceDetailsActivity.this,getString(errorCode),Toast.LENGTH_SHORT).show();
 96				}
 97			});
 98		}
 99
100		@Override
101		public void userInputRequried(PendingIntent pi, Conversation object) {
102
103		}
104	};
105
106	private OnClickListener mNotifyStatusClickListener = new OnClickListener() {
107		@Override
108		public void onClick(View v) {
109			AlertDialog.Builder builder = new AlertDialog.Builder(ConferenceDetailsActivity.this);
110			builder.setTitle(R.string.pref_notification_settings);
111			String[] choices = {
112					getString(R.string.notify_on_all_messages),
113					getString(R.string.notify_only_when_highlighted),
114					getString(R.string.notify_never)
115			};
116			final AtomicInteger choice;
117			if (mConversation.getLongAttribute(Conversation.ATTRIBUTE_MUTED_TILL,0) == Long.MAX_VALUE) {
118				choice = new AtomicInteger(2);
119			} else {
120				choice = new AtomicInteger(mConversation.alwaysNotify() ? 0 : 1);
121			}
122			builder.setSingleChoiceItems(choices, choice.get(), new DialogInterface.OnClickListener() {
123				@Override
124				public void onClick(DialogInterface dialog, int which) {
125					choice.set(which);
126				}
127			});
128			builder.setNegativeButton(R.string.cancel, null);
129			builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
130				@Override
131				public void onClick(DialogInterface dialog, int which) {
132					if (choice.get() == 2) {
133						mConversation.setMutedTill(Long.MAX_VALUE);
134					} else {
135						mConversation.setMutedTill(0);
136						mConversation.setAttribute(Conversation.ATTRIBUTE_ALWAYS_NOTIFY,String.valueOf(choice.get() == 0));
137					}
138					xmppConnectionService.updateConversation(mConversation);
139					updateView();
140				}
141			});
142			builder.create().show();
143		}
144	};
145
146	private OnClickListener mChangeConferenceSettings = new OnClickListener() {
147		@Override
148		public void onClick(View v) {
149			final MucOptions mucOptions = mConversation.getMucOptions();
150			AlertDialog.Builder builder = new AlertDialog.Builder(ConferenceDetailsActivity.this);
151			builder.setTitle(R.string.conference_options);
152			final String[] options;
153			final boolean[] values;
154			if (mAdvancedMode) {
155				options = new String[]{
156						getString(R.string.members_only),
157						getString(R.string.moderated),
158						getString(R.string.non_anonymous)
159				};
160				values = new boolean[]{
161						mucOptions.membersOnly(),
162						mucOptions.moderated(),
163						mucOptions.nonanonymous()
164				};
165			} else {
166				options = new String[]{
167						getString(R.string.members_only),
168						getString(R.string.non_anonymous)
169				};
170				values = new boolean[]{
171						mucOptions.membersOnly(),
172						mucOptions.nonanonymous()
173				};
174			}
175			builder.setMultiChoiceItems(options,values,new DialogInterface.OnMultiChoiceClickListener() {
176				@Override
177				public void onClick(DialogInterface dialog, int which, boolean isChecked) {
178					values[which] = isChecked;
179				}
180			});
181			builder.setNegativeButton(R.string.cancel, null);
182			builder.setPositiveButton(R.string.confirm,new DialogInterface.OnClickListener() {
183				@Override
184				public void onClick(DialogInterface dialog, int which) {
185					if (!mucOptions.membersOnly() && values[0]) {
186						xmppConnectionService.changeAffiliationsInConference(mConversation,
187								MucOptions.Affiliation.NONE,
188								MucOptions.Affiliation.MEMBER);
189					}
190					Bundle options = new Bundle();
191					options.putString("muc#roomconfig_membersonly", values[0] ? "1" : "0");
192					if (values.length == 2) {
193						options.putString("muc#roomconfig_whois", values[1] ? "anyone" : "moderators");
194					} else if (values.length == 3) {
195						options.putString("muc#roomconfig_moderatedroom", values[1] ? "1" : "0");
196						options.putString("muc#roomconfig_whois", values[2] ? "anyone" : "moderators");
197					}
198					options.putString("muc#roomconfig_persistentroom", "1");
199					xmppConnectionService.pushConferenceConfiguration(mConversation,
200							options,
201							ConferenceDetailsActivity.this);
202				}
203			});
204			builder.create().show();
205		}
206	};
207	private OnValueEdited onSubjectEdited = new OnValueEdited() {
208
209		@Override
210		public void onValueEdited(String value) {
211			xmppConnectionService.pushSubjectToConference(mConversation,value);
212		}
213	};
214
215	@Override
216	public void onConversationUpdate() {
217		refreshUi();
218	}
219
220	@Override
221	public void onMucRosterUpdate() {
222		refreshUi();
223	}
224
225	@Override
226	protected void refreshUiReal() {
227		updateView();
228	}
229
230	@Override
231	protected void onCreate(Bundle savedInstanceState) {
232		super.onCreate(savedInstanceState);
233		setContentView(R.layout.activity_muc_details);
234		mYourNick = (TextView) findViewById(R.id.muc_your_nick);
235		mYourPhoto = (ImageView) findViewById(R.id.your_photo);
236		mEditNickButton = (ImageButton) findViewById(R.id.edit_nick_button);
237		mFullJid = (TextView) findViewById(R.id.muc_jabberid);
238		membersView = (LinearLayout) findViewById(R.id.muc_members);
239		mAccountJid = (TextView) findViewById(R.id.details_account);
240		mMoreDetails = (LinearLayout) findViewById(R.id.muc_more_details);
241		mMoreDetails.setVisibility(View.GONE);
242		mChangeConferenceSettingsButton = (ImageButton) findViewById(R.id.change_conference_button);
243		mChangeConferenceSettingsButton.setOnClickListener(this.mChangeConferenceSettings);
244		mInviteButton = (Button) findViewById(R.id.invite);
245		mInviteButton.setOnClickListener(inviteListener);
246		mConferenceType = (TextView) findViewById(R.id.muc_conference_type);
247		if (getActionBar() != null) {
248			getActionBar().setHomeButtonEnabled(true);
249			getActionBar().setDisplayHomeAsUpEnabled(true);
250		}
251		mEditNickButton.setOnClickListener(new OnClickListener() {
252
253			@Override
254			public void onClick(View v) {
255				quickEdit(mConversation.getMucOptions().getActualNick(),
256						new OnValueEdited() {
257
258							@Override
259							public void onValueEdited(String value) {
260								xmppConnectionService.renameInMuc(mConversation,value,renameCallback);
261							}
262						});
263			}
264		});
265		this.mAdvancedMode = getPreferences().getBoolean("advanced_muc_mode", false);
266		this.mConferenceInfoTable = (TableLayout) findViewById(R.id.muc_info_more);
267		mConferenceInfoTable.setVisibility(this.mAdvancedMode ? View.VISIBLE : View.GONE);
268		this.mConferenceInfoMam = (TextView) findViewById(R.id.muc_info_mam);
269		this.mNotifyStatusButton = (ImageButton) findViewById(R.id.notification_status_button);
270		this.mNotifyStatusButton.setOnClickListener(this.mNotifyStatusClickListener);
271		this.mNotifyStatusText = (TextView) findViewById(R.id.notification_status_text);
272	}
273
274	@Override
275	public boolean onOptionsItemSelected(MenuItem menuItem) {
276		switch (menuItem.getItemId()) {
277			case android.R.id.home:
278				finish();
279				break;
280			case R.id.action_edit_subject:
281				if (mConversation != null) {
282					quickEdit(mConversation.getName(),this.onSubjectEdited);
283				}
284				break;
285			case R.id.action_save_as_bookmark:
286				saveAsBookmark();
287				break;
288			case R.id.action_delete_bookmark:
289				deleteBookmark();
290				break;
291			case R.id.action_advanced_mode:
292				this.mAdvancedMode = !menuItem.isChecked();
293				menuItem.setChecked(this.mAdvancedMode);
294				getPreferences().edit().putBoolean("advanced_muc_mode", mAdvancedMode).commit();
295				mConferenceInfoTable.setVisibility(this.mAdvancedMode ? View.VISIBLE : View.GONE);
296				invalidateOptionsMenu();
297				updateView();
298				break;
299		}
300		return super.onOptionsItemSelected(menuItem);
301	}
302
303	@Override
304	protected String getShareableUri() {
305		if (mConversation != null) {
306			return "xmpp:" + mConversation.getJid().toBareJid().toString() + "?join";
307		} else {
308			return "";
309		}
310	}
311
312	@Override
313	public boolean onPrepareOptionsMenu(Menu menu) {
314		MenuItem menuItemSaveBookmark = menu.findItem(R.id.action_save_as_bookmark);
315		MenuItem menuItemDeleteBookmark = menu.findItem(R.id.action_delete_bookmark);
316		MenuItem menuItemAdvancedMode = menu.findItem(R.id.action_advanced_mode);
317		MenuItem menuItemChangeSubject = menu.findItem(R.id.action_edit_subject);
318		menuItemAdvancedMode.setChecked(mAdvancedMode);
319		if (mConversation == null) {
320			return true;
321		}
322		Account account = mConversation.getAccount();
323		if (account.hasBookmarkFor(mConversation.getJid().toBareJid())) {
324			menuItemSaveBookmark.setVisible(false);
325			menuItemDeleteBookmark.setVisible(true);
326		} else {
327			menuItemDeleteBookmark.setVisible(false);
328			menuItemSaveBookmark.setVisible(true);
329		}
330		menuItemChangeSubject.setVisible(mConversation.getMucOptions().canChangeSubject());
331		return true;
332	}
333
334	@Override
335	public boolean onCreateOptionsMenu(Menu menu) {
336		getMenuInflater().inflate(R.menu.muc_details, menu);
337		return true;
338	}
339
340	@Override
341	public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
342		Object tag = v.getTag();
343		if (tag instanceof User) {
344			getMenuInflater().inflate(R.menu.muc_details_context,menu);
345			final User user = (User) tag;
346			final User self = mConversation.getMucOptions().getSelf();
347			this.mSelectedUser = user;
348			String name;
349			final Contact contact = user.getContact();
350			if (contact != null) {
351				name = contact.getDisplayName();
352			} else if (user.getJid() != null){
353				name = user.getJid().toBareJid().toString();
354			} else {
355				name = user.getName();
356			}
357			menu.setHeaderTitle(name);
358			if (user.getJid() != null) {
359				MenuItem showContactDetails = menu.findItem(R.id.action_contact_details);
360				MenuItem startConversation = menu.findItem(R.id.start_conversation);
361				MenuItem giveMembership = menu.findItem(R.id.give_membership);
362				MenuItem removeMembership = menu.findItem(R.id.remove_membership);
363				MenuItem giveAdminPrivileges = menu.findItem(R.id.give_admin_privileges);
364				MenuItem removeAdminPrivileges = menu.findItem(R.id.remove_admin_privileges);
365				MenuItem removeFromRoom = menu.findItem(R.id.remove_from_room);
366				MenuItem banFromConference = menu.findItem(R.id.ban_from_conference);
367				startConversation.setVisible(true);
368				if (contact != null) {
369					showContactDetails.setVisible(true);
370				}
371				if (self.getAffiliation().ranks(MucOptions.Affiliation.ADMIN) &&
372						self.getAffiliation().outranks(user.getAffiliation())) {
373					if (mAdvancedMode) {
374						if (user.getAffiliation() == MucOptions.Affiliation.NONE) {
375							giveMembership.setVisible(true);
376						} else {
377							removeMembership.setVisible(true);
378						}
379						banFromConference.setVisible(true);
380					} else {
381						removeFromRoom.setVisible(true);
382					}
383					if (user.getAffiliation() != MucOptions.Affiliation.ADMIN) {
384						giveAdminPrivileges.setVisible(true);
385					} else {
386						removeAdminPrivileges.setVisible(true);
387					}
388				}
389			} else {
390				MenuItem sendPrivateMessage = menu.findItem(R.id.send_private_message);
391				sendPrivateMessage.setVisible(true);
392			}
393
394		}
395		super.onCreateContextMenu(menu, v, menuInfo);
396	}
397
398	@Override
399	public boolean onContextItemSelected(MenuItem item) {
400		switch (item.getItemId()) {
401			case R.id.action_contact_details:
402				Contact contact = mSelectedUser.getContact();
403				if (contact != null) {
404					switchToContactDetails(contact);
405				}
406				return true;
407			case R.id.start_conversation:
408				startConversation(mSelectedUser);
409				return true;
410			case R.id.give_admin_privileges:
411				xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.ADMIN,this);
412				return true;
413			case R.id.give_membership:
414				xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.MEMBER,this);
415				return true;
416			case R.id.remove_membership:
417				xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.NONE,this);
418				return true;
419			case R.id.remove_admin_privileges:
420				xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.MEMBER,this);
421				return true;
422			case R.id.remove_from_room:
423				removeFromRoom(mSelectedUser);
424				return true;
425			case R.id.ban_from_conference:
426				xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.OUTCAST,this);
427				xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,this);
428				return true;
429			case R.id.send_private_message:
430				privateMsgInMuc(mConversation,mSelectedUser.getName());
431				return true;
432			default:
433				return super.onContextItemSelected(item);
434		}
435	}
436
437	private void removeFromRoom(final User user) {
438		if (mConversation.getMucOptions().membersOnly()) {
439			xmppConnectionService.changeAffiliationInConference(mConversation,user.getJid(), MucOptions.Affiliation.NONE,this);
440			xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,ConferenceDetailsActivity.this);
441		} else {
442			AlertDialog.Builder builder = new AlertDialog.Builder(this);
443			builder.setTitle(R.string.ban_from_conference);
444			builder.setMessage(getString(R.string.removing_from_public_conference,user.getName()));
445			builder.setNegativeButton(R.string.cancel,null);
446			builder.setPositiveButton(R.string.ban_now,new DialogInterface.OnClickListener() {
447				@Override
448				public void onClick(DialogInterface dialog, int which) {
449					xmppConnectionService.changeAffiliationInConference(mConversation,user.getJid(), MucOptions.Affiliation.OUTCAST,ConferenceDetailsActivity.this);
450					xmppConnectionService.changeRoleInConference(mConversation,mSelectedUser.getName(), MucOptions.Role.NONE,ConferenceDetailsActivity.this);
451				}
452			});
453			builder.create().show();
454		}
455	}
456
457	protected void startConversation(User user) {
458		if (user.getJid() != null) {
459			Conversation conversation = xmppConnectionService.findOrCreateConversation(this.mConversation.getAccount(),user.getJid().toBareJid(),false);
460			switchToConversation(conversation);
461		}
462	}
463
464	protected void saveAsBookmark() {
465		Account account = mConversation.getAccount();
466		Bookmark bookmark = new Bookmark(account, mConversation.getJid().toBareJid());
467		if (!mConversation.getJid().isBareJid()) {
468			bookmark.setNick(mConversation.getJid().getResourcepart());
469		}
470		bookmark.setBookmarkName(mConversation.getMucOptions().getSubject());
471		bookmark.setAutojoin(true);
472		account.getBookmarks().add(bookmark);
473		xmppConnectionService.pushBookmarks(account);
474		mConversation.setBookmark(bookmark);
475	}
476
477	protected void deleteBookmark() {
478		Account account = mConversation.getAccount();
479		Bookmark bookmark = mConversation.getBookmark();
480		bookmark.unregisterConversation();
481		account.getBookmarks().remove(bookmark);
482		xmppConnectionService.pushBookmarks(account);
483	}
484
485	@Override
486	void onBackendConnected() {
487		if (mPendingConferenceInvite != null) {
488			mPendingConferenceInvite.execute(this);
489			mPendingConferenceInvite = null;
490		}
491		if (getIntent().getAction().equals(ACTION_VIEW_MUC)) {
492			this.uuid = getIntent().getExtras().getString("uuid");
493		}
494		if (uuid != null) {
495			this.mConversation = xmppConnectionService
496				.findConversationByUuid(uuid);
497			if (this.mConversation != null) {
498				updateView();
499			}
500		}
501	}
502
503	private void updateView() {
504		final MucOptions mucOptions = mConversation.getMucOptions();
505		final User self = mucOptions.getSelf();
506		String account;
507		if (Config.DOMAIN_LOCK != null) {
508			account = mConversation.getAccount().getJid().getLocalpart();
509		} else {
510			account = mConversation.getAccount().getJid().toBareJid().toString();
511		}
512		mAccountJid.setText(getString(R.string.using_account, account));
513		mYourPhoto.setImageBitmap(avatarService().get(mConversation.getAccount(), getPixel(48)));
514		setTitle(mConversation.getName());
515		mFullJid.setText(mConversation.getJid().toBareJid().toString());
516		mYourNick.setText(mucOptions.getActualNick());
517		mRoleAffiliaton = (TextView) findViewById(R.id.muc_role);
518		if (mucOptions.online()) {
519			mMoreDetails.setVisibility(View.VISIBLE);
520			final String status = getStatus(self);
521			if (status != null) {
522				mRoleAffiliaton.setVisibility(View.VISIBLE);
523				mRoleAffiliaton.setText(status);
524			} else {
525				mRoleAffiliaton.setVisibility(View.GONE);
526			}
527			if (mucOptions.membersOnly()) {
528				mConferenceType.setText(R.string.private_conference);
529			} else {
530				mConferenceType.setText(R.string.public_conference);
531			}
532			if (mucOptions.mamSupport()) {
533				mConferenceInfoMam.setText(R.string.server_info_available);
534			} else {
535				mConferenceInfoMam.setText(R.string.server_info_unavailable);
536			}
537			if (self.getAffiliation().ranks(MucOptions.Affiliation.OWNER)) {
538				mChangeConferenceSettingsButton.setVisibility(View.VISIBLE);
539			} else {
540				mChangeConferenceSettingsButton.setVisibility(View.GONE);
541			}
542		}
543
544		long mutedTill = mConversation.getLongAttribute(Conversation.ATTRIBUTE_MUTED_TILL,0);
545		if (mutedTill == Long.MAX_VALUE) {
546			mNotifyStatusText.setText(R.string.notify_never);
547			mNotifyStatusButton.setImageResource(R.drawable.ic_notifications_off_grey600_24dp);
548		} else if (System.currentTimeMillis() < mutedTill) {
549			mNotifyStatusText.setText(R.string.notify_paused);
550			mNotifyStatusButton.setImageResource(R.drawable.ic_notifications_paused_grey600_24dp);
551		} else if (mConversation.alwaysNotify()) {
552			mNotifyStatusButton.setImageResource(R.drawable.ic_notifications_grey600_24dp);
553			mNotifyStatusText.setText(R.string.notify_on_all_messages);
554		} else {
555			mNotifyStatusButton.setImageResource(R.drawable.ic_notifications_none_grey600_24dp);
556			mNotifyStatusText.setText(R.string.notify_only_when_highlighted);
557		}
558
559		LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
560		membersView.removeAllViews();
561		final ArrayList<User> users = mucOptions.getUsers();
562		Collections.sort(users,new Comparator<User>() {
563			@Override
564			public int compare(User lhs, User rhs) {
565				return lhs.getName().compareToIgnoreCase(rhs.getName());
566			}
567		});
568		for (final User user : users) {
569			View view = inflater.inflate(R.layout.contact, membersView,false);
570			this.setListItemBackgroundOnView(view);
571			view.setOnClickListener(new OnClickListener() {
572				@Override
573				public void onClick(View view) {
574					highlightInMuc(mConversation, user.getName());
575				}
576			});
577			registerForContextMenu(view);
578			view.setTag(user);
579			TextView tvDisplayName = (TextView) view.findViewById(R.id.contact_display_name);
580			TextView tvKey = (TextView) view.findViewById(R.id.key);
581			TextView tvStatus = (TextView) view.findViewById(R.id.contact_jid);
582			if (mAdvancedMode && user.getPgpKeyId() != 0) {
583				tvKey.setVisibility(View.VISIBLE);
584				tvKey.setOnClickListener(new OnClickListener() {
585
586					@Override
587					public void onClick(View v) {
588						viewPgpKey(user);
589					}
590				});
591				tvKey.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId()));
592			}
593			Contact contact = user.getContact();
594			if (contact != null) {
595				tvDisplayName.setText(contact.getDisplayName());
596				tvStatus.setText(user.getName() + " \u2022 " + getStatus(user));
597			} else {
598				tvDisplayName.setText(user.getName());
599				tvStatus.setText(getStatus(user));
600
601			}
602			ImageView iv = (ImageView) view.findViewById(R.id.contact_photo);
603			iv.setImageBitmap(avatarService().get(user, getPixel(48), false));
604			membersView.addView(view);
605			if (mConversation.getMucOptions().canInvite()) {
606				mInviteButton.setVisibility(View.VISIBLE);
607			} else {
608				mInviteButton.setVisibility(View.GONE);
609			}
610		}
611	}
612
613	private String getStatus(User user) {
614		if (mAdvancedMode) {
615			StringBuilder builder = new StringBuilder();
616			builder.append(getString(user.getAffiliation().getResId()));
617			builder.append(" (");
618			builder.append(getString(user.getRole().getResId()));
619			builder.append(')');
620			return builder.toString();
621		} else {
622			return getString(user.getAffiliation().getResId());
623		}
624	}
625
626	@SuppressWarnings("deprecation")
627	@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
628	private void setListItemBackgroundOnView(View view) {
629		int sdk = android.os.Build.VERSION.SDK_INT;
630		if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
631			view.setBackgroundDrawable(getResources().getDrawable(R.drawable.greybackground));
632		} else {
633			view.setBackground(getResources().getDrawable(R.drawable.greybackground));
634		}
635	}
636
637	private void viewPgpKey(User user) {
638		PgpEngine pgp = xmppConnectionService.getPgpEngine();
639		if (pgp != null) {
640			PendingIntent intent = pgp.getIntentForKey(
641					mConversation.getAccount(), user.getPgpKeyId());
642			if (intent != null) {
643				try {
644					startIntentSenderForResult(intent.getIntentSender(), 0,
645							null, 0, 0, 0);
646				} catch (SendIntentException ignored) {
647
648				}
649			}
650		}
651	}
652
653	@Override
654	public void onAffiliationChangedSuccessful(Jid jid) {
655
656	}
657
658	@Override
659	public void onAffiliationChangeFailed(Jid jid, int resId) {
660		displayToast(getString(resId,jid.toBareJid().toString()));
661	}
662
663	@Override
664	public void onRoleChangedSuccessful(String nick) {
665
666	}
667
668	@Override
669	public void onRoleChangeFailed(String nick, int resId) {
670		displayToast(getString(resId,nick));
671	}
672
673	@Override
674	public void onPushSucceeded() {
675		displayToast(getString(R.string.modified_conference_options));
676	}
677
678	@Override
679	public void onPushFailed() {
680		displayToast(getString(R.string.could_not_modify_conference_options));
681	}
682
683	private void displayToast(final String msg) {
684		runOnUiThread(new Runnable() {
685			@Override
686			public void run() {
687				Toast.makeText(ConferenceDetailsActivity.this,msg,Toast.LENGTH_SHORT).show();
688			}
689		});
690	}
691}