MucDetailsContextMenuHelper.java

  1package eu.siacs.conversations.ui.util;
  2
  3import android.app.Activity;
  4import android.preference.PreferenceManager;
  5import android.text.SpannableString;
  6import android.text.Spanned;
  7import android.text.style.TypefaceSpan;
  8import android.view.ContextMenu;
  9import android.view.Menu;
 10import android.view.MenuItem;
 11import android.view.View;
 12import com.google.android.material.dialog.MaterialAlertDialogBuilder;
 13import eu.siacs.conversations.Config;
 14import eu.siacs.conversations.R;
 15import eu.siacs.conversations.entities.Account;
 16import eu.siacs.conversations.entities.Contact;
 17import eu.siacs.conversations.entities.Conversation;
 18import eu.siacs.conversations.entities.MucOptions;
 19import eu.siacs.conversations.entities.MucOptions.User;
 20import eu.siacs.conversations.services.XmppConnectionService;
 21import eu.siacs.conversations.ui.ConferenceDetailsActivity;
 22import eu.siacs.conversations.ui.ConversationFragment;
 23import eu.siacs.conversations.ui.ConversationsActivity;
 24import eu.siacs.conversations.ui.MucUsersActivity;
 25import eu.siacs.conversations.ui.XmppActivity;
 26import eu.siacs.conversations.xmpp.Jid;
 27
 28public final class MucDetailsContextMenuHelper {
 29
 30    public static void onCreateContextMenu(ContextMenu menu, View v) {
 31        final XmppActivity activity = XmppActivity.find(v);
 32        final Object tag = v.getTag();
 33        if (tag instanceof User user && activity != null) {
 34            activity.getMenuInflater().inflate(R.menu.muc_details_context, menu);
 35            String name;
 36            final Contact contact = user.getContact();
 37            if (contact != null && contact.showInContactList()) {
 38                name = contact.getDisplayName();
 39            } else if (user.getRealJid() != null) {
 40                name = user.getRealJid().asBareJid().toString();
 41            } else {
 42                name = user.getName();
 43            }
 44            menu.setHeaderTitle(name);
 45            MucDetailsContextMenuHelper.configureMucDetailsContextMenu(
 46                    activity, menu, user.getConversation(), user);
 47        }
 48    }
 49
 50    public static void configureMucDetailsContextMenu(
 51            Activity activity, Menu menu, Conversation conversation, User user) {
 52        final MucOptions mucOptions = conversation.getMucOptions();
 53        final boolean advancedMode =
 54                PreferenceManager.getDefaultSharedPreferences(activity)
 55                        .getBoolean("advanced_muc_mode", false);
 56        final boolean isGroupChat = mucOptions.isPrivateAndNonAnonymous();
 57        MenuItem sendPrivateMessage = menu.findItem(R.id.send_private_message);
 58        if (user != null && user.getRealJid() != null) {
 59            MenuItem showContactDetails = menu.findItem(R.id.action_contact_details);
 60            MenuItem startConversation = menu.findItem(R.id.start_conversation);
 61            MenuItem giveMembership = menu.findItem(R.id.give_membership);
 62            MenuItem removeMembership = menu.findItem(R.id.remove_membership);
 63            MenuItem giveAdminPrivileges = menu.findItem(R.id.give_admin_privileges);
 64            MenuItem giveOwnerPrivileges = menu.findItem(R.id.give_owner_privileges);
 65            MenuItem removeOwnerPrivileges = menu.findItem(R.id.revoke_owner_privileges);
 66            MenuItem removeAdminPrivileges = menu.findItem(R.id.remove_admin_privileges);
 67            MenuItem removeFromRoom = menu.findItem(R.id.remove_from_room);
 68            MenuItem managePermissions = menu.findItem(R.id.manage_permissions);
 69            removeFromRoom.setTitle(
 70                    isGroupChat ? R.string.remove_from_room : R.string.remove_from_channel);
 71            MenuItem banFromConference = menu.findItem(R.id.ban_from_conference);
 72            banFromConference.setTitle(
 73                    isGroupChat ? R.string.ban_from_conference : R.string.ban_from_channel);
 74            MenuItem invite = menu.findItem(R.id.invite);
 75            startConversation.setVisible(true);
 76            final Contact contact = user.getContact();
 77            final User self = conversation.getMucOptions().getSelf();
 78            if ((contact != null && contact.showInRoster())
 79                    || mucOptions.isPrivateAndNonAnonymous()) {
 80                showContactDetails.setVisible(contact == null || !contact.isSelf());
 81            }
 82            if ((activity instanceof ConferenceDetailsActivity
 83                            || activity instanceof MucUsersActivity)
 84                    && user.getRole() == MucOptions.Role.NONE) {
 85                invite.setVisible(true);
 86            }
 87            boolean managePermissionsVisible = false;
 88            if ((self.getAffiliation().ranks(MucOptions.Affiliation.ADMIN)
 89                            && self.getAffiliation().outranks(user.getAffiliation()))
 90                    || self.getAffiliation() == MucOptions.Affiliation.OWNER) {
 91                if (advancedMode) {
 92                    if (!user.getAffiliation().ranks(MucOptions.Affiliation.MEMBER)) {
 93                        managePermissionsVisible = true;
 94                        giveMembership.setVisible(true);
 95                    } else if (user.getAffiliation() == MucOptions.Affiliation.MEMBER) {
 96                        managePermissionsVisible = true;
 97                        removeMembership.setVisible(true);
 98                    }
 99                    if (!Config.DISABLE_BAN) {
100                        managePermissionsVisible = true;
101                        banFromConference.setVisible(true);
102                    }
103                } else {
104                    if (!Config.DISABLE_BAN || conversation.getMucOptions().membersOnly()) {
105                        removeFromRoom.setVisible(true);
106                    }
107                }
108            }
109            if (self.getAffiliation().ranks(MucOptions.Affiliation.OWNER)) {
110                if (isGroupChat
111                        || advancedMode
112                        || user.getAffiliation() == MucOptions.Affiliation.OWNER) {
113                    if (!user.getAffiliation().ranks(MucOptions.Affiliation.OWNER)) {
114                        managePermissionsVisible = true;
115                        giveOwnerPrivileges.setVisible(true);
116                    } else if (user.getAffiliation() == MucOptions.Affiliation.OWNER) {
117                        managePermissionsVisible = true;
118                        removeOwnerPrivileges.setVisible(true);
119                    }
120                }
121                if (!isGroupChat
122                        || advancedMode
123                        || user.getAffiliation() == MucOptions.Affiliation.ADMIN) {
124                    if (!user.getAffiliation().ranks(MucOptions.Affiliation.ADMIN)) {
125                        managePermissionsVisible = true;
126                        giveAdminPrivileges.setVisible(true);
127                    } else if (user.getAffiliation() == MucOptions.Affiliation.ADMIN) {
128                        managePermissionsVisible = true;
129                        removeAdminPrivileges.setVisible(true);
130                    }
131                }
132            }
133            managePermissions.setVisible(managePermissionsVisible);
134            sendPrivateMessage.setVisible(
135                    !isGroupChat
136                            && mucOptions.allowPm()
137                            && user.getRole().ranks(MucOptions.Role.VISITOR));
138        } else {
139            sendPrivateMessage.setVisible(true);
140            sendPrivateMessage.setEnabled(
141                    user != null
142                            && mucOptions.allowPm()
143                            && user.getRole().ranks(MucOptions.Role.VISITOR));
144        }
145    }
146
147    public static boolean onContextItemSelected(MenuItem item, User user, XmppActivity activity) {
148        return onContextItemSelected(item, user, activity, null);
149    }
150
151    public static boolean onContextItemSelected(
152            MenuItem item, User user, XmppActivity activity, final String fingerprint) {
153        final Conversation conversation = user.getConversation();
154        final XmppConnectionService.OnAffiliationChanged onAffiliationChanged =
155                activity instanceof XmppConnectionService.OnAffiliationChanged
156                        ? (XmppConnectionService.OnAffiliationChanged) activity
157                        : null;
158        Jid jid = user.getRealJid();
159        switch (item.getItemId()) {
160            case R.id.action_contact_details:
161                final Jid realJid = user.getRealJid();
162                final Account account = conversation.getAccount();
163                final Contact contact =
164                        realJid == null ? null : account.getRoster().getContact(realJid);
165                if (contact != null) {
166                    activity.switchToContactDetails(contact, fingerprint);
167                }
168                return true;
169            case R.id.start_conversation:
170                startConversation(user, activity);
171                return true;
172            case R.id.give_admin_privileges:
173                activity.xmppConnectionService.changeAffiliationInConference(
174                        conversation, jid, MucOptions.Affiliation.ADMIN, onAffiliationChanged);
175                return true;
176            case R.id.give_membership:
177            case R.id.remove_admin_privileges:
178            case R.id.revoke_owner_privileges:
179                activity.xmppConnectionService.changeAffiliationInConference(
180                        conversation, jid, MucOptions.Affiliation.MEMBER, onAffiliationChanged);
181                return true;
182            case R.id.give_owner_privileges:
183                activity.xmppConnectionService.changeAffiliationInConference(
184                        conversation, jid, MucOptions.Affiliation.OWNER, onAffiliationChanged);
185                return true;
186            case R.id.remove_membership:
187                activity.xmppConnectionService.changeAffiliationInConference(
188                        conversation, jid, MucOptions.Affiliation.NONE, onAffiliationChanged);
189                return true;
190            case R.id.remove_from_room:
191                removeFromRoom(user, activity, onAffiliationChanged);
192                return true;
193            case R.id.ban_from_conference:
194                activity.xmppConnectionService.changeAffiliationInConference(
195                        conversation, jid, MucOptions.Affiliation.OUTCAST, onAffiliationChanged);
196                if (user.getRole() != MucOptions.Role.NONE) {
197                    activity.xmppConnectionService.changeRoleInConference(
198                            conversation, user.getName(), MucOptions.Role.NONE);
199                }
200                return true;
201            case R.id.send_private_message:
202                if (activity instanceof ConversationsActivity) {
203                    ConversationFragment conversationFragment = ConversationFragment.get(activity);
204                    if (conversationFragment != null) {
205                        conversationFragment.privateMessageWith(user.getFullJid());
206                        return true;
207                    }
208                }
209                activity.privateMsgInMuc(conversation, user.getName());
210                return true;
211            case R.id.invite:
212                // TODO use direct invites for public conferences
213                if (user.getAffiliation().ranks(MucOptions.Affiliation.MEMBER)) {
214                    activity.xmppConnectionService.directInvite(conversation, jid.asBareJid());
215                } else {
216                    activity.xmppConnectionService.invite(conversation, jid);
217                }
218                return true;
219            default:
220                return false;
221        }
222    }
223
224    private static void removeFromRoom(
225            final User user,
226            XmppActivity activity,
227            XmppConnectionService.OnAffiliationChanged onAffiliationChanged) {
228        final Conversation conversation = user.getConversation();
229        if (conversation.getMucOptions().membersOnly()) {
230            activity.xmppConnectionService.changeAffiliationInConference(
231                    conversation,
232                    user.getRealJid(),
233                    MucOptions.Affiliation.NONE,
234                    onAffiliationChanged);
235            if (user.getRole() != MucOptions.Role.NONE) {
236                activity.xmppConnectionService.changeRoleInConference(
237                        conversation, user.getName(), MucOptions.Role.NONE);
238            }
239        } else {
240            final MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(activity);
241            builder.setTitle(R.string.ban_from_conference);
242            String jid = user.getRealJid().asBareJid().toString();
243            SpannableString message =
244                    new SpannableString(
245                            activity.getString(R.string.removing_from_public_conference, jid));
246            int start = message.toString().indexOf(jid);
247            if (start >= 0) {
248                message.setSpan(
249                        new TypefaceSpan("monospace"),
250                        start,
251                        start + jid.length(),
252                        Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
253            }
254            builder.setMessage(message);
255            builder.setNegativeButton(R.string.cancel, null);
256            builder.setPositiveButton(
257                    R.string.ban_now,
258                    (dialog, which) -> {
259                        activity.xmppConnectionService.changeAffiliationInConference(
260                                conversation,
261                                user.getRealJid(),
262                                MucOptions.Affiliation.OUTCAST,
263                                onAffiliationChanged);
264                        if (user.getRole() != MucOptions.Role.NONE) {
265                            activity.xmppConnectionService.changeRoleInConference(
266                                    conversation, user.getName(), MucOptions.Role.NONE);
267                        }
268                    });
269            builder.create().show();
270        }
271    }
272
273    private static void startConversation(User user, XmppActivity activity) {
274        if (user.getRealJid() != null) {
275            Conversation newConversation =
276                    activity.xmppConnectionService.findOrCreateConversation(
277                            user.getAccount(), user.getRealJid().asBareJid(), false, true);
278            activity.switchToConversation(newConversation);
279        }
280    }
281}