ListItemAdapter.java

  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}