aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Schneppe <christian@pix-art.de>2018-04-07 21:33:45 +0200
committerChristian Schneppe <christian@pix-art.de>2018-04-07 21:33:45 +0200
commit8409e61d6a7275da73c2fbff3152177bc864c90e (patch)
tree09833a98496e88e93d6654190294bcd6affd8229
parent33a46a4a6a8fa6fa8734095ff7ba588b759e897e (diff)
display irregular unicode code points
-rw-r--r--src/main/java/de/pixart/messenger/entities/Bookmark.java10
-rw-r--r--src/main/java/de/pixart/messenger/entities/Contact.java9
-rw-r--r--src/main/java/de/pixart/messenger/entities/ListItem.java2
-rw-r--r--src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java15
-rw-r--r--src/main/java/de/pixart/messenger/ui/TrustKeysActivity.java6
-rw-r--r--src/main/java/de/pixart/messenger/ui/adapter/ListItemAdapter.java6
-rw-r--r--src/main/java/de/pixart/messenger/utils/IrregularUnicodeBlockDetector.java160
-rw-r--r--src/main/res/values/colors.xml2
-rw-r--r--src/main/res/values/themes.xml3
9 files changed, 177 insertions, 36 deletions
diff --git a/src/main/java/de/pixart/messenger/entities/Bookmark.java b/src/main/java/de/pixart/messenger/entities/Bookmark.java
index 27997e750..a09ad794e 100644
--- a/src/main/java/de/pixart/messenger/entities/Bookmark.java
+++ b/src/main/java/de/pixart/messenger/entities/Bookmark.java
@@ -64,16 +64,6 @@ public class Bookmark extends Element implements ListItem {
}
@Override
- public String getDisplayJid() {
- Jid jid = getJid();
- if (jid != null) {
- return jid.toString();
- } else {
- return getAttribute("jid"); //fallback if jid wasn't parsable
- }
- }
-
- @Override
public int getOffline() {
return 0;
}
diff --git a/src/main/java/de/pixart/messenger/entities/Contact.java b/src/main/java/de/pixart/messenger/entities/Contact.java
index 827840442..76dd916f8 100644
--- a/src/main/java/de/pixart/messenger/entities/Contact.java
+++ b/src/main/java/de/pixart/messenger/entities/Contact.java
@@ -128,15 +128,6 @@ public class Contact implements ListItem, Blockable {
}
@Override
- public String getDisplayJid() {
- if (jid != null) {
- return jid.toString();
- } else {
- return null;
- }
- }
-
- @Override
public int getOffline() {
return 0;
}
diff --git a/src/main/java/de/pixart/messenger/entities/ListItem.java b/src/main/java/de/pixart/messenger/entities/ListItem.java
index df1ba75b0..21fb6c2b6 100644
--- a/src/main/java/de/pixart/messenger/entities/ListItem.java
+++ b/src/main/java/de/pixart/messenger/entities/ListItem.java
@@ -9,8 +9,6 @@ import rocks.xmpp.addr.Jid;
public interface ListItem extends Comparable<ListItem> {
String getDisplayName();
- String getDisplayJid();
-
int getOffline();
Jid getJid();
diff --git a/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java b/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java
index 18a3e8adc..984a9c58a 100644
--- a/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/ContactDetailsActivity.java
@@ -44,6 +44,7 @@ import de.pixart.messenger.entities.ListItem;
import de.pixart.messenger.services.XmppConnectionService.OnAccountUpdate;
import de.pixart.messenger.services.XmppConnectionService.OnRosterUpdate;
import de.pixart.messenger.utils.CryptoHelper;
+import de.pixart.messenger.utils.IrregularUnicodeBlockDetector;
import de.pixart.messenger.utils.Namespace;
import de.pixart.messenger.utils.TimeframeUtils;
import de.pixart.messenger.utils.UIHelper;
@@ -140,8 +141,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
AlertDialog.Builder builder = new AlertDialog.Builder(
ContactDetailsActivity.this);
builder.setTitle(getString(R.string.action_add_phone_book));
- builder.setMessage(getString(R.string.add_phone_book_text,
- contact.getDisplayJid()));
+ builder.setMessage(getString(R.string.add_phone_book_text, contact.getJid().toString()));
builder.setNegativeButton(getString(R.string.cancel), null);
builder.setPositiveButton(getString(R.string.add), addToPhonebook);
builder.create().show();
@@ -392,7 +392,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
if (contact.getServer().toString().toLowerCase().equals(accountJid.getDomain().toLowerCase())) {
binding.contactDisplayName.setText(contact.getDisplayName());
} else {
- binding.contactDisplayName.setText(contact.getDisplayJid());
+ binding.contactDisplayName.setText(contact.getJid().toString());
}
if (contact.showInRoster()) {
binding.detailsSendPresence.setVisibility(View.VISIBLE);
@@ -411,7 +411,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
deleteFromRosterDialog.setTitle(getString(R.string.action_delete_contact))
.setMessage(
getString(R.string.remove_contact_text,
- contact.getDisplayJid()))
+ contact.getJid().toString()))
.setPositiveButton(getString(R.string.delete),
removeFromRoster).create().show();
}
@@ -509,12 +509,7 @@ public class ContactDetailsActivity extends OmemoActivity implements OnAccountUp
}
}
- if (contact.getPresences().size() > 1) {
- binding.detailsContactjid.setText(contact.getDisplayJid() + " ("
- + contact.getPresences().size() + ")");
- } else {
- binding.detailsContactjid.setText(contact.getDisplayJid());
- }
+ binding.detailsContactjid.setText(IrregularUnicodeBlockDetector.style(this, contact.getJid()));
String account;
if (Config.DOMAIN_LOCK != null) {
account = contact.getAccount().getJid().getLocal();
diff --git a/src/main/java/de/pixart/messenger/ui/TrustKeysActivity.java b/src/main/java/de/pixart/messenger/ui/TrustKeysActivity.java
index 3f97b12f9..d401a3c39 100644
--- a/src/main/java/de/pixart/messenger/ui/TrustKeysActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/TrustKeysActivity.java
@@ -31,6 +31,7 @@ import de.pixart.messenger.databinding.KeysCardBinding;
import de.pixart.messenger.entities.Account;
import de.pixart.messenger.entities.Conversation;
import de.pixart.messenger.utils.CryptoHelper;
+import de.pixart.messenger.utils.IrregularUnicodeBlockDetector;
import de.pixart.messenger.utils.XmppUri;
import de.pixart.messenger.xmpp.OnKeyStatusUpdated;
import rocks.xmpp.addr.Jid;
@@ -189,9 +190,8 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat
for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) {
hasForeignKeys = true;
KeysCardBinding keysCardBinding = DataBindingUtil.inflate(getLayoutInflater(),R.layout.keys_card, binding.foreignKeys,false);
- //final LinearLayout layout = (LinearLayout) getLayoutInflater().inflate(R.layout.keys_card, foreignKeys, false);
final Jid jid = entry.getKey();
- keysCardBinding.foreignKeysTitle.setText(jid.toString());
+ keysCardBinding.foreignKeysTitle.setText(IrregularUnicodeBlockDetector.style(this, jid));
keysCardBinding.foreignKeysTitle.setOnClickListener(v -> switchToContactDetails(mAccount.getRoster().getContact(jid)));
final Map<String, Boolean> fingerprints = entry.getValue();
for (final String fingerprint : fingerprints.keySet()) {
@@ -391,7 +391,7 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat
fingerprint,
FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)));
}
- List<Jid> acceptedTargets = mConversation == null ? new ArrayList<Jid>() : mConversation.getAcceptedCryptoTargets();
+ List<Jid> acceptedTargets = mConversation == null ? new ArrayList<>() : mConversation.getAcceptedCryptoTargets();
synchronized (this.foreignKeysToTrust) {
for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) {
Jid jid = entry.getKey();
diff --git a/src/main/java/de/pixart/messenger/ui/adapter/ListItemAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/ListItemAdapter.java
index f25e6e51d..821483f33 100644
--- a/src/main/java/de/pixart/messenger/ui/adapter/ListItemAdapter.java
+++ b/src/main/java/de/pixart/messenger/ui/adapter/ListItemAdapter.java
@@ -27,7 +27,9 @@ import de.pixart.messenger.databinding.ContactBinding;
import de.pixart.messenger.entities.ListItem;
import de.pixart.messenger.ui.SettingsActivity;
import de.pixart.messenger.ui.XmppActivity;
+import de.pixart.messenger.utils.IrregularUnicodeBlockDetector;
import de.pixart.messenger.utils.UIHelper;
+import rocks.xmpp.addr.Jid;
public class ListItemAdapter extends ArrayAdapter<ListItem> {
@@ -87,10 +89,10 @@ public class ListItemAdapter extends ArrayAdapter<ListItem> {
viewHolder.tags.addView(tv);
}
}
- final String jid = item.getDisplayJid();
+ final Jid jid = item.getJid();
if (jid != null) {
viewHolder.jid.setVisibility(View.VISIBLE);
- viewHolder.jid.setText(jid);
+ viewHolder.jid.setText(IrregularUnicodeBlockDetector.style(activity, jid));
} else {
viewHolder.jid.setVisibility(View.GONE);
}
diff --git a/src/main/java/de/pixart/messenger/utils/IrregularUnicodeBlockDetector.java b/src/main/java/de/pixart/messenger/utils/IrregularUnicodeBlockDetector.java
new file mode 100644
index 000000000..df654eeb3
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/utils/IrregularUnicodeBlockDetector.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2018, Daniel Gultsch All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package de.pixart.messenger.utils;
+
+import android.content.Context;
+import android.support.annotation.ColorInt;
+import android.text.Spannable;
+import android.text.SpannableString;
+import android.text.SpannableStringBuilder;
+import android.text.style.ForegroundColorSpan;
+import android.util.LruCache;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import de.pixart.messenger.R;
+import de.pixart.messenger.ui.util.Color;
+import rocks.xmpp.addr.Jid;
+
+public class IrregularUnicodeBlockDetector {
+
+ private static final Map<Character.UnicodeBlock,Character.UnicodeBlock> NORMALIZATION_MAP;
+
+ static {
+ Map<Character.UnicodeBlock,Character.UnicodeBlock> temp = new HashMap<>();
+ temp.put(Character.UnicodeBlock.LATIN_1_SUPPLEMENT, Character.UnicodeBlock.BASIC_LATIN);
+ NORMALIZATION_MAP = Collections.unmodifiableMap(temp);
+ }
+
+ private static Character.UnicodeBlock normalize(Character.UnicodeBlock in) {
+ if (NORMALIZATION_MAP.containsKey(in)) {
+ return NORMALIZATION_MAP.get(in);
+ } else {
+ return in;
+ }
+ }
+
+ private static final LruCache<Jid, Pattern> CACHE = new LruCache<>(100);
+
+ public static Spannable style(Context context, Jid jid) {
+ return style(jid, Color.get(context, R.attr.color_warning));
+ }
+
+ private static Spannable style(Jid jid, @ColorInt int color) {
+ SpannableStringBuilder builder = new SpannableStringBuilder();
+ if (jid.getLocal() != null) {
+ SpannableString local = new SpannableString(jid.getLocal());
+ Matcher matcher = find(jid).matcher(local);
+ while (matcher.find()) {
+ if (matcher.start() < matcher.end()) {
+ local.setSpan(new ForegroundColorSpan(color), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
+ }
+ builder.append(local);
+ builder.append('@');
+ }
+ if (jid.getDomain() != null) {
+ builder.append(jid.getDomain());
+ }
+ if (builder.length() != 0 && jid.getResource() != null) {
+ builder.append('/');
+ builder.append(jid.getResource());
+ }
+ return builder;
+ }
+
+ private static Map<Character.UnicodeBlock, List<String>> map(Jid jid) {
+ Map<Character.UnicodeBlock, List<String>> map = new HashMap<>();
+ String local = jid.getLocal();
+ final int length = local.length();
+ for (int offset = 0; offset < length; ) {
+ final int codePoint = local.codePointAt(offset);
+ Character.UnicodeBlock block = normalize(Character.UnicodeBlock.of(codePoint));
+ List<String> codePoints;
+ if (map.containsKey(block)) {
+ codePoints = map.get(block);
+ } else {
+ codePoints = new ArrayList<>();
+ map.put(block, codePoints);
+ }
+ codePoints.add(String.copyValueOf(Character.toChars(codePoint)));
+ offset += Character.charCount(codePoint);
+ }
+ return map;
+ }
+
+ private static Set<String> eliminateFirstAndGetCodePoints(Map<Character.UnicodeBlock, List<String>> map) {
+ Character.UnicodeBlock block = Character.UnicodeBlock.BASIC_LATIN;
+ int size = 0;
+ for (Map.Entry<Character.UnicodeBlock, List<String>> entry : map.entrySet()) {
+ if (entry.getValue().size() > size) {
+ size = entry.getValue().size();
+ block = entry.getKey();
+ }
+ }
+ map.remove(block);
+ Set<String> all = new HashSet<>();
+ for (List<String> codePoints : map.values()) {
+ all.addAll(codePoints);
+ }
+ return all;
+ }
+
+ private static Pattern find(Jid jid) {
+ synchronized (CACHE) {
+ Pattern pattern = CACHE.get(jid);
+ if (pattern != null) {
+ return pattern;
+ }
+ pattern = create(eliminateFirstAndGetCodePoints(map(jid)));
+ CACHE.put(jid, pattern);
+ return pattern;
+ }
+ }
+
+ private static Pattern create(Set<String> codePoints) {
+ final StringBuilder pattern = new StringBuilder();
+ for (String codePoint : codePoints) {
+ if (pattern.length() != 0) {
+ pattern.append('|');
+ }
+ pattern.append(Pattern.quote(codePoint));
+ }
+ return Pattern.compile(pattern.toString());
+ }
+} \ No newline at end of file
diff --git a/src/main/res/values/colors.xml b/src/main/res/values/colors.xml
index 90e56a791..ad99d25c0 100644
--- a/src/main/res/values/colors.xml
+++ b/src/main/res/values/colors.xml
@@ -17,6 +17,8 @@
<color name="grey800">#ff424242</color>
<color name="red800">#ffc62828</color>
<color name="red500">#fff44336</color>
+ <color name="red_a700">#ffd50000</color>
+ <color name="red_a100">#ffff8a80</color>
<color name="orange500">#ffff9800</color>
<color name="bubble">#ff2e4272</color>
<color name="realwhite">#ffffffff</color>
diff --git a/src/main/res/values/themes.xml b/src/main/res/values/themes.xml
index a8103324e..fc5d264f8 100644
--- a/src/main/res/values/themes.xml
+++ b/src/main/res/values/themes.xml
@@ -8,6 +8,7 @@
<item name="color_background_primary">@color/grey50</item>
<item name="color_background_secondary">@color/grey200</item>
+ <item name="color_warning">@color/red_a700</item>
<item name="android:windowActionModeOverlay">true</item>
<item name="android:actionModeBackground">@color/accent</item>
@@ -62,6 +63,8 @@
<item name="ic_file_pdf">@drawable/ic_file_pdf_grey600_48dp</item>
<item name="ic_file_vcard">@drawable/ic_account_card_details_grey600_48dp</item>
<item name="ic_file_calendar">@drawable/ic_calendar_grey600_48dp</item>
+ <item name="color_warning">@color/red_a100</item>
+
</style>
<style name="ConversationsTheme.LargerText" parent="ConversationsTheme">