UserAdapter.java

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