mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-30 13:35:18 +00:00
parent
2f6cefca8a
commit
e5e5b93884
BIN
assets/fonts/Roboto-Light.ttf
Normal file
BIN
assets/fonts/Roboto-Light.ttf
Normal file
Binary file not shown.
@ -39,6 +39,20 @@
|
|||||||
<item>Ukrainian Український</item>
|
<item>Ukrainian Український</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
<array name="avatar_colors">
|
||||||
|
<item>#6dcaec</item>
|
||||||
|
<item>#cf9fe7</item>
|
||||||
|
<item>#b6db49</item>
|
||||||
|
<item>#ffd060</item>
|
||||||
|
<item>#ff7979</item>
|
||||||
|
|
||||||
|
<item>#2cb1e1</item>
|
||||||
|
<item>#c182e0</item>
|
||||||
|
<item>#92c500</item>
|
||||||
|
<item>#ffb61c</item>
|
||||||
|
<item>#f83a3a</item>
|
||||||
|
</array>
|
||||||
|
|
||||||
<string-array name="language_values">
|
<string-array name="language_values">
|
||||||
<item>zz</item>
|
<item>zz</item>
|
||||||
<item>en</item>
|
<item>en</item>
|
||||||
|
@ -22,6 +22,7 @@ import android.content.Context;
|
|||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.res.TypedArray;
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
@ -40,6 +41,7 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.contacts.ContactPhotoFactory;
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
||||||
@ -405,7 +407,15 @@ public class ConversationItem extends LinearLayout {
|
|||||||
private void setContactPhotoForRecipient(final Recipient recipient) {
|
private void setContactPhotoForRecipient(final Recipient recipient) {
|
||||||
if (contactPhoto == null) return;
|
if (contactPhoto == null) return;
|
||||||
|
|
||||||
contactPhoto.setImageBitmap(recipient.getCircleCroppedContactPhoto());
|
Bitmap contactPhotoBitmap;
|
||||||
|
|
||||||
|
if ((recipient.getContactPhoto() == ContactPhotoFactory.getDefaultContactPhoto(context)) && (groupThread)) {
|
||||||
|
contactPhotoBitmap = recipient.getGeneratedAvatar(context);
|
||||||
|
} else {
|
||||||
|
contactPhotoBitmap = recipient.getCircleCroppedContactPhoto();
|
||||||
|
}
|
||||||
|
|
||||||
|
contactPhoto.setImageBitmap(contactPhotoBitmap);
|
||||||
|
|
||||||
contactPhoto.setOnClickListener(new View.OnClickListener() {
|
contactPhoto.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
|
120
src/org/thoughtcrime/securesms/recipients/AvatarGenerator.java
Normal file
120
src/org/thoughtcrime/securesms/recipients/AvatarGenerator.java
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
package org.thoughtcrime.securesms.recipients;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.Canvas;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.Rect;
|
||||||
|
import android.graphics.Typeface;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.R;
|
||||||
|
import org.thoughtcrime.securesms.contacts.ContactPhotoFactory;
|
||||||
|
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class to generate avatars for contacts who don't have a contact
|
||||||
|
* picture set.
|
||||||
|
*
|
||||||
|
* @author Lukas Barth
|
||||||
|
*/
|
||||||
|
public class AvatarGenerator {
|
||||||
|
|
||||||
|
public static Bitmap generateFor(Context context, Recipient recipient) {
|
||||||
|
if ((recipient == null) || (recipient.getName() == null)) {
|
||||||
|
return BitmapUtil.getCircleCroppedBitmap(ContactPhotoFactory.getDefaultContactPhoto(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
final int size = ContactPhotoFactory.getDefaultContactPhoto(context).getHeight();
|
||||||
|
final Bitmap output = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
|
||||||
|
final Canvas canvas = new Canvas(output);
|
||||||
|
final int color = getColorForRecipient(recipient, context);
|
||||||
|
final Paint paint = new Paint();
|
||||||
|
final int innerRectOffset = (int) Math.ceil((size - Math.sqrt(2) * (size / 2)) / 2);
|
||||||
|
final Rect innerRect = new Rect(innerRectOffset, innerRectOffset,
|
||||||
|
size - innerRectOffset, size - innerRectOffset);
|
||||||
|
|
||||||
|
paint.setAntiAlias(true);
|
||||||
|
paint.setColor(color);
|
||||||
|
canvas.drawCircle(size / 2, size / 2, size / 2, paint);
|
||||||
|
|
||||||
|
paint.setColor(Color.WHITE);
|
||||||
|
Typeface robotoLightTypeface = Typeface.createFromAsset(context.getAssets(), "fonts/Roboto-Light.ttf");
|
||||||
|
paint.setTypeface(robotoLightTypeface);
|
||||||
|
setFontSize(innerRect, paint);
|
||||||
|
|
||||||
|
paint.setTextAlign(Paint.Align.CENTER);
|
||||||
|
|
||||||
|
int initialIndex = 0;
|
||||||
|
char[] contactName = recipient.getName().toCharArray();
|
||||||
|
|
||||||
|
if (contactName.length == 0) {
|
||||||
|
contactName = new char[]{'?'};
|
||||||
|
initialIndex = 0;
|
||||||
|
} else {
|
||||||
|
while ((! Character.isLetter(contactName[initialIndex]))) {
|
||||||
|
initialIndex ++;
|
||||||
|
|
||||||
|
if (initialIndex >= contactName.length) {
|
||||||
|
contactName[0] = '?';
|
||||||
|
initialIndex = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect textBounds = new Rect();
|
||||||
|
paint.getTextBounds(contactName, initialIndex, 1, textBounds);
|
||||||
|
|
||||||
|
int bottomOffset = (innerRect.height() - textBounds.height()) / 2;
|
||||||
|
|
||||||
|
canvas.drawText(Character.toString(contactName[initialIndex]),
|
||||||
|
innerRect.centerX(), innerRect.bottom - bottomOffset, paint);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static int getColorForRecipient(Recipient recipient, Context context) {
|
||||||
|
if ((recipient == null) || (recipient.getName() == null)) {
|
||||||
|
return Color.WHITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
long nameHash = recipient.getName().hashCode();
|
||||||
|
Resources res = context.getResources();
|
||||||
|
TypedArray colorArray = res.obtainTypedArray(R.array.avatar_colors);
|
||||||
|
int index = Math.abs((int) (nameHash % colorArray.length()));
|
||||||
|
int color = colorArray.getColor(index, Color.BLACK);
|
||||||
|
|
||||||
|
colorArray.recycle();
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int setFontSize(Rect textRect, Paint paint) {
|
||||||
|
boolean overflow = false;
|
||||||
|
int currentSize = 0;
|
||||||
|
|
||||||
|
while (!overflow) {
|
||||||
|
currentSize++;
|
||||||
|
paint.setTextSize(currentSize);
|
||||||
|
|
||||||
|
Paint.FontMetricsInt fontMetrics = paint.getFontMetricsInt();
|
||||||
|
int textHeight = fontMetrics.descent - fontMetrics.ascent;
|
||||||
|
|
||||||
|
if (textHeight > textRect.height()) {
|
||||||
|
overflow = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
currentSize--;
|
||||||
|
|
||||||
|
currentSize *= 1.2;
|
||||||
|
|
||||||
|
paint.setTextSize(currentSize);
|
||||||
|
|
||||||
|
return currentSize;
|
||||||
|
}
|
||||||
|
}
|
@ -54,6 +54,7 @@ public class Recipient implements Parcelable {
|
|||||||
|
|
||||||
private Bitmap contactPhoto;
|
private Bitmap contactPhoto;
|
||||||
private Bitmap circleCroppedContactPhoto;
|
private Bitmap circleCroppedContactPhoto;
|
||||||
|
private Bitmap generatedAvatar;
|
||||||
|
|
||||||
private Uri contactUri;
|
private Uri contactUri;
|
||||||
|
|
||||||
@ -64,6 +65,7 @@ public class Recipient implements Parcelable {
|
|||||||
this.circleCroppedContactPhoto = circleCroppedContactPhoto;
|
this.circleCroppedContactPhoto = circleCroppedContactPhoto;
|
||||||
this.contactPhoto = contactPhoto;
|
this.contactPhoto = contactPhoto;
|
||||||
this.recipientId = recipientId;
|
this.recipientId = recipientId;
|
||||||
|
this.generatedAvatar = null;
|
||||||
|
|
||||||
future.addListener(new FutureTaskListener<RecipientDetails>() {
|
future.addListener(new FutureTaskListener<RecipientDetails>() {
|
||||||
@Override
|
@Override
|
||||||
@ -187,6 +189,13 @@ public class Recipient implements Parcelable {
|
|||||||
return this.circleCroppedContactPhoto;
|
return this.circleCroppedContactPhoto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public synchronized Bitmap getGeneratedAvatar(Context context) {
|
||||||
|
if (this.generatedAvatar == null)
|
||||||
|
this.generatedAvatar = AvatarGenerator.generateFor(context, this);
|
||||||
|
|
||||||
|
return this.generatedAvatar;
|
||||||
|
}
|
||||||
|
|
||||||
public static Recipient getUnknownRecipient(Context context) {
|
public static Recipient getUnknownRecipient(Context context) {
|
||||||
return new Recipient("Unknown", "Unknown", -1, null,
|
return new Recipient("Unknown", "Unknown", -1, null,
|
||||||
ContactPhotoFactory.getDefaultContactPhoto(context),
|
ContactPhotoFactory.getDefaultContactPhoto(context),
|
||||||
|
Loading…
Reference in New Issue
Block a user