diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index d126558911..88b62fd085 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -212,6 +212,8 @@
android:theme="@android:style/Theme.Translucent.NoTitleBar"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
+
+
diff --git a/build.gradle b/build.gradle
index 258a313d6f..a5916cc8d6 100644
--- a/build.gradle
+++ b/build.gradle
@@ -40,6 +40,8 @@ dependencies {
compile 'org.w3c:smil:1.0.0'
compile 'org.apache.httpcomponents:httpclient-android:4.3.5'
compile 'com.github.chrisbanes.photoview:library:1.2.3'
+ compile 'com.makeramen:roundedimageview:1.5.0'
+ compile 'com.soundcloud.android:android-crop:0.9.10@aar'
compile 'com.android.support:appcompat-v7:20.0.0'
compile 'com.madgag.spongycastle:prov:1.51.0.0'
compile 'com.google.zxing:android-integration:3.1.0'
@@ -71,6 +73,8 @@ dependencyVerification {
'org.w3c:smil:085dc40f2bb249651578bfa07499fd08b16ad0886dbe2c4078586a408da62f9b',
'org.apache.httpcomponents:httpclient-android:6f56466a9bd0d42934b90bfbfe9977a8b654c058bf44a12bdc2877c4e1f033f1',
'com.github.chrisbanes.photoview:library:8b5344e206f125e7ba9d684008f36c4992d03853c57e5814125f88496126e3cc',
+ 'com.makeramen:roundedimageview:7dda2e78c406760e5c356ccce59b0df46b5b171cf18abb891998594405021548',
+ 'com.soundcloud.android:android-crop:ffd4b973cf6e97f7d64118a0dc088df50e9066fd5634fe6911dd0c0c5d346177',
'com.android.support:appcompat-v7:736f576ab0b68d27bdf18b1e7931566e6d8254b73965175313e87f8866b91547',
'com.madgag.spongycastle:prov:b8c3fec3a59aac1aa04ccf4dad7179351e54ef7672f53f508151b614c131398a',
'com.google.zxing:android-integration:89e56aadf1164bd71e57949163c53abf90af368b51669c0d4a47a163335f95c4',
diff --git a/res/layout/conversation_item_received.xml b/res/layout/conversation_item_received.xml
index d919678a8c..cb292f3703 100644
--- a/res/layout/conversation_item_received.xml
+++ b/res/layout/conversation_item_received.xml
@@ -1,11 +1,12 @@
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:paddingRight="10dip"
+ android:orientation="vertical"
+ android:background="?conversation_item_background"
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto">
-
@@ -15,11 +16,12 @@
android:paddingRight="10dp"
android:visibility="visible">
-
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
diff --git a/res/layout/push_contact_selection_list_item.xml b/res/layout/push_contact_selection_list_item.xml
index 2e3d081bf4..7460dc7dde 100644
--- a/res/layout/push_contact_selection_list_item.xml
+++ b/res/layout/push_contact_selection_list_item.xml
@@ -1,11 +1,13 @@
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="match_parent"
+ android:layout_height="?android:attr/listPreferredItemHeight"
+ android:paddingRight="25dip">
-
localUserContactPhotoCache =
Collections.synchronizedMap(new LRUCache(2));
@@ -56,24 +52,6 @@ public class ContactPhotoFactory {
}
}
- public static Bitmap getDefaultContactPhotoCropped(Context context) {
- synchronized (defaultPhotoCroppedLock) {
- if (defaultContactPhotoCropped == null)
- defaultContactPhotoCropped = BitmapUtil.getCircleCroppedBitmap(getDefaultContactPhoto(context));
-
- return defaultContactPhotoCropped;
- }
- }
-
- public static Bitmap getDefaultGroupPhotoCropped(Context context) {
- synchronized (defaultGroupPhotoCroppedLock) {
- if (defaultGroupContactPhotoCropped == null)
- defaultGroupContactPhotoCropped = BitmapUtil.getCircleCroppedBitmap(getDefaultGroupPhoto(context));
-
- return defaultGroupContactPhotoCropped;
- }
- }
-
public static Bitmap getLocalUserContactPhoto(Context context, Uri uri) {
if (uri == null) return getDefaultContactPhoto(context);
diff --git a/src/org/thoughtcrime/securesms/contacts/ContactSelectionListAdapter.java b/src/org/thoughtcrime/securesms/contacts/ContactSelectionListAdapter.java
index 5a8039aedd..95e1d7f9e9 100644
--- a/src/org/thoughtcrime/securesms/contacts/ContactSelectionListAdapter.java
+++ b/src/org/thoughtcrime/securesms/contacts/ContactSelectionListAdapter.java
@@ -30,12 +30,10 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
-import android.widget.FilterQueryProvider;
import android.widget.ImageView;
import android.widget.TextView;
import org.thoughtcrime.securesms.R;
-import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.BitmapWorkerRunnable;
import org.thoughtcrime.securesms.util.BitmapWorkerRunnable.AsyncDrawable;
import org.thoughtcrime.securesms.util.TaggedFutureTask;
@@ -76,10 +74,9 @@ public class ContactSelectionListAdapter extends CursorAdapter
private final LayoutInflater li;
private final TypedArray drawables;
private final Bitmap defaultPhoto;
- private final Bitmap defaultCroppedPhoto;
private final int scaledPhotoSize;
- private final HashMap selectedContacts = new HashMap();
+ private final HashMap selectedContacts = new HashMap<>();
public ContactSelectionListAdapter(Context context, Cursor cursor, boolean multiSelect) {
super(context, cursor, 0);
@@ -89,7 +86,6 @@ public class ContactSelectionListAdapter extends CursorAdapter
this.multiSelect = multiSelect;
this.defaultPhoto = ContactPhotoFactory.getDefaultContactPhoto(context);
this.scaledPhotoSize = context.getResources().getDimensionPixelSize(R.dimen.contact_selection_photo_size);
- this.defaultCroppedPhoto = BitmapUtil.getScaledCircleCroppedBitmap(defaultPhoto, scaledPhotoSize);
}
public static class ViewHolder {
@@ -184,7 +180,7 @@ public class ContactSelectionListAdapter extends CursorAdapter
numberLabelSpan.setSpan(new ForegroundColorSpan(drawables.getColor(2, 0xff444444)), contactData.number.length(), numberWithLabel.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
holder.number.setText(numberLabelSpan);
}
- holder.contactPhoto.setImageBitmap(defaultCroppedPhoto);
+ holder.contactPhoto.setImageBitmap(defaultPhoto);
if (contactData.id > -1) loadBitmap(contactData.number, holder.contactPhoto);
}
@@ -237,7 +233,7 @@ public class ContactSelectionListAdapter extends CursorAdapter
if (cancelPotentialWork(number, imageView)) {
final BitmapWorkerRunnable runnable = new BitmapWorkerRunnable(context, imageView, defaultPhoto, number, scaledPhotoSize);
final TaggedFutureTask> task = new TaggedFutureTask(runnable, null, number);
- final AsyncDrawable asyncDrawable = new AsyncDrawable(context.getResources(), defaultCroppedPhoto, task);
+ final AsyncDrawable asyncDrawable = new AsyncDrawable(defaultPhoto, task);
imageView.setImageDrawable(asyncDrawable);
if (!task.isCancelled()) photoResolver.execute(new FutureTask(task, null));
diff --git a/src/org/thoughtcrime/securesms/recipients/AvatarGenerator.java b/src/org/thoughtcrime/securesms/recipients/AvatarGenerator.java
index 188514435c..142f238613 100644
--- a/src/org/thoughtcrime/securesms/recipients/AvatarGenerator.java
+++ b/src/org/thoughtcrime/securesms/recipients/AvatarGenerator.java
@@ -24,7 +24,7 @@ public class AvatarGenerator {
public static Bitmap generateFor(Context context, Recipient recipient) {
if ((recipient == null) || (recipient.getName() == null)) {
- return BitmapUtil.getCircleCroppedBitmap(ContactPhotoFactory.getDefaultContactPhoto(context));
+ return ContactPhotoFactory.getDefaultContactPhoto(context);
}
final int size = ContactPhotoFactory.getDefaultContactPhoto(context).getHeight();
diff --git a/src/org/thoughtcrime/securesms/recipients/Recipient.java b/src/org/thoughtcrime/securesms/recipients/Recipient.java
index c317807975..cde6e9c262 100644
--- a/src/org/thoughtcrime/securesms/recipients/Recipient.java
+++ b/src/org/thoughtcrime/securesms/recipients/Recipient.java
@@ -41,16 +41,14 @@ public class Recipient {
private String name;
private Bitmap contactPhoto;
- private Bitmap circleCroppedContactPhoto;
private Bitmap generatedAvatar;
private Uri contactUri;
- Recipient(String number, Bitmap contactPhoto, Bitmap circleCroppedContactPhoto,
+ Recipient(String number, Bitmap contactPhoto,
long recipientId, ListenableFutureTask future)
{
this.number = number;
- this.circleCroppedContactPhoto = circleCroppedContactPhoto;
this.contactPhoto = contactPhoto;
this.recipientId = recipientId;
this.generatedAvatar = null;
@@ -66,8 +64,7 @@ public class Recipient {
Recipient.this.number = result.number;
Recipient.this.contactUri = result.contactUri;
Recipient.this.contactPhoto = result.avatar;
- Recipient.this.circleCroppedContactPhoto = result.croppedAvatar;
-
+
localListeners = (HashSet) listeners.clone();
listeners.clear();
}
@@ -84,15 +81,12 @@ public class Recipient {
});
}
- Recipient(String name, String number, long recipientId, Uri contactUri, Bitmap contactPhoto,
- Bitmap circleCroppedContactPhoto)
- {
+ Recipient(String name, String number, long recipientId, Uri contactUri, Bitmap contactPhoto) {
this.number = number;
this.recipientId = recipientId;
this.contactUri = contactUri;
this.name = name;
this.contactPhoto = contactPhoto;
- this.circleCroppedContactPhoto = circleCroppedContactPhoto;
}
public synchronized Uri getContactUri() {
@@ -153,10 +147,6 @@ public class Recipient {
return contactPhoto;
}
- public synchronized Bitmap getCircleCroppedContactPhoto() {
- return this.circleCroppedContactPhoto;
- }
-
public synchronized Bitmap getGeneratedAvatar(Context context) {
if (this.generatedAvatar == null)
this.generatedAvatar = AvatarGenerator.generateFor(context, this);
@@ -166,8 +156,7 @@ public class Recipient {
public static Recipient getUnknownRecipient(Context context) {
return new Recipient("Unknown", "Unknown", -1, null,
- ContactPhotoFactory.getDefaultContactPhoto(context),
- ContactPhotoFactory.getDefaultContactPhotoCropped(context));
+ ContactPhotoFactory.getDefaultContactPhoto(context));
}
@Override
diff --git a/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java b/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java
index 6cf15b0f29..a0a941221e 100644
--- a/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java
+++ b/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java
@@ -73,17 +73,13 @@ public class RecipientProvider {
else details = getRecipientDetails(context, number);
if (details != null) {
- recipient = new Recipient(details.name, details.number, recipientId, details.contactUri, details.avatar,
- details.croppedAvatar);
+ recipient = new Recipient(details.name, details.number, recipientId, details.contactUri, details.avatar);
} else {
final Bitmap defaultPhoto = isGroupRecipient
? ContactPhotoFactory.getDefaultGroupPhoto(context)
: ContactPhotoFactory.getDefaultContactPhoto(context);
- final Bitmap defaultCroppedPhoto = isGroupRecipient
- ? ContactPhotoFactory.getDefaultGroupPhotoCropped(context)
- : ContactPhotoFactory.getDefaultContactPhotoCropped(context);
- recipient = new Recipient(null, number, recipientId, null, defaultPhoto, defaultCroppedPhoto);
+ recipient = new Recipient(null, number, recipientId, null, defaultPhoto);
}
recipientCache.put(recipientId, recipient);
@@ -109,17 +105,14 @@ public class RecipientProvider {
asyncRecipientResolver.submit(future);
Bitmap contactPhoto;
- Bitmap contactPhotoCropped;
if (isGroupRecipient) {
contactPhoto = ContactPhotoFactory.getDefaultGroupPhoto(context);
- contactPhotoCropped = ContactPhotoFactory.getDefaultGroupPhotoCropped(context);
} else {
contactPhoto = ContactPhotoFactory.getDefaultContactPhoto(context);
- contactPhotoCropped = ContactPhotoFactory.getDefaultContactPhotoCropped(context);
}
- Recipient recipient = new Recipient(number, contactPhoto, contactPhotoCropped, recipientId, future);
+ Recipient recipient = new Recipient(number, contactPhoto, recipientId, future);
recipientCache.put(recipientId, recipient);
return recipient;
@@ -144,8 +137,7 @@ public class RecipientProvider {
Uri contactUri = Contacts.getLookupUri(cursor.getLong(2), cursor.getString(1));
Bitmap contactPhoto = ContactPhotoFactory.getContactPhoto(context, Uri.withAppendedPath(Contacts.CONTENT_URI,
cursor.getLong(2)+""));
- return new RecipientDetails(cursor.getString(0), cursor.getString(3), contactUri, contactPhoto,
- BitmapUtil.getCircleCroppedBitmap(contactPhoto));
+ return new RecipientDetails(cursor.getString(0), cursor.getString(3), contactUri, contactPhoto);
}
} finally {
if (cursor != null)
@@ -167,7 +159,7 @@ public class RecipientProvider {
if (avatarBytes == null) avatar = ContactPhotoFactory.getDefaultGroupPhoto(context);
else avatar = BitmapFactory.decodeByteArray(avatarBytes, 0, avatarBytes.length);
- return new RecipientDetails(record.getTitle(), groupId, null, avatar, BitmapUtil.getCircleCroppedBitmap(avatar));
+ return new RecipientDetails(record.getTitle(), groupId, null, avatar);
}
return null;
@@ -181,14 +173,12 @@ public class RecipientProvider {
public final String name;
public final String number;
public final Bitmap avatar;
- public final Bitmap croppedAvatar;
public final Uri contactUri;
- public RecipientDetails(String name, String number, Uri contactUri, Bitmap avatar, Bitmap croppedAvatar) {
+ public RecipientDetails(String name, String number, Uri contactUri, Bitmap avatar) {
this.name = name;
this.number = number;
this.avatar = avatar;
- this.croppedAvatar = croppedAvatar;
this.contactUri = contactUri;
}
}
diff --git a/src/org/thoughtcrime/securesms/util/BitmapUtil.java b/src/org/thoughtcrime/securesms/util/BitmapUtil.java
index 6fd86507e5..4590dd43de 100644
--- a/src/org/thoughtcrime/securesms/util/BitmapUtil.java
+++ b/src/org/thoughtcrime/securesms/util/BitmapUtil.java
@@ -217,41 +217,6 @@ public class BitmapUtil {
return new Pair<>(options.outWidth, options.outHeight);
}
- public static Bitmap getCircleCroppedBitmap(Bitmap bitmap) {
- if (bitmap == null) return null;
- final int srcSize = Math.min(bitmap.getWidth(), bitmap.getHeight());
- return getScaledCircleCroppedBitmap(bitmap, srcSize);
- }
-
- public static Bitmap getScaledCircleCroppedBitmap(Context context, MasterSecret masterSecret, Uri uri, int destSize)
- throws IOException, BitmapDecodingException
- {
- Bitmap bitmap = createScaledBitmap(context, masterSecret, uri, destSize, destSize);
- return getScaledCircleCroppedBitmap(bitmap, destSize);
- }
-
- public static Bitmap getScaledCircleCroppedBitmap(Bitmap bitmap, int destSize) {
- if (bitmap == null) return null;
- Bitmap output = Bitmap.createBitmap(destSize, destSize, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(output);
-
- final int srcSize = Math.min(bitmap.getWidth(), bitmap.getHeight());
- final int srcX = (bitmap.getWidth() - srcSize) / 2;
- final int srcY = (bitmap.getHeight() - srcSize) / 2;
- final Rect srcRect = new Rect(srcX, srcY, srcX + srcSize, srcY + srcSize);
- final Rect destRect = new Rect(0, 0, destSize, destSize);
- final int color = 0xff424242;
- final Paint paint = new Paint();
-
- paint.setAntiAlias(true);
- canvas.drawARGB(0, 0, 0, 0);
- paint.setColor(color);
- canvas.drawCircle(destSize / 2, destSize / 2, destSize / 2, paint);
- paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
- canvas.drawBitmap(bitmap, srcRect, destRect, paint);
- return output;
- }
-
public static InputStream toCompressedJpeg(Bitmap bitmap) {
ByteArrayOutputStream thumbnailBytes = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG, 85, thumbnailBytes);
diff --git a/src/org/thoughtcrime/securesms/util/BitmapWorkerRunnable.java b/src/org/thoughtcrime/securesms/util/BitmapWorkerRunnable.java
index 90676b0f4d..c5bf9a121a 100644
--- a/src/org/thoughtcrime/securesms/util/BitmapWorkerRunnable.java
+++ b/src/org/thoughtcrime/securesms/util/BitmapWorkerRunnable.java
@@ -25,6 +25,8 @@ import android.graphics.drawable.Drawable;
import android.util.Log;
import android.widget.ImageView;
+import com.makeramen.RoundedDrawable;
+
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
@@ -48,7 +50,7 @@ public class BitmapWorkerRunnable implements Runnable {
public final String number;
public BitmapWorkerRunnable(Context context, ImageView imageView, Bitmap defaultPhoto, String number, int size) {
- this.imageViewReference = new WeakReference(imageView);
+ this.imageViewReference = new WeakReference<>(imageView);
this.context = context;
this.defaultPhoto = defaultPhoto;
this.size = size;
@@ -57,42 +59,36 @@ public class BitmapWorkerRunnable implements Runnable {
@Override
public void run() {
- final Bitmap bitmap;
try {
final Recipient recipient = RecipientFactory.getRecipientsFromString(context, number, false).getPrimaryRecipient();
final Bitmap contactPhoto = recipient.getContactPhoto();
if (defaultPhoto == contactPhoto) {
return;
}
+ if (recipient.getContactPhoto() != null) {
+ final ImageView imageView = imageViewReference.get();
+ final TaggedFutureTask> bitmapWorkerTask = AsyncDrawable.getBitmapWorkerTask(imageView);
- bitmap = BitmapUtil.getScaledCircleCroppedBitmap(contactPhoto, size);
+ if (bitmapWorkerTask.getTag().equals(number) && imageView != null) {
+ final BitmapDrawable drawable = new BitmapDrawable(context.getResources(), recipient.getContactPhoto());
+ imageView.post(new Runnable() {
+ @Override
+ public void run() {
+ imageView.setImageDrawable(drawable);
+ }
+ });
+ }
+ }
} catch (RecipientFormattingException rfe) {
Log.w(TAG, "Couldn't get recipient from string", rfe);
- return;
- }
-
- if (bitmap != null) {
- final ImageView imageView = imageViewReference.get();
- final TaggedFutureTask> bitmapWorkerTask = AsyncDrawable.getBitmapWorkerTask(imageView);
-
- if (bitmapWorkerTask.getTag().equals(number) && imageView != null) {
- final BitmapDrawable drawable = new BitmapDrawable(context.getResources(), bitmap);
- imageView.post(new Runnable() {
- @Override
- public void run() {
- imageView.setImageDrawable(drawable);
- }
- });
- }
}
}
- public static class AsyncDrawable extends BitmapDrawable {
+ public static class AsyncDrawable extends RoundedDrawable {
private final WeakReference> bitmapWorkerTaskReference;
- public AsyncDrawable(Resources res, Bitmap bitmap,
- TaggedFutureTask> bitmapWorkerTask) {
- super(res, bitmap);
+ public AsyncDrawable(Bitmap bitmap, TaggedFutureTask> bitmapWorkerTask) {
+ super(bitmap);
bitmapWorkerTaskReference =
new WeakReference>(bitmapWorkerTask);
}
@@ -112,5 +108,4 @@ public class BitmapWorkerRunnable implements Runnable {
return null;
}
}
-
}