1package eu.siacs.conversations.ui.adapter;
2
3import android.content.SharedPreferences;
4import android.content.res.ColorStateList;
5import android.preference.PreferenceManager;
6import android.util.Log;
7import android.view.LayoutInflater;
8import android.view.View;
9import android.view.ViewGroup;
10import android.widget.ArrayAdapter;
11import android.widget.ImageView;
12import android.widget.TextView;
13
14import androidx.core.graphics.ColorUtils;
15import androidx.annotation.NonNull;
16import androidx.constraintlayout.helper.widget.Flow;
17import androidx.constraintlayout.widget.ConstraintLayout;
18import androidx.core.content.ContextCompat;
19import androidx.core.view.ViewCompat;
20import androidx.databinding.DataBindingUtil;
21import com.google.android.material.color.MaterialColors;
22import com.google.common.collect.ImmutableList;
23import com.google.common.primitives.Ints;
24import eu.siacs.conversations.AppSettings;
25import eu.siacs.conversations.Config;
26import eu.siacs.conversations.R;
27import eu.siacs.conversations.databinding.ItemContactBinding;
28import eu.siacs.conversations.entities.Contact;
29import eu.siacs.conversations.entities.ListItem;
30import eu.siacs.conversations.ui.XmppActivity;
31import eu.siacs.conversations.ui.util.AvatarWorkerTask;
32import eu.siacs.conversations.utils.IrregularUnicodeDetector;
33import eu.siacs.conversations.utils.UIHelper;
34import eu.siacs.conversations.utils.XEP0392Helper;
35import eu.siacs.conversations.xmpp.Jid;
36import im.conversations.android.xmpp.model.stanza.Presence;
37import java.util.List;
38
39public class ListItemAdapter extends ArrayAdapter<ListItem> {
40
41 protected XmppActivity activity;
42 private boolean showDynamicTags = false;
43 private OnTagClickedListener mOnTagClickedListener = null;
44 private final View.OnClickListener onTagTvClick =
45 view -> {
46 if (view instanceof TextView tv && mOnTagClickedListener != null) {
47 final String tag = tv.getText().toString();
48 mOnTagClickedListener.onTagClicked(tag);
49 }
50 };
51
52 public ListItemAdapter(XmppActivity activity, List<ListItem> objects) {
53 super(activity, 0, objects);
54 this.activity = activity;
55 }
56
57 public void refreshSettings() {
58 SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(activity);
59 this.showDynamicTags = preferences.getBoolean(AppSettings.SHOW_DYNAMIC_TAGS, false);
60 }
61
62 @NonNull
63 @Override
64 public View getView(int position, View view, @NonNull ViewGroup parent) {
65 LayoutInflater inflater = activity.getLayoutInflater();
66 final ListItem item = getItem(position);
67 ViewHolder viewHolder;
68 View innerView;
69 if (view == null) {
70 final ItemContactBinding binding =
71 DataBindingUtil.inflate(inflater, R.layout.item_contact, parent, false);
72 viewHolder = ViewHolder.get(binding);
73 view = binding.getRoot();
74 innerView = binding.inner;
75 } else {
76 viewHolder = (ViewHolder) view.getTag();
77 innerView = viewHolder.inner;
78 }
79 if (view.isActivated()) {
80 Log.d(Config.LOGTAG, "item " + item.getDisplayName() + " is activated");
81 }
82 if (activity.colorCodeAccounts()) {
83 innerView.setBackgroundColor(item.getAccount().getColor(activity.isDark()));
84 }
85 // view.setBackground(StyledAttributes.getDrawable(view.getContext(),R.attr.list_item_background));
86 final List<ListItem.Tag> tags = item.getTags(activity);
87 final boolean hasMetaTags;
88 if (item instanceof Contact contact) {
89 hasMetaTags =
90 contact.isBlocked()
91 || contact.getShownStatus() != Presence.Availability.OFFLINE;
92 } else {
93 hasMetaTags = false;
94 }
95 if ((tags.isEmpty() && !hasMetaTags) || !this.showDynamicTags) {
96 viewHolder.tags.setVisibility(View.GONE);
97 } else {
98 viewHolder.tags.setVisibility(View.VISIBLE);
99 viewHolder.tags.removeViews(1, viewHolder.tags.getChildCount() - 1);
100 final ImmutableList.Builder<Integer> viewIdBuilder = new ImmutableList.Builder<>();
101 for (final ListItem.Tag tag : tags) {
102 final String name = tag.getName();
103 final TextView tv =
104 (TextView) inflater.inflate(R.layout.item_tag, viewHolder.tags, false);
105 tv.setText(name);
106 tv.setBackgroundTintList(
107 ColorStateList.valueOf(
108 MaterialColors.harmonizeWithPrimary(
109 getContext(), XEP0392Helper.rgbFromNick(name))));
110 tv.setOnClickListener(this.onTagTvClick);
111 final int id = ViewCompat.generateViewId();
112 tv.setId(id);
113 viewIdBuilder.add(id);
114 viewHolder.tags.addView(tv);
115 }
116 if (item instanceof Contact contact) {
117 if (contact.isBlocked()) {
118 final TextView tv =
119 (TextView) inflater.inflate(R.layout.item_tag, viewHolder.tags, false);
120 tv.setText(R.string.blocked);
121 tv.setBackgroundTintList(
122 ColorStateList.valueOf(
123 MaterialColors.harmonizeWithPrimary(
124 tv.getContext(),
125 ContextCompat.getColor(
126 tv.getContext(), R.color.gray_800))));
127 final int id = ViewCompat.generateViewId();
128 tv.setId(id);
129 viewIdBuilder.add(id);
130 viewHolder.tags.addView(tv);
131 } else {
132 final Presence.Availability status = contact.getShownStatus();
133 if (status != Presence.Availability.OFFLINE) {
134 final TextView tv =
135 (TextView)
136 inflater.inflate(R.layout.item_tag, viewHolder.tags, false);
137 UIHelper.setStatus(tv, status);
138 final int id = ViewCompat.generateViewId();
139 tv.setId(id);
140 viewIdBuilder.add(id);
141 viewHolder.tags.addView(tv);
142 }
143 }
144 }
145 viewHolder.flowWidget.setReferencedIds(Ints.toArray(viewIdBuilder.build()));
146 }
147 final Jid jid = item.getJid();
148 if (jid != null) {
149 viewHolder.jid.setVisibility(View.VISIBLE);
150 viewHolder.jid.setText(IrregularUnicodeDetector.style(activity, jid));
151 } else {
152 viewHolder.jid.setVisibility(View.GONE);
153 }
154 viewHolder.name.setText(item.getDisplayName());
155 AvatarWorkerTask.loadAvatar(item, viewHolder.avatar, R.dimen.avatar);
156 return view;
157 }
158
159 public void setOnTagClickedListener(OnTagClickedListener listener) {
160 this.mOnTagClickedListener = listener;
161 }
162
163 public interface OnTagClickedListener {
164 void onTagClicked(String tag);
165 }
166
167 private static class ViewHolder {
168 private TextView name;
169 private TextView jid;
170 private ImageView avatar;
171 private View inner;
172 private ConstraintLayout tags;
173 private Flow flowWidget;
174
175 private ViewHolder() {}
176
177 public static ViewHolder get(final ItemContactBinding binding) {
178 ViewHolder viewHolder = new ViewHolder();
179 viewHolder.name = binding.contactDisplayName;
180 viewHolder.jid = binding.contactJid;
181 viewHolder.avatar = binding.contactPhoto;
182 viewHolder.tags = binding.tags;
183 viewHolder.inner = binding.inner;
184 viewHolder.flowWidget = binding.flowWidget;
185 binding.getRoot().setTag(viewHolder);
186 return viewHolder;
187 }
188 }
189}