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}