mirror of
https://github.com/oxen-io/session-android.git
synced 2025-01-11 16:33:39 +00:00
ditch RoundedImageView, make animated gifs work
// FREEBIE
This commit is contained in:
parent
a66dd8be82
commit
f13ad54ba1
@ -44,7 +44,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.6.0'
|
||||
compile 'com.github.bumptech.glide:glide:3.6.1'
|
||||
compile 'com.makeramen:roundedimageview:2.1.0'
|
||||
compile 'com.pnikosis:materialish-progress:1.5'
|
||||
compile 'de.greenrobot:eventbus:2.4.0'
|
||||
@ -108,7 +108,7 @@ dependencyVerification {
|
||||
'org.w3c:smil:085dc40f2bb249651578bfa07499fd08b16ad0886dbe2c4078586a408da62f9b',
|
||||
'org.apache.httpcomponents:httpclient-android:6f56466a9bd0d42934b90bfbfe9977a8b654c058bf44a12bdc2877c4e1f033f1',
|
||||
'com.github.chrisbanes.photoview:library:8b5344e206f125e7ba9d684008f36c4992d03853c57e5814125f88496126e3cc',
|
||||
'com.github.bumptech.glide:glide:adf657e6bddccb168a29e18ab0954043af46a9b5c736d8c3193c9783fd83d69e',
|
||||
'com.github.bumptech.glide:glide:4718ac4c57ebabe56e673dc3265950b9dbf940d1c43c0adc363e8b95c0abdf75',
|
||||
'com.makeramen:roundedimageview:1f5a1865796b308c6cdd114acc6e78408b110f0a62fc63553278fbeacd489cd1',
|
||||
'com.pnikosis:materialish-progress:d71d80e00717a096784482aee21001a9d299fec3833e4ebd87739ed36cf77c54',
|
||||
'de.greenrobot:eventbus:61d743a748156a372024d083de763b9e91ac2dcb3f6a1cbc74995c7ddab6e968',
|
||||
|
@ -55,8 +55,8 @@
|
||||
android:id="@+id/attachment_thumbnail"
|
||||
android:layout_width="230dp"
|
||||
android:layout_height="150dp"
|
||||
app:riv_corner_radius="3dp"
|
||||
android:contentDescription="@string/conversation_activity__attachment_thumbnail"/>
|
||||
android:contentDescription="@string/conversation_activity__attachment_thumbnail"
|
||||
app:backgroundColorHint="?conversation_background" />
|
||||
</FrameLayout>
|
||||
|
||||
<ImageView android:id="@+id/remove_image_button"
|
||||
|
@ -54,8 +54,6 @@
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@string/conversation_item__mms_image_description"
|
||||
android:visibility="gone"
|
||||
app:riv_corner_radius="@dimen/message_bubble_corner_radius"
|
||||
app:riv_border_width="0dp"
|
||||
tools:src="@drawable/ic_video_light"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
@ -65,8 +65,6 @@
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@string/conversation_item__mms_image_description"
|
||||
android:visibility="gone"
|
||||
app:riv_corner_radius="@dimen/message_bubble_corner_radius"
|
||||
app:riv_border_width="0dp"
|
||||
tools:src="@drawable/ic_video_light"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
@ -25,7 +25,6 @@
|
||||
android:layout_width="70dp"
|
||||
android:layout_height="70dp"
|
||||
position="bottom_right"
|
||||
app:riv_oval="true"
|
||||
android:layout_marginRight="10dp"
|
||||
android:src="@drawable/ic_group_photo"
|
||||
android:contentDescription="@string/GroupCreateActivity_avatar_content_description" />
|
||||
|
@ -2,15 +2,13 @@
|
||||
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<com.makeramen.roundedimageview.RoundedImageView
|
||||
android:id="@+id/thumbnail_image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:scaleType="fitCenter"
|
||||
android:adjustViewBounds="true"
|
||||
android:contentDescription="@string/conversation_item__mms_image_description"
|
||||
android:layout_margin="@dimen/media_bubble_border_width"
|
||||
app:riv_corner_radius="@dimen/message_bubble_corner_radius" />
|
||||
<ImageView android:id="@+id/thumbnail_image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="fitCenter"
|
||||
android:contentDescription="@string/conversation_item__mms_image_description"
|
||||
android:layout_margin="@dimen/media_bubble_border_width" />
|
||||
|
||||
<com.pnikosis.materialishprogress.ProgressWheel
|
||||
android:id="@+id/progress_wheel"
|
||||
|
@ -130,4 +130,7 @@
|
||||
<attr name="inverted" format="boolean"/>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="ThumbnailView">
|
||||
<attr name="backgroundColorHint" format="color" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
|
@ -218,11 +218,12 @@ public class ConversationItem extends LinearLayout implements Recipient.Recipien
|
||||
private void setBubbleState(MessageRecord messageRecord, Recipient recipient) {
|
||||
if (messageRecord.isOutgoing()) {
|
||||
bodyBubble.getBackground().setColorFilter(defaultBubbleColor, PorterDuff.Mode.MULTIPLY);
|
||||
mediaThumbnail.setBackgroundColorHint(defaultBubbleColor);
|
||||
} else {
|
||||
bodyBubble.getBackground().setColorFilter(recipient.getColor().toConversationColor(context),
|
||||
PorterDuff.Mode.MULTIPLY);
|
||||
int color = recipient.getColor().toConversationColor(context);
|
||||
bodyBubble.getBackground().setColorFilter(color, PorterDuff.Mode.MULTIPLY);
|
||||
mediaThumbnail.setBackgroundColorHint(color);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void setSelectionBackgroundDrawables(MessageRecord messageRecord) {
|
||||
|
@ -7,11 +7,9 @@ import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.makeramen.roundedimageview.RoundedImageView;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
|
||||
public class ImageDivet extends RoundedImageView {
|
||||
public class ImageDivet extends ImageView {
|
||||
private static final float CORNER_OFFSET = 12F;
|
||||
private static final String[] POSITIONS = new String[] {"bottom_right"};
|
||||
|
||||
|
@ -3,7 +3,8 @@ package org.thoughtcrime.securesms.components;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.support.annotation.NonNull;
|
||||
@ -15,13 +16,16 @@ import android.view.animation.AlphaAnimation;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.Animation.AnimationListener;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.bumptech.glide.DrawableTypeRequest;
|
||||
import com.bumptech.glide.GenericRequestBuilder;
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.bitmap.CenterCrop;
|
||||
import com.bumptech.glide.load.resource.bitmap.GlideBitmapDrawable;
|
||||
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
|
||||
import com.bumptech.glide.request.RequestListener;
|
||||
import com.bumptech.glide.request.target.Target;
|
||||
import com.makeramen.roundedimageview.RoundedImageView;
|
||||
import com.pnikosis.materialishprogress.ProgressWheel;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
@ -32,6 +36,7 @@ import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.util.FutureTaskListener;
|
||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
import org.thoughtcrime.securesms.mms.RoundedCorners;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
@ -40,9 +45,11 @@ import ws.com.google.android.mms.pdu.PduPart;
|
||||
public class ThumbnailView extends FrameLayout {
|
||||
private static final String TAG = ThumbnailView.class.getSimpleName();
|
||||
|
||||
private boolean showProgress = true;
|
||||
private RoundedImageView image;
|
||||
private ProgressWheel progress;
|
||||
private boolean showProgress = true;
|
||||
private ImageView image;
|
||||
private ProgressWheel progress;
|
||||
private int backgroundColorHint;
|
||||
private int radius;
|
||||
|
||||
private ListenableFutureTask<SlideDeck> slideDeckFuture = null;
|
||||
private SlideDeckListener slideDeckListener = null;
|
||||
@ -61,8 +68,15 @@ public class ThumbnailView extends FrameLayout {
|
||||
public ThumbnailView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
inflate(context, R.layout.thumbnail_view, this);
|
||||
image = (RoundedImageView) findViewById(R.id.thumbnail_image);
|
||||
progress = (ProgressWheel) findViewById(R.id.progress_wheel);
|
||||
radius = getResources().getDimensionPixelSize(R.dimen.message_bubble_corner_radius);
|
||||
image = (ImageView) findViewById(R.id.thumbnail_image);
|
||||
progress = (ProgressWheel) findViewById(R.id.progress_wheel);
|
||||
|
||||
if (attrs != null) {
|
||||
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ThumbnailView, 0, 0);
|
||||
backgroundColorHint = typedArray.getColor(0, Color.BLACK);
|
||||
typedArray.recycle();
|
||||
}
|
||||
}
|
||||
|
||||
@Override protected void onAttachedToWindow() {
|
||||
@ -80,13 +94,17 @@ public class ThumbnailView extends FrameLayout {
|
||||
if (this.slide != null && event.partId.equals(this.slide.getPart().getPartId())) {
|
||||
Util.runOnMain(new Runnable() {
|
||||
@Override public void run() {
|
||||
progress.setInstantProgress(((float) event.progress) / event.total);
|
||||
progress.setInstantProgress(((float)event.progress) / event.total);
|
||||
if (event.progress >= event.total) animateOutProgress();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void setBackgroundColorHint(int color) {
|
||||
this.backgroundColorHint = color;
|
||||
}
|
||||
|
||||
public void setImageResource(@Nullable MasterSecret masterSecret,
|
||||
long id, long timestamp,
|
||||
@NonNull ListenableFutureTask<SlideDeck> slideDeckFuture)
|
||||
@ -155,6 +173,7 @@ public class ThumbnailView extends FrameLayout {
|
||||
private GenericRequestBuilder buildGlideRequest(@NonNull Slide slide,
|
||||
@Nullable MasterSecret masterSecret)
|
||||
{
|
||||
Log.w(TAG, "slide type " + slide.getContentType());
|
||||
final GenericRequestBuilder builder;
|
||||
if (slide.getThumbnailUri() != null) {
|
||||
builder = buildThumbnailGlideRequest(slide, masterSecret);
|
||||
@ -182,8 +201,7 @@ public class ThumbnailView extends FrameLayout {
|
||||
if (masterSecret == null) request = Glide.with(getContext()).load(slide.getThumbnailUri());
|
||||
else request = Glide.with(getContext()).load(new DecryptableUri(masterSecret, slide.getThumbnailUri()));
|
||||
|
||||
return request.asBitmap()
|
||||
.fitCenter()
|
||||
return request.transform(new RoundedCorners(getContext(), false, radius, backgroundColorHint))
|
||||
.listener(new PduThumbnailSetListener(slide.getPart()));
|
||||
}
|
||||
|
||||
@ -192,9 +210,9 @@ public class ThumbnailView extends FrameLayout {
|
||||
throw new IllegalStateException("null MasterSecret when loading non-draft thumbnail");
|
||||
}
|
||||
|
||||
return Glide.with(getContext()).load(new DecryptableUri(masterSecret, slide.getThumbnailUri()))
|
||||
.asBitmap()
|
||||
.centerCrop();
|
||||
return Glide.with(getContext()).load(new DecryptableUri(masterSecret, slide.getThumbnailUri()))
|
||||
.crossFade()
|
||||
.transform(new RoundedCorners(getContext(), true, radius, backgroundColorHint));
|
||||
}
|
||||
|
||||
private GenericRequestBuilder buildPlaceholderGlideRequest(Slide slide) {
|
||||
@ -282,7 +300,7 @@ public class ThumbnailView extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
private static class PduThumbnailSetListener implements RequestListener<Object, Bitmap> {
|
||||
private static class PduThumbnailSetListener implements RequestListener<Object, GlideDrawable> {
|
||||
private PduPart part;
|
||||
|
||||
public PduThumbnailSetListener(@NonNull PduPart part) {
|
||||
@ -290,15 +308,17 @@ public class ThumbnailView extends FrameLayout {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onException(Exception e, Object model, Target<Bitmap> target, boolean isFirstResource) {
|
||||
public boolean onException(Exception e, Object model, Target<GlideDrawable> target, boolean isFirstResource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) {
|
||||
part.setThumbnail(resource);
|
||||
public boolean onResourceReady(GlideDrawable resource, Object model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
|
||||
if (resource instanceof GlideBitmapDrawable) {
|
||||
Log.w(TAG, "onResourceReady() for a Bitmap. Saving.");
|
||||
part.setThumbnail(((GlideBitmapDrawable)resource).getBitmap());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,9 @@ import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.bumptech.glide.Glide;
|
||||
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
|
||||
import com.bumptech.glide.request.target.BitmapImageViewTarget;
|
||||
import com.bumptech.glide.request.target.GlideDrawableImageViewTarget;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
|
||||
@ -32,11 +34,10 @@ public class ZoomingImageView extends ImageView {
|
||||
public void setImageUri(MasterSecret masterSecret, Uri uri) {
|
||||
Glide.with(getContext())
|
||||
.load(new DecryptableUri(masterSecret, uri))
|
||||
.asBitmap()
|
||||
.dontTransform()
|
||||
.dontAnimate()
|
||||
.into(new BitmapImageViewTarget(this) {
|
||||
@Override protected void setResource(Bitmap resource) {
|
||||
.into(new GlideDrawableImageViewTarget(this) {
|
||||
@Override protected void setResource(GlideDrawable resource) {
|
||||
super.setResource(resource);
|
||||
attacher.update();
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.providers.CaptureProvider;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -68,22 +69,14 @@ public class AttachmentManager {
|
||||
AlphaAnimation animation = new AlphaAnimation(1.0f, 0.0f);
|
||||
animation.setDuration(200);
|
||||
animation.setAnimationListener(new Animation.AnimationListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animation animation) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animation animation) {
|
||||
@Override public void onAnimationStart(Animation animation) {}
|
||||
@Override public void onAnimationRepeat(Animation animation) {}
|
||||
@Override public void onAnimationEnd(Animation animation) {
|
||||
slideDeck.clear();
|
||||
attachmentView.setVisibility(View.GONE);
|
||||
attachmentListener.onAttachmentChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationRepeat(Animation animation) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
attachmentView.startAnimation(animation);
|
||||
@ -95,7 +88,11 @@ public class AttachmentManager {
|
||||
}
|
||||
|
||||
public void setImage(MasterSecret masterSecret, Uri image) throws IOException, BitmapDecodingException {
|
||||
setMedia(new ImageSlide(context, masterSecret, image), masterSecret);
|
||||
if (MediaUtil.getMimeType(context, image).startsWith("image/gif")) {
|
||||
setMedia(new GifSlide(context, masterSecret, image), masterSecret);
|
||||
} else {
|
||||
setMedia(new ImageSlide(context, masterSecret, image), masterSecret);
|
||||
}
|
||||
}
|
||||
|
||||
public void setVideo(Uri video) throws IOException, MediaTooLargeException {
|
||||
@ -148,7 +145,6 @@ public class AttachmentManager {
|
||||
return captureUri;
|
||||
}
|
||||
|
||||
|
||||
public void setCaptureUri(Uri captureUri) {
|
||||
this.captureUri = captureUri;
|
||||
}
|
||||
|
27
src/org/thoughtcrime/securesms/mms/GifSlide.java
Normal file
27
src/org/thoughtcrime/securesms/mms/GifSlide.java
Normal file
@ -0,0 +1,27 @@
|
||||
package org.thoughtcrime.securesms.mms;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import ws.com.google.android.mms.pdu.PduPart;
|
||||
|
||||
public class GifSlide extends ImageSlide {
|
||||
public GifSlide(Context context, MasterSecret masterSecret, PduPart part) {
|
||||
super(context, masterSecret, part);
|
||||
}
|
||||
|
||||
public GifSlide(Context context, MasterSecret masterSecret, Uri uri)
|
||||
throws IOException, BitmapDecodingException
|
||||
{
|
||||
super(context, masterSecret, uri);
|
||||
}
|
||||
|
||||
@Override public Uri getThumbnailUri() {
|
||||
return getPart().getDataUri();
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ import android.support.annotation.DrawableRes;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@ -38,7 +39,7 @@ public class ImageSlide extends Slide {
|
||||
}
|
||||
|
||||
public ImageSlide(Context context, MasterSecret masterSecret, Uri uri) throws IOException, BitmapDecodingException {
|
||||
super(context, masterSecret, constructPartFromUri(uri));
|
||||
super(context, masterSecret, constructPartFromUri(context, uri));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -62,13 +63,15 @@ public class ImageSlide extends Slide {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static PduPart constructPartFromUri(Uri uri)
|
||||
private static PduPart constructPartFromUri(Context context, Uri uri)
|
||||
throws IOException, BitmapDecodingException
|
||||
{
|
||||
PduPart part = new PduPart();
|
||||
|
||||
final String mimeType = MediaUtil.getMimeType(context, uri);
|
||||
|
||||
part.setDataUri(uri);
|
||||
part.setContentType(ContentType.IMAGE_JPEG.getBytes());
|
||||
part.setContentType((mimeType != null ? mimeType : ContentType.IMAGE_JPEG).getBytes());
|
||||
part.setContentId((System.currentTimeMillis()+"").getBytes());
|
||||
part.setName(("Image" + System.currentTimeMillis()).getBytes());
|
||||
|
||||
|
@ -25,15 +25,18 @@ public abstract class MediaConstraints {
|
||||
public abstract int getImageMaxHeight(Context context);
|
||||
public abstract int getImageMaxSize();
|
||||
|
||||
public abstract int getGifMaxSize();
|
||||
|
||||
public abstract int getVideoMaxSize();
|
||||
|
||||
public abstract int getAudioMaxSize();
|
||||
|
||||
public boolean isSatisfied(Context context, MasterSecret masterSecret, PduPart part) {
|
||||
try {
|
||||
return (MediaUtil.isImage(part) && part.getDataSize() <= getImageMaxSize() && isWithinBounds(context, masterSecret, part.getDataUri())) ||
|
||||
(MediaUtil.isAudio(part) && part.getDataSize() <= getAudioMaxSize()) ||
|
||||
(MediaUtil.isVideo(part) && part.getDataSize() <= getVideoMaxSize()) ||
|
||||
return (MediaUtil.isGif(part) && part.getDataSize() <= getGifMaxSize()) ||
|
||||
(MediaUtil.isImage(part) && part.getDataSize() <= getImageMaxSize() && isWithinBounds(context, masterSecret, part.getDataUri())) ||
|
||||
(MediaUtil.isAudio(part) && part.getDataSize() <= getAudioMaxSize()) ||
|
||||
(MediaUtil.isVideo(part) && part.getDataSize() <= getVideoMaxSize()) ||
|
||||
(!MediaUtil.isImage(part) && !MediaUtil.isAudio(part) && !MediaUtil.isVideo(part));
|
||||
} catch (IOException ioe) {
|
||||
Log.w(TAG, "Failed to determine if media's constraints are satisfied.", ioe);
|
||||
@ -49,7 +52,7 @@ public abstract class MediaConstraints {
|
||||
}
|
||||
|
||||
public boolean canResize(PduPart part) {
|
||||
return part != null && MediaUtil.isImage(part);
|
||||
return part != null && MediaUtil.isImage(part) && !MediaUtil.isGif(part);
|
||||
}
|
||||
|
||||
public byte[] getResizedMedia(Context context, MasterSecret masterSecret, PduPart part)
|
||||
|
@ -24,6 +24,11 @@ public class MmsMediaConstraints extends MediaConstraints {
|
||||
return MAX_MESSAGE_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGifMaxSize() {
|
||||
return MAX_MESSAGE_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVideoMaxSize() {
|
||||
return MAX_MESSAGE_SIZE;
|
||||
|
@ -25,6 +25,11 @@ public class PushMediaConstraints extends MediaConstraints {
|
||||
return 420 * KB;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGifMaxSize() {
|
||||
return 1 * MB;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVideoMaxSize() {
|
||||
return MmsMediaConstraints.MAX_MESSAGE_SIZE;
|
||||
|
88
src/org/thoughtcrime/securesms/mms/RoundedCorners.java
Normal file
88
src/org/thoughtcrime/securesms/mms/RoundedCorners.java
Normal file
@ -0,0 +1,88 @@
|
||||
package org.thoughtcrime.securesms.mms;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Bitmap.Config;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader.TileMode;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool;
|
||||
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation;
|
||||
import com.bumptech.glide.load.resource.bitmap.TransformationUtils;
|
||||
|
||||
public class RoundedCorners extends BitmapTransformation {
|
||||
private final boolean crop;
|
||||
private final int radius;
|
||||
private final int colorHint;
|
||||
|
||||
public RoundedCorners(@NonNull Context context, boolean crop, int radius, int colorHint) {
|
||||
super(context);
|
||||
this.crop = crop;
|
||||
this.radius = radius;
|
||||
this.colorHint = colorHint;
|
||||
}
|
||||
|
||||
@Override protected Bitmap transform(BitmapPool pool, Bitmap toTransform, int outWidth,
|
||||
int outHeight)
|
||||
{
|
||||
final Bitmap toRound = crop ? centerCrop(pool, toTransform, outWidth, outHeight)
|
||||
: fitCenter(pool, toTransform, outWidth, outHeight);
|
||||
return round(pool, toRound);
|
||||
}
|
||||
|
||||
private Bitmap centerCrop(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
|
||||
final Bitmap toReuse = pool.get(outWidth, outHeight, getSafeConfig(toTransform));
|
||||
final Bitmap transformed = TransformationUtils.centerCrop(toReuse, toTransform, outWidth, outHeight);
|
||||
if (toReuse != null && toReuse != transformed && !pool.put(toReuse)) {
|
||||
toReuse.recycle();
|
||||
}
|
||||
return transformed;
|
||||
}
|
||||
|
||||
private Bitmap fitCenter(BitmapPool pool, Bitmap toTransform, int outWidth, int outHeight) {
|
||||
return TransformationUtils.fitCenter(toTransform, pool, outWidth, outHeight);
|
||||
}
|
||||
|
||||
private Bitmap round(@NonNull BitmapPool pool, @Nullable Bitmap toRound) {
|
||||
if (toRound == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Bitmap result;
|
||||
final Bitmap toReuse = pool.get(toRound.getWidth(), toRound.getHeight(), getSafeConfig(toRound));
|
||||
if (toReuse != null) {
|
||||
result = toReuse;
|
||||
} else {
|
||||
result = Bitmap.createBitmap(toRound.getWidth(), toRound.getHeight(), getSafeConfig(toRound));
|
||||
}
|
||||
|
||||
final Canvas canvas = new Canvas(result);
|
||||
final Paint cornerPaint = new Paint();
|
||||
final Paint shaderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
|
||||
|
||||
shaderPaint.setShader(new BitmapShader(toRound, TileMode.CLAMP, TileMode.CLAMP));
|
||||
cornerPaint.setColor(colorHint);
|
||||
if (Config.RGB_565.equals(result.getConfig())) {
|
||||
canvas.drawRect(0, 0, radius, radius, cornerPaint);
|
||||
canvas.drawRect(0, toRound.getHeight() - radius, radius, toRound.getHeight(), cornerPaint);
|
||||
canvas.drawRect(toRound.getWidth() - radius, 0, toRound.getWidth(), radius, cornerPaint);
|
||||
canvas.drawRect(toRound.getWidth() - radius, toRound.getHeight() - radius, toRound.getWidth(), toRound.getHeight(), cornerPaint);
|
||||
}
|
||||
canvas.drawRoundRect(new RectF(0, 0, toRound.getWidth(), toRound.getHeight()), radius, radius, shaderPaint);
|
||||
// Log.w("RoundedCorners", "in was " + toRound.getWidth() + "x" + toRound.getHeight() + ", out to " + result.getWidth() + "x" + result.getHeight());
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Bitmap.Config getSafeConfig(Bitmap bitmap) {
|
||||
return bitmap.getConfig() != null ? bitmap.getConfig() : Bitmap.Config.ARGB_8888;
|
||||
}
|
||||
|
||||
@Override public String getId() {
|
||||
return RoundedCorners.class.getCanonicalName();
|
||||
}
|
||||
}
|
@ -3,11 +3,14 @@ package org.thoughtcrime.securesms.util;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.mms.AudioSlide;
|
||||
import org.thoughtcrime.securesms.mms.GifSlide;
|
||||
import org.thoughtcrime.securesms.mms.ImageSlide;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
@ -59,7 +62,9 @@ public class MediaUtil {
|
||||
|
||||
public static Slide getSlideForPart(Context context, MasterSecret masterSecret, PduPart part, String contentType) {
|
||||
Slide slide = null;
|
||||
if (ContentType.isImageType(contentType)) {
|
||||
if (isGif(contentType)) {
|
||||
slide = new GifSlide(context, masterSecret, part);
|
||||
} else if (ContentType.isImageType(contentType)) {
|
||||
slide = new ImageSlide(context, masterSecret, part);
|
||||
} else if (ContentType.isVideoType(contentType)) {
|
||||
slide = new VideoSlide(context, masterSecret, part);
|
||||
@ -70,6 +75,23 @@ public class MediaUtil {
|
||||
return slide;
|
||||
}
|
||||
|
||||
public static String getMimeType(Context context, Uri uri) {
|
||||
String type = context.getContentResolver().getType(uri);
|
||||
if (type == null) {
|
||||
final String extension = MimeTypeMap.getFileExtensionFromUrl(uri.toString());
|
||||
type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
private static boolean isGif(String contentType) {
|
||||
return !TextUtils.isEmpty(contentType) && contentType.trim().equals("image/gif");
|
||||
}
|
||||
|
||||
public static boolean isGif(PduPart part) {
|
||||
return isGif(Util.toIsoString(part.getContentType()));
|
||||
}
|
||||
|
||||
public static boolean isImage(PduPart part) {
|
||||
return ContentType.isImageType(Util.toIsoString(part.getContentType()));
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user