1package eu.siacs.conversations.ui;
2
3import android.annotation.TargetApi;
4import android.app.PendingIntent;
5import android.content.Context;
6import android.content.IntentSender.SendIntentException;
7import android.graphics.Bitmap;
8import android.os.Build;
9import android.os.Bundle;
10import android.view.ContextMenu;
11import android.view.LayoutInflater;
12import android.view.Menu;
13import android.view.MenuItem;
14import android.view.View;
15import android.view.View.OnClickListener;
16import android.widget.Button;
17import android.widget.ImageButton;
18import android.widget.ImageView;
19import android.widget.LinearLayout;
20import android.widget.TextView;
21import android.widget.Toast;
22
23import org.openintents.openpgp.util.OpenPgpUtils;
24
25import java.util.ArrayList;
26import java.util.List;
27
28import eu.siacs.conversations.R;
29import eu.siacs.conversations.crypto.PgpEngine;
30import eu.siacs.conversations.entities.Account;
31import eu.siacs.conversations.entities.Bookmark;
32import eu.siacs.conversations.entities.Contact;
33import eu.siacs.conversations.entities.Conversation;
34import eu.siacs.conversations.entities.MucOptions;
35import eu.siacs.conversations.entities.MucOptions.User;
36import eu.siacs.conversations.services.XmppConnectionService;
37import eu.siacs.conversations.services.XmppConnectionService.OnMucRosterUpdate;
38import eu.siacs.conversations.services.XmppConnectionService.OnConversationUpdate;
39import eu.siacs.conversations.xmpp.jid.Jid;
40import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
41
42public class ConferenceDetailsActivity extends XmppActivity implements OnConversationUpdate, OnMucRosterUpdate, XmppConnectionService.OnAffiliationChanged {
43 public static final String ACTION_VIEW_MUC = "view_muc";
44 private Conversation mConversation;
45 private OnClickListener inviteListener = new OnClickListener() {
46
47 @Override
48 public void onClick(View v) {
49 inviteToConversation(mConversation);
50 }
51 };
52 private TextView mYourNick;
53 private ImageView mYourPhoto;
54 private ImageButton mEditNickButton;
55 private TextView mRoleAffiliaton;
56 private TextView mFullJid;
57 private TextView mAccountJid;
58 private LinearLayout membersView;
59 private LinearLayout mMoreDetails;
60 private Button mInviteButton;
61 private String uuid = null;
62 private List<User> users = new ArrayList<>();
63 private User mSelectedUser = null;
64
65 private boolean mAdvancedMode = false;
66
67 private UiCallback<Conversation> renameCallback = new UiCallback<Conversation>() {
68 @Override
69 public void success(Conversation object) {
70 runOnUiThread(new Runnable() {
71 @Override
72 public void run() {
73 Toast.makeText(ConferenceDetailsActivity.this,getString(R.string.your_nick_has_been_changed),Toast.LENGTH_SHORT).show();
74 updateView();
75 }
76 });
77
78 }
79
80 @Override
81 public void error(final int errorCode, Conversation object) {
82 runOnUiThread(new Runnable() {
83 @Override
84 public void run() {
85 Toast.makeText(ConferenceDetailsActivity.this,getString(errorCode),Toast.LENGTH_SHORT).show();
86 }
87 });
88 }
89
90 @Override
91 public void userInputRequried(PendingIntent pi, Conversation object) {
92
93 }
94 };
95
96 @Override
97 public void onConversationUpdate() {
98 runOnUiThread(new Runnable() {
99
100 @Override
101 public void run() {
102 updateView();
103 }
104 });
105 }
106
107 @Override
108 public void onMucRosterUpdate() {
109 runOnUiThread(new Runnable() {
110
111 @Override
112 public void run() {
113 updateView();
114 }
115 });
116 }
117
118 @Override
119 protected void onCreate(Bundle savedInstanceState) {
120 super.onCreate(savedInstanceState);
121 setContentView(R.layout.activity_muc_details);
122 mYourNick = (TextView) findViewById(R.id.muc_your_nick);
123 mYourPhoto = (ImageView) findViewById(R.id.your_photo);
124 mEditNickButton = (ImageButton) findViewById(R.id.edit_nick_button);
125 mFullJid = (TextView) findViewById(R.id.muc_jabberid);
126 membersView = (LinearLayout) findViewById(R.id.muc_members);
127 mAccountJid = (TextView) findViewById(R.id.details_account);
128 mMoreDetails = (LinearLayout) findViewById(R.id.muc_more_details);
129 mMoreDetails.setVisibility(View.GONE);
130 mInviteButton = (Button) findViewById(R.id.invite);
131 mInviteButton.setOnClickListener(inviteListener);
132 if (getActionBar() != null) {
133 getActionBar().setHomeButtonEnabled(true);
134 getActionBar().setDisplayHomeAsUpEnabled(true);
135 }
136 mEditNickButton.setOnClickListener(new OnClickListener() {
137
138 @Override
139 public void onClick(View v) {
140 quickEdit(mConversation.getMucOptions().getActualNick(),
141 new OnValueEdited() {
142
143 @Override
144 public void onValueEdited(String value) {
145 xmppConnectionService.renameInMuc(mConversation,value,renameCallback);
146 }
147 });
148 }
149 });
150 }
151
152 @Override
153 public boolean onOptionsItemSelected(MenuItem menuItem) {
154 switch (menuItem.getItemId()) {
155 case android.R.id.home:
156 finish();
157 break;
158 case R.id.action_edit_subject:
159 if (mConversation != null) {
160 quickEdit(mConversation.getName(), new OnValueEdited() {
161
162 @Override
163 public void onValueEdited(String value) {
164 MessagePacket packet = xmppConnectionService
165 .getMessageGenerator().conferenceSubject(
166 mConversation, value);
167 xmppConnectionService.sendMessagePacket(
168 mConversation.getAccount(), packet);
169 }
170 });
171 }
172 break;
173 case R.id.action_save_as_bookmark:
174 saveAsBookmark();
175 break;
176 case R.id.action_delete_bookmark:
177 deleteBookmark();
178 break;
179 case R.id.action_advanced_mode:
180 this.mAdvancedMode = !menuItem.isChecked();
181 menuItem.setChecked(this.mAdvancedMode);
182 invalidateOptionsMenu();
183 updateView();
184 break;
185 }
186 return super.onOptionsItemSelected(menuItem);
187 }
188
189 @Override
190 protected String getShareableUri() {
191 if (mConversation != null) {
192 return "xmpp:" + mConversation.getJid().toBareJid().toString() + "?join";
193 } else {
194 return "";
195 }
196 }
197
198 @Override
199 public boolean onPrepareOptionsMenu(Menu menu) {
200 MenuItem menuItemSaveBookmark = menu.findItem(R.id.action_save_as_bookmark);
201 MenuItem menuItemDeleteBookmark = menu.findItem(R.id.action_delete_bookmark);
202 MenuItem menuItemAdvancedMode = menu.findItem(R.id.action_advanced_mode);
203 menuItemAdvancedMode.setChecked(mAdvancedMode);
204 Account account = mConversation.getAccount();
205 if (account.hasBookmarkFor(mConversation.getJid().toBareJid())) {
206 menuItemSaveBookmark.setVisible(false);
207 menuItemDeleteBookmark.setVisible(true);
208 } else {
209 menuItemDeleteBookmark.setVisible(false);
210 menuItemSaveBookmark.setVisible(true);
211 }
212 return true;
213 }
214
215 @Override
216 public boolean onCreateOptionsMenu(Menu menu) {
217 getMenuInflater().inflate(R.menu.muc_details, menu);
218 return true;
219 }
220
221 @Override
222 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
223 Object tag = v.getTag();
224 if (tag instanceof User) {
225 getMenuInflater().inflate(R.menu.muc_details_context,menu);
226 final User user = (User) tag;
227 final User self = mConversation.getMucOptions().getSelf();
228 this.mSelectedUser = user;
229 String name;
230 if (user.getJid() != null) {
231 final Contact contact = user.getContact();
232 if (contact != null) {
233 name = contact.getDisplayName();
234 } else if (user.getJid() != null) {
235 name = user.getJid().toBareJid().toString();
236 } else {
237 name = user.getName();
238 }
239 menu.setHeaderTitle(name);
240 MenuItem startConversation = menu.findItem(R.id.start_conversation);
241 MenuItem giveMembership = menu.findItem(R.id.give_membership);
242 MenuItem removeMembership = menu.findItem(R.id.remove_membership);
243 MenuItem giveAdminPrivileges = menu.findItem(R.id.give_admin_privileges);
244 MenuItem removeAdminPrivileges = menu.findItem(R.id.remove_admin_privileges);
245 MenuItem removeFromRoom = menu.findItem(R.id.remove_from_room);
246 startConversation.setVisible(true);
247 if (self.getAffiliation().ranks(MucOptions.Affiliation.ADMIN) &&
248 self.getAffiliation().outranks(user.getAffiliation())) {
249 if (mAdvancedMode) {
250 if (user.getAffiliation() == MucOptions.Affiliation.NONE) {
251 giveMembership.setVisible(true);
252 } else {
253 removeMembership.setVisible(true);
254 }
255 }
256 if (user.getAffiliation() != MucOptions.Affiliation.ADMIN) {
257 giveAdminPrivileges.setVisible(true);
258 } else {
259 removeAdminPrivileges.setVisible(true);
260 }
261 removeFromRoom.setVisible(true);
262 }
263 }
264
265 }
266 super.onCreateContextMenu(menu,v,menuInfo);
267 }
268
269 @Override
270 public boolean onContextItemSelected(MenuItem item) {
271 switch (item.getItemId()) {
272 case R.id.start_conversation:
273 startConversation(mSelectedUser);
274 return true;
275 case R.id.give_admin_privileges:
276 xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.ADMIN,this);
277 return true;
278 case R.id.give_membership:
279 xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.MEMBER,this);
280 return true;
281 case R.id.remove_membership:
282 xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.NONE,this);
283 return true;
284 case R.id.remove_admin_privileges:
285 xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.MEMBER,this);
286 return true;
287 case R.id.remove_from_room:
288 xmppConnectionService.changeAffiliationInConference(mConversation,mSelectedUser.getJid(), MucOptions.Affiliation.OUTCAST,this);
289 return true;
290 default:
291 return super.onContextItemSelected(item);
292 }
293 }
294
295 protected void startConversation(User user) {
296 if (user.getJid() != null) {
297 Conversation conversation = xmppConnectionService.findOrCreateConversation(this.mConversation.getAccount(),user.getJid().toBareJid(),false);
298 switchToConversation(conversation);
299 }
300 }
301
302 protected void saveAsBookmark() {
303 Account account = mConversation.getAccount();
304 Bookmark bookmark = new Bookmark(account, mConversation.getJid().toBareJid());
305 if (!mConversation.getJid().isBareJid()) {
306 bookmark.setNick(mConversation.getJid().getResourcepart());
307 }
308 bookmark.setAutojoin(true);
309 account.getBookmarks().add(bookmark);
310 xmppConnectionService.pushBookmarks(account);
311 mConversation.setBookmark(bookmark);
312 }
313
314 protected void deleteBookmark() {
315 Account account = mConversation.getAccount();
316 Bookmark bookmark = mConversation.getBookmark();
317 bookmark.unregisterConversation();
318 account.getBookmarks().remove(bookmark);
319 xmppConnectionService.pushBookmarks(account);
320 }
321
322 @Override
323 void onBackendConnected() {
324 if (getIntent().getAction().equals(ACTION_VIEW_MUC)) {
325 this.uuid = getIntent().getExtras().getString("uuid");
326 }
327 if (uuid != null) {
328 this.mConversation = xmppConnectionService
329 .findConversationByUuid(uuid);
330 if (this.mConversation != null) {
331 updateView();
332 }
333 }
334 }
335
336 private void updateView() {
337 mAccountJid.setText(getString(R.string.using_account, mConversation
338 .getAccount().getJid().toBareJid()));
339 mYourPhoto.setImageBitmap(avatarService().get(mConversation.getAccount(), getPixel(48)));
340 setTitle(mConversation.getName());
341 mFullJid.setText(mConversation.getJid().toBareJid().toString());
342 mYourNick.setText(mConversation.getMucOptions().getActualNick());
343 mRoleAffiliaton = (TextView) findViewById(R.id.muc_role);
344 if (mConversation.getMucOptions().online()) {
345 mMoreDetails.setVisibility(View.VISIBLE);
346 User self = mConversation.getMucOptions().getSelf();
347 final String status = getStatus(self);
348 if (status != null) {
349 mRoleAffiliaton.setVisibility(View.VISIBLE);
350 mRoleAffiliaton.setText(status);
351 } else {
352 mRoleAffiliaton.setVisibility(View.GONE);
353 }
354 }
355 this.users.clear();
356 this.users.addAll(mConversation.getMucOptions().getUsers());
357 LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
358 membersView.removeAllViews();
359 for (final User user : mConversation.getMucOptions().getUsers()) {
360 View view = inflater.inflate(R.layout.contact, membersView,
361 false);
362 this.setListItemBackgroundOnView(view);
363 view.setOnClickListener(new OnClickListener() {
364 @Override
365 public void onClick(View view) {
366 highlightInMuc(mConversation, user.getName());
367 }
368 });
369 registerForContextMenu(view);
370 view.setTag(user);
371 TextView tvDisplayName = (TextView) view.findViewById(R.id.contact_display_name);
372 TextView tvKey = (TextView) view.findViewById(R.id.key);
373 TextView tvStatus = (TextView) view.findViewById(R.id.contact_jid);
374 if (mAdvancedMode && user.getPgpKeyId() != 0) {
375 tvKey.setVisibility(View.VISIBLE);
376 tvKey.setOnClickListener(new OnClickListener() {
377
378 @Override
379 public void onClick(View v) {
380 viewPgpKey(user);
381 }
382 });
383 tvKey.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId()));
384 }
385 Bitmap bm;
386 Contact contact = user.getContact();
387 if (contact != null) {
388 bm = avatarService().get(contact, getPixel(48));
389 tvDisplayName.setText(contact.getDisplayName());
390 tvStatus.setText(user.getName() + " \u2022 " + getStatus(user));
391 } else {
392 bm = avatarService().get(user.getName(), getPixel(48));
393 tvDisplayName.setText(user.getName());
394 tvStatus.setText(getStatus(user));
395
396 }
397 ImageView iv = (ImageView) view.findViewById(R.id.contact_photo);
398 iv.setImageBitmap(bm);
399 membersView.addView(view);
400 }
401 }
402
403 private String getStatus(User user) {
404 if (mAdvancedMode) {
405 StringBuilder builder = new StringBuilder();
406 builder.append(getString(user.getAffiliation().getResId()));
407 builder.append(" (");
408 builder.append(getString(user.getRole().getResId()));
409 builder.append(')');
410 return builder.toString();
411 } else {
412 return getString(user.getAffiliation().getResId());
413 }
414 }
415
416 @SuppressWarnings("deprecation")
417 @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
418 private void setListItemBackgroundOnView(View view) {
419 int sdk = android.os.Build.VERSION.SDK_INT;
420 if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) {
421 view.setBackgroundDrawable(getResources().getDrawable(R.drawable.greybackground));
422 } else {
423 view.setBackground(getResources().getDrawable(R.drawable.greybackground));
424 }
425 }
426
427 private void viewPgpKey(User user) {
428 PgpEngine pgp = xmppConnectionService.getPgpEngine();
429 if (pgp != null) {
430 PendingIntent intent = pgp.getIntentForKey(
431 mConversation.getAccount(), user.getPgpKeyId());
432 if (intent != null) {
433 try {
434 startIntentSenderForResult(intent.getIntentSender(), 0,
435 null, 0, 0, 0);
436 } catch (SendIntentException ignored) {
437
438 }
439 }
440 }
441 }
442
443 @Override
444 public void onAffiliationChangedSuccessful(Jid jid) {
445
446 }
447
448 @Override
449 public void onAffiliationChangeFailed(Jid jid, int resId) {
450
451 }
452}