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