mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-23 18:15:22 +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>
|
||||
</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">
|
||||
<item>zz</item>
|
||||
<item>en</item>
|
||||
|
@ -22,6 +22,7 @@ import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.net.Uri;
|
||||
@ -40,6 +41,7 @@ import android.widget.Toast;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.contacts.ContactPhotoFactory;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
||||
@ -405,7 +407,15 @@ public class ConversationItem extends LinearLayout {
|
||||
private void setContactPhotoForRecipient(final Recipient recipient) {
|
||||
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() {
|
||||
@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 circleCroppedContactPhoto;
|
||||
private Bitmap generatedAvatar;
|
||||
|
||||
private Uri contactUri;
|
||||
|
||||
@ -64,6 +65,7 @@ public class Recipient implements Parcelable {
|
||||
this.circleCroppedContactPhoto = circleCroppedContactPhoto;
|
||||
this.contactPhoto = contactPhoto;
|
||||
this.recipientId = recipientId;
|
||||
this.generatedAvatar = null;
|
||||
|
||||
future.addListener(new FutureTaskListener<RecipientDetails>() {
|
||||
@Override
|
||||
@ -187,6 +189,13 @@ public class Recipient implements Parcelable {
|
||||
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) {
|
||||
return new Recipient("Unknown", "Unknown", -1, null,
|
||||
ContactPhotoFactory.getDefaultContactPhoto(context),
|
||||
|
Loading…
Reference in New Issue
Block a user