Skip to content

Commit

Permalink
Assign color to group members based on XEP-0392
Browse files Browse the repository at this point in the history
More or less. Close #1122

Signed-off-by: Daniele Ricci <[email protected]>
  • Loading branch information
daniele-athome committed Dec 22, 2017
1 parent b7463be commit 3a502a2
Show file tree
Hide file tree
Showing 7 changed files with 207 additions and 1 deletion.
33 changes: 33 additions & 0 deletions app/src/androidTest/java/org/kontalk/util/XMPPUtilsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Kontalk Android client
* Copyright (C) 2017 Kontalk Devteam <[email protected]>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.kontalk.util;

import org.junit.Test;

import static org.junit.Assert.*;


public class XMPPUtilsTest {

@Test
public void testGetJIDColor() throws Exception {
assertEquals(0xff55ff00, XMPPUtils.getJIDColor("[email protected]"));
}

}
2 changes: 2 additions & 0 deletions app/src/main/java/org/kontalk/ui/view/BaseMessageTheme.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.kontalk.message.MessageComponent;
import org.kontalk.message.TextComponent;
import org.kontalk.provider.MyMessages;
import org.kontalk.util.XMPPUtils;


/**
Expand Down Expand Up @@ -133,6 +134,7 @@ public void setIncoming(Contact contact, boolean sameMessageBlock) {
if (mGroupChat) {
if (contact != null) {
mContactNameView.setText(contact.getDisplayName());
mContactNameView.setTextColor(XMPPUtils.getJIDColor(contact.getJID()));
mContactNameView.setVisibility(View.VISIBLE);
}
else {
Expand Down
105 changes: 105 additions & 0 deletions app/src/main/java/org/kontalk/util/ConsistentColorGeneration.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
* Kontalk Android client
* Copyright (C) 2017 Kontalk Devteam <[email protected]>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.kontalk.util;

import org.jivesoftware.smack.util.SHA1;


/**
* Implementation of XEP-0392: Consistent Color Generation<br>
* TODO this class is a brutal porting from JavaScript code and should be optimized
* @see <a href="https://xmpp.org/extensions/xep-0392.html">XEP-0392</a>
* @see <a href="https://github.com/jsxc/consistent-color-generation">Ported from JavaScript implementation</a>
*/
public class ConsistentColorGeneration {

public static final int CORRECTION_NONE = 0;
public static final int CORRECTION_REDGREEN = 1;
public static final int CORRECTION_BLUE = 2;

private static final double KR = 0.299;
private static final double KG = 0.587;
private static final double KB = 0.114;

private ConsistentColorGeneration() {}

public static double[] getRGB(String identifier, int correction) {
return getRGB(identifier, correction, 0.732);
}

public static double[] getRGB(String identifier, int correction, double y) {
double angle = generateAngle(identifier, correction);
double[] space = generateCbCr(angle);

return cbCrToRGB(space[0], space[1], y);
}

private static double[] generateCbCr(double angle) {
double cr = Math.sin(angle);
double cb = Math.cos(angle);
double factor;

if (Math.abs(cr) > Math.abs(cb)) {
factor = 0.5d / Math.abs(cr);
}
else {
factor = 0.5d / Math.abs(cb);
}

cb = cb * factor;
cr = cr * factor;

return new double[] { cb, cr };
}

private static double generateAngle(String identifier, int correction) {
String hash = SHA1.hex(identifier);
String first16bits = hash.substring(0, 4);
String littleEndian = first16bits.substring(2) + first16bits.substring(0, 2);
double angle = (double) Integer.parseInt(littleEndian, 16) / 65535 * 2 * Math.PI;

switch (correction) {
case CORRECTION_REDGREEN:
angle /= 2;
break;
case CORRECTION_BLUE:
angle = (angle / 2) + (Math.PI / 2);
break;
}

return angle;
}

private static double clipValueToRangeFrom0To1(double value) {
return Math.max(0, Math.min(value, 1));
}

private static double[] cbCrToRGB(double cb, double cr, double y) {
double r = 2 * (1 - KR) * cr + y;
double b = 2 * (1 - KB) * cb + y;
double g = (y - KR * r - KB * b) / KG;

return new double[] {
clipValueToRangeFrom0To1(r),
clipValueToRangeFrom0To1(g),
clipValueToRangeFrom0To1(b),
};
}

}
3 changes: 2 additions & 1 deletion app/src/main/java/org/kontalk/util/MessageUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,8 @@ public static String bytesToHex(byte[] data) {
return buf.toString();
}

/** TODO move somewhere else */
/** @deprecated Use {@link org.jivesoftware.smack.util.SHA1#hex(String)} */
@Deprecated
public static String sha1(String text) {
MessageDigest md = new SHA1.Digest();
md.update(text.getBytes(), 0, text.length());
Expand Down
18 changes: 18 additions & 0 deletions app/src/main/java/org/kontalk/util/XMPPUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import org.xmlpull.v1.XmlPullParserFactory;

import android.content.Context;
import android.graphics.Color;
import android.support.annotation.ColorInt;

import org.kontalk.client.EndpointServer;

Expand Down Expand Up @@ -139,4 +141,20 @@ public static boolean isDomainJID(String jid) {
.equalsIgnoreCase(jid);
}

/**
* Returns a color for the given JID calculated with the rules of XEP-0392
* @see <a href="https://xmpp.org/extensions/xep-0392.html">XEP-0392</a>
*/
@ColorInt
public static int getJIDColor(String jid) {
// TODO get correction from accessibility settings
double[] rgb = ConsistentColorGeneration.getRGB(jid,
ConsistentColorGeneration.CORRECTION_NONE);

return Color.argb(0xff,
(int) (rgb[0] * 255),
(int) (rgb[1] * 255),
(int) (rgb[2] * 255));
}

}
2 changes: 2 additions & 0 deletions app/src/main/res/layout/balloon_avatar_in.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
android:gravity="start">

<TextView android:id="@+id/contact_name"
style="?android:attr/textAppearance"
android:textStyle="bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Kontalk Android client
* Copyright (C) 2017 Kontalk Devteam <[email protected]>
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package org.kontalk.util;

import org.junit.Test;

import static org.junit.Assert.*;


public class ConsistentColorGenerationTest {

@Test
public void testGetRGB() throws Exception {
double[] rgb;

rgb = ConsistentColorGeneration.getRGB("[email protected]",
ConsistentColorGeneration.CORRECTION_NONE);
assertEquals(rgb[0], 0.337, 0.01);
assertEquals(rgb[1], 1.000, 0.01);
assertEquals(rgb[2], 0.000, 0.01);

rgb = ConsistentColorGeneration.getRGB("Romeo",
ConsistentColorGeneration.CORRECTION_NONE);
assertEquals(rgb[0], 0.281, 0.01);
assertEquals(rgb[1], 0.790, 0.01);
assertEquals(rgb[2], 1.000, 0.01);
}

}

0 comments on commit 3a502a2

Please sign in to comment.