UserAdapter.java

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