diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index 902cba728..3ddf5fe0e 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -81,7 +81,6 @@ public final class Config { public static final int CONNECT_DISCO_TIMEOUT = 20; public static final int MINI_GRACE_PERIOD = 750; - public static final boolean XEP_0392 = true; // enables XEP-0392 v0.6.0 // media file formats. Homogenous Android or Conversations only deployments can switch to opus // and webp diff --git a/src/main/java/eu/siacs/conversations/entities/Bookmark.java b/src/main/java/eu/siacs/conversations/entities/Bookmark.java index 24107ec8f..76c314a3e 100644 --- a/src/main/java/eu/siacs/conversations/entities/Bookmark.java +++ b/src/main/java/eu/siacs/conversations/entities/Bookmark.java @@ -5,6 +5,9 @@ import android.content.Context; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; + import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.Collections; @@ -161,15 +164,18 @@ public class Bookmark extends Element implements ListItem { } @Override - public List getTags(Context context) { - ArrayList tags = new ArrayList<>(); - for (Element element : getChildren()) { - if (element.getName().equals("group") && element.getContent() != null) { - String group = element.getContent(); - tags.add(new Tag(group, UIHelper.getColorForName(group,true))); + public List getTags(final Context context) { + final ImmutableList.Builder tags = new ImmutableList.Builder<>(); + for (final Element element : getChildren()) { + final String content = element.getContent(); + if (Strings.isNullOrEmpty(content)) { + continue; + } + if (element.getName().equals("group")) { + tags.add(new Tag(content)); } } - return tags; + return tags.build(); } public String getNick() { diff --git a/src/main/java/eu/siacs/conversations/entities/Contact.java b/src/main/java/eu/siacs/conversations/entities/Contact.java index 56e1ec02e..c66220ab5 100644 --- a/src/main/java/eu/siacs/conversations/entities/Contact.java +++ b/src/main/java/eu/siacs/conversations/entities/Contact.java @@ -180,17 +180,10 @@ public class Contact implements ListItem, Blockable { } @Override - public List getTags(Context context) { + public List getTags(final Context context) { final ArrayList tags = new ArrayList<>(); for (final String group : getGroups(true)) { - tags.add(new Tag(group, UIHelper.getColorForName(group))); - } - Presence.Status status = getShownStatus(); - if (status != Presence.Status.OFFLINE) { - tags.add(UIHelper.getTagForStatus(context, status)); - } - if (isBlocked()) { - tags.add(new Tag(context.getString(R.string.blocked), 0xff2e2f3b)); + tags.add(new Tag(group)); } return tags; } diff --git a/src/main/java/eu/siacs/conversations/entities/ListItem.java b/src/main/java/eu/siacs/conversations/entities/ListItem.java index adc7666ce..ab2321aa6 100644 --- a/src/main/java/eu/siacs/conversations/entities/ListItem.java +++ b/src/main/java/eu/siacs/conversations/entities/ListItem.java @@ -17,15 +17,9 @@ public interface ListItem extends Comparable, AvatarService.Avatarable final class Tag { private final String name; - private final int color; - public Tag(final String name, final int color) { + public Tag(final String name) { this.name = name; - this.color = color; - } - - public int getColor() { - return this.color; } public String getName() { diff --git a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java index dc038ce37..0ef99ec57 100644 --- a/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ContactDetailsActivity.java @@ -6,6 +6,7 @@ import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.content.res.ColorStateList; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -28,6 +29,7 @@ import android.widget.Toast; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; +import androidx.core.content.ContextCompat; import androidx.databinding.DataBindingUtil; import com.google.android.material.color.MaterialColors; @@ -49,6 +51,7 @@ import eu.siacs.conversations.databinding.ActivityContactDetailsBinding; import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.ListItem; +import eu.siacs.conversations.entities.Presence; import eu.siacs.conversations.services.AbstractQuickConversationsService; import eu.siacs.conversations.services.QuickConversationsService; import eu.siacs.conversations.services.XmppConnectionService.OnAccountUpdate; @@ -66,6 +69,7 @@ import eu.siacs.conversations.utils.Emoticons; import eu.siacs.conversations.utils.IrregularUnicodeDetector; import eu.siacs.conversations.utils.PhoneNumberUtilWrapper; import eu.siacs.conversations.utils.UIHelper; +import eu.siacs.conversations.utils.XEP0392Helper; import eu.siacs.conversations.utils.XmppUri; import eu.siacs.conversations.xml.Namespace; import eu.siacs.conversations.xmpp.Jid; @@ -504,18 +508,39 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp } binding.keysWrapper.setVisibility(hasKeys ? View.VISIBLE : View.GONE); - List tagList = contact.getTags(this); - if (tagList.isEmpty() || !this.showDynamicTags) { + final List tagList = contact.getTags(this); + final boolean hasMetaTags = contact.isBlocked() || contact.getShownStatus() != Presence.Status.OFFLINE; + if ((tagList.isEmpty() && !hasMetaTags) || !this.showDynamicTags) { binding.tags.setVisibility(View.GONE); } else { binding.tags.setVisibility(View.VISIBLE); binding.tags.removeAllViewsInLayout(); for (final ListItem.Tag tag : tagList) { + final String name = tag.getName(); final TextView tv = (TextView) inflater.inflate(R.layout.list_item_tag, binding.tags, false); - tv.setText(tag.getName()); - tv.setBackgroundColor(tag.getColor()); + tv.setText(name); + tv.setBackgroundTintList(ColorStateList.valueOf(MaterialColors.harmonizeWithPrimary(this,XEP0392Helper.rgbFromNick(name)))); binding.tags.addView(tv); } + if (contact.isBlocked()) { + final TextView tv = + (TextView) + inflater.inflate( + R.layout.list_item_tag, binding.tags, false); + tv.setText(R.string.blocked); + tv.setBackgroundTintList(ColorStateList.valueOf(MaterialColors.harmonizeWithPrimary(tv.getContext(), ContextCompat.getColor(tv.getContext(),R.color.gray_800)))); + binding.tags.addView(tv); + } else { + final Presence.Status status = contact.getShownStatus(); + if (status != Presence.Status.OFFLINE) { + final TextView tv = + (TextView) + inflater.inflate( + R.layout.list_item_tag, binding.tags, false); + UIHelper.setStatus(tv, status); + binding.tags.addView(tv); + } + } } } diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java index a30d25c00..ff87ee16a 100644 --- a/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java +++ b/src/main/java/eu/siacs/conversations/ui/adapter/ListItemAdapter.java @@ -1,6 +1,7 @@ package eu.siacs.conversations.ui.adapter; import android.content.SharedPreferences; +import android.content.res.ColorStateList; import android.preference.PreferenceManager; import android.util.Log; import android.view.LayoutInflater; @@ -11,18 +12,24 @@ import android.widget.ImageView; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; import androidx.databinding.DataBindingUtil; +import com.google.android.material.color.MaterialColors; import com.wefika.flowlayout.FlowLayout; import eu.siacs.conversations.AppSettings; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; import eu.siacs.conversations.databinding.ItemContactBinding; +import eu.siacs.conversations.entities.Contact; import eu.siacs.conversations.entities.ListItem; +import eu.siacs.conversations.entities.Presence; import eu.siacs.conversations.ui.XmppActivity; import eu.siacs.conversations.ui.util.AvatarWorkerTask; import eu.siacs.conversations.utils.IrregularUnicodeDetector; +import eu.siacs.conversations.utils.UIHelper; +import eu.siacs.conversations.utils.XEP0392Helper; import eu.siacs.conversations.xmpp.Jid; import java.util.List; @@ -54,7 +61,7 @@ public class ListItemAdapter extends ArrayAdapter { @Override public View getView(int position, View view, @NonNull ViewGroup parent) { LayoutInflater inflater = activity.getLayoutInflater(); - ListItem item = getItem(position); + final ListItem item = getItem(position); ViewHolder viewHolder; if (view == null) { final ItemContactBinding binding = DataBindingUtil.inflate(inflater,R.layout.item_contact,parent,false); @@ -68,18 +75,46 @@ public class ListItemAdapter extends ArrayAdapter { } //view.setBackground(StyledAttributes.getDrawable(view.getContext(),R.attr.list_item_background)); final List tags = item.getTags(activity); - if (tags.isEmpty() || !this.showDynamicTags) { + final boolean hasMetaTags; + if (item instanceof Contact contact) { + hasMetaTags = contact.isBlocked() || contact.getShownStatus() != Presence.Status.OFFLINE; + } else { + hasMetaTags = false; + } + if ((tags.isEmpty() && !hasMetaTags) || !this.showDynamicTags) { viewHolder.tags.setVisibility(View.GONE); } else { viewHolder.tags.setVisibility(View.VISIBLE); viewHolder.tags.removeAllViewsInLayout(); - for (ListItem.Tag tag : tags) { - TextView tv = (TextView) inflater.inflate(R.layout.list_item_tag, viewHolder.tags, false); - tv.setText(tag.getName()); - tv.setBackgroundColor(tag.getColor()); + for (final ListItem.Tag tag : tags) { + final String name = tag.getName(); + final TextView tv = (TextView) inflater.inflate(R.layout.list_item_tag, viewHolder.tags, false); + tv.setText(name); + tv.setBackgroundTintList(ColorStateList.valueOf(MaterialColors.harmonizeWithPrimary(getContext(),XEP0392Helper.rgbFromNick(name)))); tv.setOnClickListener(this.onTagTvClick); viewHolder.tags.addView(tv); } + if (item instanceof Contact contact) { + if (contact.isBlocked()) { + final TextView tv = + (TextView) + inflater.inflate( + R.layout.list_item_tag, viewHolder.tags, false); + tv.setText(R.string.blocked); + tv.setBackgroundTintList(ColorStateList.valueOf(MaterialColors.harmonizeWithPrimary(tv.getContext(),ContextCompat.getColor(tv.getContext(),R.color.gray_800)))); + viewHolder.tags.addView(tv); + } else { + final Presence.Status status = contact.getShownStatus(); + if (status != Presence.Status.OFFLINE) { + final TextView tv = + (TextView) + inflater.inflate( + R.layout.list_item_tag, viewHolder.tags, false); + UIHelper.setStatus(tv, status); + viewHolder.tags.addView(tv); + } + } + } } final Jid jid = item.getJid(); if (jid != null) { diff --git a/src/main/java/eu/siacs/conversations/utils/UIHelper.java b/src/main/java/eu/siacs/conversations/utils/UIHelper.java index da72ba9bd..9fcf508d2 100644 --- a/src/main/java/eu/siacs/conversations/utils/UIHelper.java +++ b/src/main/java/eu/siacs/conversations/utils/UIHelper.java @@ -1,13 +1,19 @@ package eu.siacs.conversations.utils; import android.content.Context; +import android.content.res.ColorStateList; import android.text.SpannableStringBuilder; import android.text.format.DateFormat; import android.text.format.DateUtils; import android.util.Pair; +import android.widget.TextView; import androidx.annotation.ColorInt; +import androidx.annotation.ColorRes; +import androidx.annotation.StringRes; +import androidx.core.content.ContextCompat; +import com.google.android.material.color.MaterialColors; import com.google.common.base.Strings; import java.math.BigInteger; @@ -37,78 +43,6 @@ import eu.siacs.conversations.xmpp.Jid; public class UIHelper { - private static final int[] UNSAFE_COLORS = { - 0xFFF44336, //red 500 - 0xFFE53935, //red 600 - 0xFFD32F2F, //red 700 - 0xFFC62828, //red 800 - - 0xFFEF6C00, //orange 800 - - 0xFFF4511E, //deep orange 600 - 0xFFE64A19, //deep orange 700 - 0xFFD84315, //deep orange 800, - }; - - private static final int[] SAFE_COLORS = { - 0xFFE91E63, //pink 500 - 0xFFD81B60, //pink 600 - 0xFFC2185B, //pink 700 - 0xFFAD1457, //pink 800 - - 0xFF9C27B0, //purple 500 - 0xFF8E24AA, //purple 600 - 0xFF7B1FA2, //purple 700 - 0xFF6A1B9A, //purple 800 - - 0xFF673AB7, //deep purple 500, - 0xFF5E35B1, //deep purple 600 - 0xFF512DA8, //deep purple 700 - 0xFF4527A0, //deep purple 800, - - 0xFF3F51B5, //indigo 500, - 0xFF3949AB,//indigo 600 - 0xFF303F9F,//indigo 700 - 0xFF283593, //indigo 800 - - 0xFF2196F3, //blue 500 - 0xFF1E88E5, //blue 600 - 0xFF1976D2, //blue 700 - 0xFF1565C0, //blue 800 - - 0xFF03A9F4, //light blue 500 - 0xFF039BE5, //light blue 600 - 0xFF0288D1, //light blue 700 - 0xFF0277BD, //light blue 800 - - 0xFF00BCD4, //cyan 500 - 0xFF00ACC1, //cyan 600 - 0xFF0097A7, //cyan 700 - 0xFF00838F, //cyan 800 - - 0xFF009688, //teal 500, - 0xFF00897B, //teal 600 - 0xFF00796B, //teal 700 - 0xFF00695C, //teal 800, - - //0xFF558B2F, //light green 800 - - //0xFFC0CA33, //lime 600 - 0xFF9E9D24, //lime 800 - - 0xFF795548, //brown 500, - //0xFF4E342E, //brown 800 - 0xFF607D8B, //blue grey 500, - //0xFF37474F //blue grey 800 - }; - - private static final int[] COLORS; - - static { - COLORS = Arrays.copyOf(SAFE_COLORS, SAFE_COLORS.length + UNSAFE_COLORS.length); - System.arraycopy(UNSAFE_COLORS, 0, COLORS, SAFE_COLORS.length, UNSAFE_COLORS.length); - } - private static final List LOCATION_QUESTIONS = Arrays.asList( "where are you", //en "where are you now", //en @@ -226,32 +160,11 @@ public class UIHelper { } } - public static int getColorForName(String name) { - return getColorForName(name, false); + + public static int getColorForName(final String name) { + return XEP0392Helper.rgbFromNick(name); } - public static int getColorForName(String name, boolean safe) { - if (Config.XEP_0392) { - return XEP0392Helper.rgbFromNick(name); - } - if (name == null || name.isEmpty()) { - return 0xFF202020; - } - if (safe) { - return SAFE_COLORS[(int) (getLongForName(name) % SAFE_COLORS.length)]; - } else { - return COLORS[(int) (getLongForName(name) % COLORS.length)]; - } - } - - private static long getLongForName(String name) { - try { - final MessageDigest messageDigest = MessageDigest.getInstance("MD5"); - return Math.abs(new BigInteger(messageDigest.digest(name.getBytes())).longValue()); - } catch (Exception e) { - return 0; - } - } public static Pair getMessagePreview(final Context context, final Message message) { return getMessagePreview(context, message, 0); @@ -589,19 +502,38 @@ public class UIHelper { return LOCATION_QUESTIONS.contains(body); } - public static ListItem.Tag getTagForStatus(Context context, Presence.Status status) { - switch (status) { - case CHAT: - return new ListItem.Tag(context.getString(R.string.presence_chat), 0xff259b24); - case AWAY: - return new ListItem.Tag(context.getString(R.string.presence_away), 0xffff9800); - case XA: - return new ListItem.Tag(context.getString(R.string.presence_xa), 0xfff44336); - case DND: - return new ListItem.Tag(context.getString(R.string.presence_dnd), 0xfff44336); - default: - return new ListItem.Tag(context.getString(R.string.presence_online), 0xff259b24); - } + public static void setStatus(final TextView textView, Presence.Status status) { + final @StringRes int text; + final @ColorRes int color = + switch (status) { + case CHAT -> { + text = R.string.presence_chat; + yield R.color.green_800; + } + case ONLINE -> { + text = R.string.presence_online; + yield R.color.green_800; + } + case AWAY -> { + text = R.string.presence_away; + yield R.color.amber_800; + } + case XA -> { + text = R.string.presence_xa; + yield R.color.orange_800; + } + case DND -> { + text = R.string.presence_dnd; + yield R.color.red_800; + } + default -> throw new IllegalStateException(); + }; + textView.setText(text); + textView.setBackgroundTintList( + ColorStateList.valueOf( + MaterialColors.harmonizeWithPrimary( + textView.getContext(), + ContextCompat.getColor(textView.getContext(), color)))); } public static String filesizeToString(long size) { diff --git a/src/main/java/eu/siacs/conversations/utils/XEP0392Helper.java b/src/main/java/eu/siacs/conversations/utils/XEP0392Helper.java index 69c00365e..8811b4ba1 100644 --- a/src/main/java/eu/siacs/conversations/utils/XEP0392Helper.java +++ b/src/main/java/eu/siacs/conversations/utils/XEP0392Helper.java @@ -7,7 +7,7 @@ import org.hsluv.HUSLColorConverter; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; -class XEP0392Helper { +public class XEP0392Helper { private static double angle(String nickname) { try { @@ -20,7 +20,7 @@ class XEP0392Helper { } } - static int rgbFromNick(String name) { + public static int rgbFromNick(String name) { double[] hsluv = new double[3]; hsluv[0] = angle(name) * 360; hsluv[1] = 100; diff --git a/src/main/res/drawable/background_label.xml b/src/main/res/drawable/background_label.xml new file mode 100644 index 000000000..a12b781c4 --- /dev/null +++ b/src/main/res/drawable/background_label.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/main/res/layout/list_item_tag.xml b/src/main/res/layout/list_item_tag.xml index 2ff9a09b6..03395ba44 100644 --- a/src/main/res/layout/list_item_tag.xml +++ b/src/main/res/layout/list_item_tag.xml @@ -1,12 +1,15 @@ \ No newline at end of file + android:minHeight="10dp" + android:paddingHorizontal="8dp" + android:textAppearance="?textAppearanceLabelMedium" + android:textColor="@android:color/white" + tools:text="Friends" /> \ No newline at end of file