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