Skip to content

Commit

Permalink
Use Glide for loading part thumbnails
Browse files Browse the repository at this point in the history
Closes signalapp#2885

// FREEBIE
  • Loading branch information
mcginty authored and moxie0 committed Apr 21, 2015
1 parent 9ba19df commit f42d100
Show file tree
Hide file tree
Showing 26 changed files with 500 additions and 423 deletions.
3 changes: 3 additions & 0 deletions AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@
<meta-data android:name="com.google.android.gms.version"
android:value="@integer/google_play_services_version" />

<meta-data android:name="org.thoughtcrime.securesms.mms.TextSecureGlideModule"
android:value="GlideModule" />

<activity android:name=".RegistrationProblemsActivity"
android:theme="@style/TextSecure.Light.Dialog"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
Expand Down
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ 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.github.bumptech.glide:glide:3.5.2'
compile 'com.makeramen:roundedimageview:1.5.0'
compile ('com.afollestad:material-dialogs:0.6.4.7') {
exclude module: 'appcompat-v7'
Expand Down Expand Up @@ -88,6 +89,7 @@ dependencyVerification {
'org.w3c:smil:085dc40f2bb249651578bfa07499fd08b16ad0886dbe2c4078586a408da62f9b',
'org.apache.httpcomponents:httpclient-android:6f56466a9bd0d42934b90bfbfe9977a8b654c058bf44a12bdc2877c4e1f033f1',
'com.github.chrisbanes.photoview:library:8b5344e206f125e7ba9d684008f36c4992d03853c57e5814125f88496126e3cc',
'com.github.bumptech.glide:glide:16936352b96aa604b030f2d2263fb0cc656933e6cdda0bf6ac681282d1f7f196',
'com.makeramen:roundedimageview:7dda2e78c406760e5c356ccce59b0df46b5b171cf18abb891998594405021548',
'com.afollestad:material-dialogs:6ed57c1c479219f8ae929c310fc171dbfcbcee8326a6dcd50a91959d69eccdf0',
'com.soundcloud.android:android-crop:ffd4b973cf6e97f7d64118a0dc088df50e9066fd5634fe6911dd0c0c5d346177',
Expand Down Expand Up @@ -167,6 +169,7 @@ android {
'proguard-square-okio.pro',
'proguard-spongycastle.pro',
'proguard-rounded-image-view.pro',
'proguard-glide.pro',
'proguard.cfg'
}
release {
Expand All @@ -181,6 +184,7 @@ android {
'proguard-square-okio.pro',
'proguard-spongycastle.pro',
'proguard-rounded-image-view.pro',
'proguard-glide.pro',
'proguard.cfg'
signingConfig signingConfigs.release
}
Expand Down
4 changes: 4 additions & 0 deletions proguard-glide.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
2 changes: 1 addition & 1 deletion res/layout/conversation_activity.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
android:orientation="horizontal"
android:visibility="gone">

<ImageView
<org.thoughtcrime.securesms.components.ThumbnailView
android:id="@+id/attachment_thumbnail"
android:layout_width="0dp"
android:layout_height="150dip"
Expand Down
4 changes: 2 additions & 2 deletions res/layout/conversation_bubble_incoming.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content">

<org.thoughtcrime.securesms.components.ForegroundImageView
<org.thoughtcrime.securesms.components.ThumbnailView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="@dimen/media_bubble_height"
android:layout_marginRight="@dimen/message_bubble_end_padding"
android:visibility="gone"
android:layout_gravity="center"
android:scaleType="centerCrop"
android:scaleType="centerInside"
android:adjustViewBounds="true"
android:contentDescription="@string/conversation_item__mms_image_description"
app:riv_corner_radius="@dimen/message_bubble_corner_radius"
Expand Down
2 changes: 1 addition & 1 deletion res/layout/conversation_bubble_outgoing.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
android:layout_gravity="center"
android:layout_height="wrap_content">

<org.thoughtcrime.securesms.components.ForegroundImageView
<org.thoughtcrime.securesms.components.ThumbnailView
android:id="@+id/image_view"
android:layout_width="wrap_content"
android:layout_height="@dimen/media_bubble_height"
Expand Down
2 changes: 1 addition & 1 deletion res/layout/media_overview_item.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
android:layout_width="match_parent"
android:layout_height="match_parent">

<org.thoughtcrime.securesms.components.ForegroundImageView
<org.thoughtcrime.securesms.components.ThumbnailView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
Expand Down
2 changes: 1 addition & 1 deletion res/values/colors.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='UTF-8'?>
<resources>
<color name="textsecure_primary">#ff2090ea</color>
<color name="textsecure_primary_dark">#ff145c95</color>
<color name="textsecure_primary_dark">#ff1c7ac5</color>

<color name="white">#ffffffff</color>
<color name="black">#ff000000</color>
Expand Down
120 changes: 12 additions & 108 deletions src/org/thoughtcrime/securesms/ConversationItem.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,12 @@
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.provider.ContactsContract;
import android.provider.ContactsContract.QuickContact;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.util.Pair;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
Expand All @@ -43,7 +39,7 @@

import org.thoughtcrime.securesms.ConversationFragment.SelectionClickListener;
import org.thoughtcrime.securesms.components.BubbleContainer;
import org.thoughtcrime.securesms.components.ForegroundImageView;
import org.thoughtcrime.securesms.components.ThumbnailView;
import org.thoughtcrime.securesms.contacts.ContactPhotoFactory;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory;
Expand All @@ -58,12 +54,9 @@
import org.thoughtcrime.securesms.jobs.SmsSendJob;
import org.thoughtcrime.securesms.mms.PartAuthority;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.mms.SlideDeck;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.Emoji;
import org.thoughtcrime.securesms.util.FutureTaskListener;
import org.thoughtcrime.securesms.util.ListenableFutureTask;

import java.util.Set;

Expand Down Expand Up @@ -97,16 +90,10 @@ public class ConversationItem extends LinearLayout {

private Set<MessageRecord> batchSelected;
private SelectionClickListener selectionClickListener;
private ForegroundImageView mediaThumbnail;
private ThumbnailView mediaThumbnail;
private Button mmsDownloadButton;
private TextView mmsDownloadingLabel;

private ListenableFutureTask<SlideDeck> slideDeckFuture;
private ListenableFutureTask<Pair<Drawable, Boolean>> thumbnailFuture;
private SlideDeckListener slideDeckListener;
private ThumbnailListener thumbnailListener;
private Handler handler;

private final MmsDownloadClickListener mmsDownloadClickListener = new MmsDownloadClickListener();
private final MmsPreferencesClickListener mmsPreferencesClickListener = new MmsPreferencesClickListener();
private final ClickListener clickListener = new ClickListener();
Expand Down Expand Up @@ -139,14 +126,14 @@ protected void onFinishInflate() {
this.bodyBubble = findViewById(R.id.body_bubble);
this.pendingIndicator = (ImageView)findViewById(R.id.pending_approval_indicator);
this.bubbleContainer = (BubbleContainer)findViewById(R.id.bubble);
this.mediaThumbnail = (ForegroundImageView)findViewById(R.id.image_view);

slideDeckListener = new SlideDeckListener();
handler = new Handler(Looper.getMainLooper());
this.mediaThumbnail = (ThumbnailView)findViewById(R.id.image_view);

setOnClickListener(clickListener);
if (mmsDownloadButton != null) mmsDownloadButton.setOnClickListener(mmsDownloadClickListener);
if (mediaThumbnail != null) mediaThumbnail.setOnLongClickListener(new MultiSelectLongClickListener());
if (mediaThumbnail != null) {
mediaThumbnail.setThumbnailClickListener(new ThumbnailClickListener());
mediaThumbnail.setOnLongClickListener(new MultiSelectLongClickListener());
}
}

public void set(@NonNull MasterSecret masterSecret,
Expand Down Expand Up @@ -177,13 +164,6 @@ public void set(@NonNull MasterSecret masterSecret,
}

public void unbind() {
if (slideDeckFuture != null && slideDeckListener != null) {
slideDeckFuture.removeListener(slideDeckListener);
}

if (thumbnailFuture != null && thumbnailListener != null) {
thumbnailFuture.removeListener(thumbnailListener);
}
}

public MessageRecord getMessageRecord() {
Expand Down Expand Up @@ -376,8 +356,7 @@ else if (MmsDatabase.Status.DOWNLOAD_APN_UNAVAILABLE == messageRecord.getStatus(

private void resolveMedia(MediaMmsMessageRecord messageRecord) {
if (hasMedia(messageRecord)) {
slideDeckFuture = messageRecord.getSlideDeckFuture();
slideDeckFuture.addListener(slideDeckListener);
mediaThumbnail.setImageResource(messageRecord.getSlideDeckFuture(), masterSecret);
}
}

Expand Down Expand Up @@ -429,14 +408,8 @@ private void handleKeyExchangeClicked() {
context.startActivity(intent);
}

private class ThumbnailClickListener implements View.OnClickListener {
private final Slide slide;

public ThumbnailClickListener(Slide slide) {
this.slide = slide;
}

private void fireIntent() {
private class ThumbnailClickListener implements ThumbnailView.ThumbnailClickListener {
private void fireIntent(Slide slide) {
Log.w(TAG, "Clicked: " + slide.getUri() + " , " + slide.getContentType());
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
Expand All @@ -449,7 +422,7 @@ private void fireIntent() {
}
}

public void onClick(View v) {
public void onClick(final View v, final Slide slide) {
if (!batchSelected.isEmpty()) {
selectionClickListener.onItemClick(null, ConversationItem.this, -1, -1);
} else if (MediaPreviewActivity.isContentTypeSupported(slide.getContentType())) {
Expand All @@ -468,7 +441,7 @@ public void onClick(View v) {
builder.setMessage(R.string.ConversationItem_this_media_has_been_stored_in_an_encrypted_database_external_viewer_warning);
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
fireIntent();
fireIntent(slide);
}
});
builder.setNegativeButton(R.string.no, null);
Expand Down Expand Up @@ -587,73 +560,4 @@ public void onClick(DialogInterface dialogInterface, int i) {
});
builder.show();
}

private class ThumbnailListener implements FutureTaskListener<Pair<Drawable, Boolean>> {
private final Object tag;

public ThumbnailListener(Object tag) {
this.tag = tag;
}

@Override
public void onSuccess(final Pair<Drawable, Boolean> result) {
handler.post(new Runnable() {
@Override
public void run() {
if (mediaThumbnail.getTag() == tag) {
Log.w(TAG, "displaying media thumbnail");
mediaThumbnail.show(result.first, result.second);
}
}
});
}

@Override
public void onFailure(Throwable error) {
Log.w(TAG, error);
handler.post(new Runnable() {
@Override
public void run() {
mediaThumbnail.hide();
}
});
}
}

private class SlideDeckListener implements FutureTaskListener<SlideDeck> {
@Override
public void onSuccess(final SlideDeck slideDeck) {
if (slideDeck == null) return;

handler.post(new Runnable() {
@Override
public void run() {
Slide slide = slideDeck.getThumbnailSlide(context);
if (slide != null) {
thumbnailFuture = slide.getThumbnail(context);
if (thumbnailFuture != null) {
Object tag = new Object();
mediaThumbnail.setTag(tag);
thumbnailListener = new ThumbnailListener(tag);
thumbnailFuture.addListener(thumbnailListener);
mediaThumbnail.setOnClickListener(new ThumbnailClickListener(slide));
return;
}
}
mediaThumbnail.hide();
}
});
}

@Override
public void onFailure(Throwable error) {
Log.w(TAG, error);
handler.post(new Runnable() {
@Override
public void run() {
mediaThumbnail.hide();
}
});
}
}
}
34 changes: 6 additions & 28 deletions src/org/thoughtcrime/securesms/ImageMediaAdapter.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,21 @@
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;

import org.thoughtcrime.securesms.ImageMediaAdapter.ViewHolder;
import org.thoughtcrime.securesms.components.ForegroundImageView;
import org.thoughtcrime.securesms.components.ThumbnailView;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.database.PartDatabase.ImageRecord;
import org.thoughtcrime.securesms.mms.Slide;
import org.thoughtcrime.securesms.recipients.RecipientFactory;
import org.thoughtcrime.securesms.recipients.Recipients;
import org.thoughtcrime.securesms.util.FutureTaskListener;
import org.thoughtcrime.securesms.util.MediaUtil;

import ws.com.google.android.mms.pdu.PduPart;
Expand All @@ -46,21 +42,19 @@ public class ImageMediaAdapter extends CursorRecyclerViewAdapter<ViewHolder> {
private static final String TAG = ImageMediaAdapter.class.getSimpleName();

private final MasterSecret masterSecret;
private final int gridSize;

public static class ViewHolder extends RecyclerView.ViewHolder {
public ForegroundImageView imageView;
public ThumbnailView imageView;

public ViewHolder(View v) {
super(v);
imageView = (ForegroundImageView) v.findViewById(R.id.image);
imageView = (ThumbnailView) v.findViewById(R.id.image);
}
}

public ImageMediaAdapter(Context context, MasterSecret masterSecret, Cursor c) {
super(context, c);
this.masterSecret = masterSecret;
this.gridSize = context.getResources().getDimensionPixelSize(R.dimen.thumbnail_max_size);
}

@Override
Expand All @@ -71,34 +65,18 @@ public ViewHolder onCreateViewHolder(final ViewGroup viewGroup, final int i) {

@Override
public void onBindViewHolder(final ViewHolder viewHolder, final Cursor cursor) {
final ForegroundImageView imageView = viewHolder.imageView;
final ImageRecord imageRecord = ImageRecord.from(cursor);
final ThumbnailView imageView = viewHolder.imageView;
final ImageRecord imageRecord = ImageRecord.from(cursor);

PduPart part = new PduPart();

part.setDataUri(imageRecord.getUri());
part.setContentType(imageRecord.getContentType().getBytes());
part.setId(imageRecord.getPartId());

imageView.setVisibility(View.INVISIBLE);
Slide slide = MediaUtil.getSlideForPart(getContext(), masterSecret, part, imageRecord.getContentType());
if (slide != null) {
slide.getThumbnail(getContext()).addListener(new FutureTaskListener<Pair<Drawable, Boolean>>() {
@Override
public void onSuccess(final Pair<Drawable, Boolean> result) {
imageView.post(new Runnable() {
@Override
public void run() {
imageView.show(result.first, false);
}
});
}

@Override
public void onFailure(Throwable error) {
Log.w(TAG, error);
}
});
imageView.setImageResource(slide, masterSecret);
}

imageView.setOnClickListener(new OnMediaClickListener(imageRecord));
Expand Down
Loading

0 comments on commit f42d100

Please sign in to comment.