Detailed changes
@@ -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
@@ -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<Tag> getTags(Context context) {
- ArrayList<Tag> 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<Tag> getTags(final Context context) {
+ final ImmutableList.Builder<Tag> 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() {
@@ -180,17 +180,10 @@ public class Contact implements ListItem, Blockable {
}
@Override
- public List<Tag> getTags(Context context) {
+ public List<Tag> getTags(final Context context) {
final ArrayList<Tag> 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;
}
@@ -17,15 +17,9 @@ public interface ListItem extends Comparable<ListItem>, 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() {
@@ -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<ListItem.Tag> tagList = contact.getTags(this);
- if (tagList.isEmpty() || !this.showDynamicTags) {
+ final List<ListItem.Tag> 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);
+ }
+ }
}
}
@@ -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<ListItem> {
@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<ListItem> {
}
//view.setBackground(StyledAttributes.getDrawable(view.getContext(),R.attr.list_item_background));
final List<ListItem.Tag> 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) {
@@ -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<String> 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(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)];
- }
+ public static int getColorForName(final String name) {
+ return XEP0392Helper.rgbFromNick(name);
}
- 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<CharSequence, Boolean> 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) {
@@ -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;
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android">
+ <solid android:color="@android:color/white" />
+ <corners android:radius="5dp" />
+</shape>
@@ -1,12 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_margin="2dp"
+ android:layout_marginHorizontal="2dp"
+ android:layout_marginVertical="4dp"
+ android:background="@drawable/background_label"
+ android:backgroundTint="@color/green_700"
android:maxLines="1"
- android:paddingLeft="4dp"
- android:paddingTop="1dp"
- android:paddingRight="4dp"
- android:paddingBottom="1dp"
- android:textAllCaps="true"
- android:textAppearance="?textAppearanceLabelLarge" />
+ android:minHeight="10dp"
+ android:paddingHorizontal="8dp"
+ android:textAppearance="?textAppearanceLabelMedium"
+ android:textColor="@android:color/white"
+ tools:text="Friends" />