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;
 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.base.Strings;
 22import com.google.common.collect.ImmutableList;
 23import com.google.common.primitives.Ints;
 24
 25import java.util.ArrayList;
 26import java.util.List;
 27
 28import org.openintents.openpgp.util.OpenPgpUtils;
 29
 30import com.google.common.base.Strings;
 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;
 43import im.conversations.android.xmpp.model.muc.Role;
 44import org.openintents.openpgp.util.OpenPgpUtils;
 45
 46public class UserAdapter extends ListAdapter<MucOptions.User, UserAdapter.ViewHolder>
 47        implements View.OnCreateContextMenuListener {
 48
 49    static final DiffUtil.ItemCallback<MucOptions.User> DIFF =
 50            new DiffUtil.ItemCallback<MucOptions.User>() {
 51                @Override
 52                public boolean areItemsTheSame(
 53                        @NonNull MucOptions.User a, @NonNull MucOptions.User b) {
 54                    final Jid fullA = a.getFullJid();
 55                    final Jid fullB = b.getFullJid();
 56                    final Jid realA = a.getRealJid();
 57                    final Jid realB = b.getRealJid();
 58                    if (fullA != null && fullB != null) {
 59                        return fullA.equals(fullB);
 60                    } else if (realA != null && realB != null) {
 61                        return realA.equals(realB);
 62                    } else {
 63                        return false;
 64                    }
 65                }
 66
 67                @Override
 68                public boolean areContentsTheSame(
 69                        @NonNull MucOptions.User a, @NonNull MucOptions.User b) {
 70                    return a.equals(b);
 71                }
 72            };
 73    private final boolean advancedMode;
 74    private MucOptions.User selectedUser = null;
 75
 76    public UserAdapter(final boolean advancedMode) {
 77        super(DIFF);
 78        this.advancedMode = advancedMode;
 79    }
 80
 81    @NonNull
 82    @Override
 83    public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int position) {
 84        return new ViewHolder(
 85                DataBindingUtil.inflate(
 86                        LayoutInflater.from(viewGroup.getContext()),
 87                        R.layout.item_contact,
 88                        viewGroup,
 89                        false));
 90    }
 91
 92    @Override
 93    public void onBindViewHolder(@NonNull ViewHolder viewHolder, int position) {
 94        final MucOptions.User user = getItem(position);
 95        AvatarWorkerTask.loadAvatar(user, viewHolder.binding.contactPhoto, R.dimen.avatar);
 96        viewHolder
 97                .binding
 98                .getRoot()
 99                .setOnClickListener(
100                        v -> {
101                            final XmppActivity activity = XmppActivity.find(v);
102                            if (activity == null) {
103                                return;
104                            }
105                            final var contact = user.getContact();
106                            if (user.getRole() == Role.NONE && contact != null) {
107                                Toast.makeText(
108                                                activity,
109                                                activity.getString(
110                                                        R.string.user_has_left_conference,
111                                                        contact.getDisplayName()),
112                                                Toast.LENGTH_SHORT)
113                                        .show();
114                            }
115                            activity.highlightInMuc(user.getConversation(), user.getName());
116                        });
117        viewHolder.binding.getRoot().setTag(user);
118        viewHolder.binding.getRoot().setOnCreateContextMenuListener(this);
119        viewHolder
120                .binding
121                .getRoot()
122                .setOnLongClickListener(
123                        v -> {
124                            selectedUser = user;
125                            return false;
126                        });
127        final String name = user.getNick();
128        final Contact contact = user.getContact();
129        viewHolder.binding.contactJid.setVisibility(View.GONE);
130        viewHolder.binding.contactJid.setText("");
131        if (contact != null) {
132            final String displayName = contact.getDisplayName();
133            viewHolder.binding.contactDisplayName.setText(displayName);
134            if (name != null && !name.equals(displayName)) {
135                viewHolder.binding.contactJid.setText(
136                        String.format(
137                                "%s \u2022 %s",
138                                name,
139                                ConferenceDetailsActivity.getStatus(
140                                        viewHolder.binding.getRoot().getContext(),
141                                        user,
142                                        advancedMode)));
143            } else {
144                viewHolder.binding.contactJid.setText(
145                        ConferenceDetailsActivity.getStatus(
146                                viewHolder.binding.getRoot().getContext(), user, advancedMode));
147            }
148        } else {
149            viewHolder.binding.contactDisplayName.setText(Strings.nullToEmpty(name));
150            viewHolder.binding.contactJid.setText(
151                    ConferenceDetailsActivity.getStatus(
152                            viewHolder.binding.getRoot().getContext(), user, advancedMode));
153        }
154        if (advancedMode && user.getPgpKeyId() != 0) {
155            viewHolder.binding.key.setVisibility(View.VISIBLE);
156            viewHolder.binding.key.setOnClickListener(
157                    v -> {
158                        final XmppActivity activity = XmppActivity.find(v);
159                        final XmppConnectionService service =
160                                activity == null ? null : activity.xmppConnectionService;
161                        final PgpEngine pgpEngine = service == null ? null : service.getPgpEngine();
162                        if (pgpEngine != null) {
163                            PendingIntent intent = pgpEngine.getIntentForKey(user.getPgpKeyId());
164                            if (intent != null) {
165                                try {
166                                    activity.startIntentSenderForResult(
167                                            intent.getIntentSender(),
168                                            0,
169                                            null,
170                                            0,
171                                            0,
172                                            0,
173                                            Compatibility.pgpStartIntentSenderOptions());
174                                } catch (IntentSender.SendIntentException ignored) {
175
176                                }
177                            }
178                        }
179                    });
180            viewHolder.binding.key.setText(OpenPgpUtils.convertKeyIdToHex(user.getPgpKeyId()));
181        } else {
182            viewHolder.binding.key.setVisibility(View.GONE);
183        }
184
185        final Context context = viewHolder.binding.getRoot().getContext();
186        final LayoutInflater inflater = LayoutInflater.from(context);
187        viewHolder.binding.tags.setVisibility(View.VISIBLE);
188        viewHolder.binding.tags.removeViews(1, viewHolder.binding.tags.getChildCount() - 1);
189        final ImmutableList.Builder<Integer> viewIdBuilder = new ImmutableList.Builder<>();
190        for (MucOptions.Hat hat : user.getPseudoHats(viewHolder.binding.getRoot().getContext())) {
191            final String tag = hat.toString();
192            final TextView tv = (TextView) inflater.inflate(R.layout.item_tag, viewHolder.binding.tags, false);
193            tv.setText(tag);
194            tv.setBackgroundTintList(ColorStateList.valueOf(MaterialColors.harmonizeWithPrimary(context,hat.getColor())));
195            final int id = ViewCompat.generateViewId();
196            tv.setId(id);
197            viewIdBuilder.add(id);
198            viewHolder.binding.tags.addView(tv);
199        }
200        for (MucOptions.Hat hat : user.getHats()) {
201            final String tag = hat.toString();
202            final TextView tv = (TextView) inflater.inflate(R.layout.item_tag, viewHolder.binding.tags, false);
203            tv.setText(tag);
204            tv.setBackgroundTintList(ColorStateList.valueOf(MaterialColors.harmonizeWithPrimary(context,hat.getColor())));
205            final int id = ViewCompat.generateViewId();
206            tv.setId(id);
207            viewIdBuilder.add(id);
208            viewHolder.binding.tags.addView(tv);
209        }
210        viewHolder.binding.flowWidget.setReferencedIds(Ints.toArray(viewIdBuilder.build()));
211
212        if (viewHolder.binding.tags.getChildCount() < 1) {
213            viewHolder.binding.contactJid.setVisibility(View.VISIBLE);
214            viewHolder.binding.tags.setVisibility(View.GONE);
215        }
216    }
217
218    public MucOptions.User getSelectedUser() {
219        return selectedUser;
220    }
221
222    @Override
223    public void onCreateContextMenu(
224            ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
225        MucDetailsContextMenuHelper.onCreateContextMenu(menu, v);
226    }
227
228    public static class ViewHolder extends RecyclerView.ViewHolder {
229
230        public final ItemContactBinding binding;
231
232        private ViewHolder(ItemContactBinding binding) {
233            super(binding.getRoot());
234            this.binding = binding;
235        }
236    }
237}