1package eu.siacs.conversations.ui.adapter;
  2
  3import android.app.PendingIntent;
  4import android.content.IntentSender;
  5import android.view.ContextMenu;
  6import android.view.LayoutInflater;
  7import android.view.View;
  8import android.view.ViewGroup;
  9import android.widget.Toast;
 10import androidx.annotation.NonNull;
 11import androidx.databinding.DataBindingUtil;
 12import androidx.recyclerview.widget.DiffUtil;
 13import androidx.recyclerview.widget.ListAdapter;
 14import androidx.recyclerview.widget.RecyclerView;
 15import com.google.common.base.Strings;
 16import eu.siacs.conversations.R;
 17import eu.siacs.conversations.crypto.PgpEngine;
 18import eu.siacs.conversations.databinding.ItemContactBinding;
 19import eu.siacs.conversations.entities.Contact;
 20import eu.siacs.conversations.entities.MucOptions;
 21import eu.siacs.conversations.services.XmppConnectionService;
 22import eu.siacs.conversations.ui.ConferenceDetailsActivity;
 23import eu.siacs.conversations.ui.XmppActivity;
 24import eu.siacs.conversations.ui.util.AvatarWorkerTask;
 25import eu.siacs.conversations.ui.util.MucDetailsContextMenuHelper;
 26import eu.siacs.conversations.utils.Compatibility;
 27import eu.siacs.conversations.xmpp.Jid;
 28import im.conversations.android.xmpp.model.muc.Role;
 29import org.openintents.openpgp.util.OpenPgpUtils;
 30
 31public class UserAdapter extends ListAdapter<MucOptions.User, UserAdapter.ViewHolder>
 32        implements View.OnCreateContextMenuListener {
 33
 34    static final DiffUtil.ItemCallback<MucOptions.User> DIFF =
 35            new DiffUtil.ItemCallback<MucOptions.User>() {
 36                @Override
 37                public boolean areItemsTheSame(
 38                        @NonNull MucOptions.User a, @NonNull MucOptions.User b) {
 39                    final Jid fullA = a.getFullJid();
 40                    final Jid fullB = b.getFullJid();
 41                    final Jid realA = a.getRealJid();
 42                    final Jid realB = b.getRealJid();
 43                    if (fullA != null && fullB != null) {
 44                        return fullA.equals(fullB);
 45                    } else if (realA != null && realB != null) {
 46                        return realA.equals(realB);
 47                    } else {
 48                        return false;
 49                    }
 50                }
 51
 52                @Override
 53                public boolean areContentsTheSame(
 54                        @NonNull MucOptions.User a, @NonNull MucOptions.User b) {
 55                    return a.equals(b);
 56                }
 57            };
 58    private final boolean advancedMode;
 59    private MucOptions.User selectedUser = null;
 60
 61    public UserAdapter(final boolean advancedMode) {
 62        super(DIFF);
 63        this.advancedMode = advancedMode;
 64    }
 65
 66    @NonNull
 67    @Override
 68    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int position) {
 69        return new ViewHolder(
 70                DataBindingUtil.inflate(
 71                        LayoutInflater.from(viewGroup.getContext()),
 72                        R.layout.item_contact,
 73                        viewGroup,
 74                        false));
 75    }
 76
 77    @Override
 78    public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
 79        final MucOptions.User user = getItem(position);
 80        AvatarWorkerTask.loadAvatar(user, viewHolder.binding.contactPhoto, R.dimen.avatar);
 81        viewHolder
 82                .binding
 83                .getRoot()
 84                .setOnClickListener(
 85                        v -> {
 86                            final XmppActivity activity = XmppActivity.find(v);
 87                            if (activity == null) {
 88                                return;
 89                            }
 90                            final var contact = user.getContact();
 91                            if (user.getRole() == Role.NONE && contact != null) {
 92                                Toast.makeText(
 93                                                activity,
 94                                                activity.getString(
 95                                                        R.string.user_has_left_conference,
 96                                                        contact.getDisplayName()),
 97                                                Toast.LENGTH_SHORT)
 98                                        .show();
 99                            }
100                            activity.highlightInMuc(user.getConversation(), user.getName());
101                        });
102        viewHolder.binding.getRoot().setTag(user);
103        viewHolder.binding.getRoot().setOnCreateContextMenuListener(this);
104        viewHolder
105                .binding
106                .getRoot()
107                .setOnLongClickListener(
108                        v -> {
109                            selectedUser = user;
110                            return false;
111                        });
112        final String name = user.getName();
113        final Contact contact = user.getContact();
114        if (contact != null) {
115            final String displayName = contact.getDisplayName();
116            viewHolder.binding.contactDisplayName.setText(displayName);
117            if (name != null && !name.equals(displayName)) {
118                viewHolder.binding.contactJid.setText(
119                        String.format(
120                                "%s \u2022 %s",
121                                name,
122                                ConferenceDetailsActivity.getStatus(
123                                        viewHolder.binding.getRoot().getContext(),
124                                        user,
125                                        advancedMode)));
126            } else {
127                viewHolder.binding.contactJid.setText(
128                        ConferenceDetailsActivity.getStatus(
129                                viewHolder.binding.getRoot().getContext(), user, advancedMode));
130            }
131        } else {
132            viewHolder.binding.contactDisplayName.setText(Strings.nullToEmpty(name));
133            viewHolder.binding.contactJid.setText(
134                    ConferenceDetailsActivity.getStatus(
135                            viewHolder.binding.getRoot().getContext(), user, advancedMode));
136        }
137        if (advancedMode && user.getPgpKeyId() != 0) {
138            viewHolder.binding.key.setVisibility(View.VISIBLE);
139            viewHolder.binding.key.setOnClickListener(
140                    v -> {
141                        final XmppActivity activity = XmppActivity.find(v);
142                        final XmppConnectionService service =
143                                activity == null ? null : activity.xmppConnectionService;
144                        final PgpEngine pgpEngine = service == null ? null : service.getPgpEngine();
145                        if (pgpEngine != null) {
146                            PendingIntent intent = pgpEngine.getIntentForKey(user.getPgpKeyId());
147                            if (intent != null) {
148                                try {
149                                    activity.startIntentSenderForResult(
150                                            intent.getIntentSender(),
151                                            0,
152                                            null,
153                                            0,
154                                            0,
155                                            0,
156                                            Compatibility.pgpStartIntentSenderOptions());
157                                } catch (IntentSender.SendIntentException ignored) {
158
159                                }
160                            }
161                        }
162                    });
163            viewHolder.binding.key.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId()));
164        } else {
165            viewHolder.binding.key.setVisibility(View.GONE);
166        }
167    }
168
169    public MucOptions.User getSelectedUser() {
170        return selectedUser;
171    }
172
173    @Override
174    public void onCreateContextMenu(
175            ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
176        MucDetailsContextMenuHelper.onCreateContextMenu(menu, v);
177    }
178
179    static class ViewHolder extends RecyclerView.ViewHolder {
180
181        private final ItemContactBinding binding;
182
183        private ViewHolder(ItemContactBinding binding) {
184            super(binding.getRoot());
185            this.binding = binding;
186        }
187    }
188}