Commit 3ed31364 authored by Tiago Cunha's avatar Tiago Cunha

Using Fresco to render images - widgets module

parent faca14aa
...@@ -7,9 +7,11 @@ import io.realm.Realm; ...@@ -7,9 +7,11 @@ import io.realm.Realm;
import io.realm.RealmConfiguration; import io.realm.RealmConfiguration;
import java.util.List; import java.util.List;
import chat.rocket.android.helper.OkHttpHelper;
import chat.rocket.android.realm_helper.RealmStore; import chat.rocket.android.realm_helper.RealmStore;
import chat.rocket.android.service.ConnectivityManager; import chat.rocket.android.service.ConnectivityManager;
import chat.rocket.android.service.ServerInfo; import chat.rocket.android.service.ServerInfo;
import chat.rocket.android.widget.RocketChatWidgets;
import chat.rocket.android.wrappers.InstabugWrapper; import chat.rocket.android.wrappers.InstabugWrapper;
/** /**
...@@ -37,5 +39,7 @@ public class RocketChatApplication extends MultiDexApplication { ...@@ -37,5 +39,7 @@ public class RocketChatApplication extends MultiDexApplication {
InstabugWrapper.build(this, getString(R.string.instabug_api_key)); InstabugWrapper.build(this, getString(R.string.instabug_api_key));
//TODO: add periodic trigger for RocketChatService.keepAlive(this) here! //TODO: add periodic trigger for RocketChatService.keepAlive(this) here!
RocketChatWidgets.initialize(this, OkHttpHelper.getClientForDownloadFile(this));
} }
} }
...@@ -21,6 +21,10 @@ public class RocketChatCache { ...@@ -21,6 +21,10 @@ public class RocketChatCache {
return context.getSharedPreferences("cache", Context.MODE_PRIVATE); return context.getSharedPreferences("cache", Context.MODE_PRIVATE);
} }
public static String getSelectedServerHostname(Context context) {
return get(context).getString(KEY_SELECTED_SERVER_HOSTNAME, null);
}
public static String getOrCreatePushId(Context context) { public static String getOrCreatePushId(Context context) {
SharedPreferences preferences = get(context); SharedPreferences preferences = get(context);
if (!preferences.contains(KEY_PUSH_ID)) { if (!preferences.contains(KEY_PUSH_ID)) {
......
package chat.rocket.android.api.rest;
import java.io.IOException;
import okhttp3.*;
import okhttp3.Response;
public class CookieInterceptor implements Interceptor {
private final CookieProvider cookieProvider;
public CookieInterceptor(CookieProvider cookieProvider) {
this.cookieProvider = cookieProvider;
}
@Override
public Response intercept(Chain chain) throws IOException {
if (chain.request().url().host().equals(cookieProvider.getHostname())) {
Request newRequest = chain.request().newBuilder()
.header("Cookie", cookieProvider.getCookie())
.build();
return chain.proceed(newRequest);
}
return chain.proceed(chain.request());
}
}
package chat.rocket.android.api.rest;
public interface CookieProvider {
String getHostname();
String getCookie();
}
package chat.rocket.android.api.rest;
import android.content.Context;
import chat.rocket.android.RocketChatCache;
import chat.rocket.android.model.ddp.User;
import chat.rocket.android.model.internal.Session;
import chat.rocket.android.realm_helper.RealmHelper;
import chat.rocket.android.realm_helper.RealmStore;
public class DefaultCookieProvider implements CookieProvider {
private final Context applicationContext;
public DefaultCookieProvider(Context context) {
applicationContext = context.getApplicationContext();
}
@Override
public String getHostname() {
return getHostnameFromCache();
}
@Override
public String getCookie() {
final String hostname = getHostnameFromCache();
if (hostname == null) {
return "";
}
final RealmHelper realmHelper = RealmStore.get(getHostnameFromCache());
if (realmHelper == null) {
return "";
}
final String userId = realmHelper.executeTransactionForRead(realm ->
User.queryCurrentUser(realm).findFirst()).getId();
final String token = realmHelper.executeTransactionForRead(realm ->
Session.queryDefaultSession(realm).findFirst()).getToken();
return "rc_uid=" + userId + ";rc_token=" + token;
}
private String getHostnameFromCache() {
return RocketChatCache.getSelectedServerHostname(applicationContext);
}
}
...@@ -6,17 +6,12 @@ import android.graphics.Canvas; ...@@ -6,17 +6,12 @@ import android.graphics.Canvas;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.widget.ImageView; import android.widget.ImageView;
import com.amulyakhare.textdrawable.TextDrawable; import com.amulyakhare.textdrawable.TextDrawable;
import com.squareup.picasso.Picasso; import com.squareup.picasso.Picasso;
import com.squareup.picasso.Target;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URLEncoder; import java.net.URLEncoder;
import bolts.Task;
import bolts.TaskCompletionSource;
import chat.rocket.android.log.RCLog; import chat.rocket.android.log.RCLog;
/** /**
...@@ -113,45 +108,4 @@ public class Avatar { ...@@ -113,45 +108,4 @@ public class Avatar {
.buildRoundRect(getInitialsForUser(username), getColorForUser(username), round); .buildRoundRect(getInitialsForUser(username), getColorForUser(username), round);
} }
public Task<Bitmap> getBitmap(Context context, int size) {
TaskCompletionSource<Bitmap> task = new TaskCompletionSource<>();
// Picasso can be triggered only on Main Thread.
if (Looper.myLooper() != Looper.getMainLooper()) {
new Handler(Looper.getMainLooper()).post(() ->
getBitmap(context, size)
.continueWith(_task -> {
if (_task.isFaulted()) {
task.setError(_task.getError());
} else {
task.setResult(_task.getResult());
}
return null;
}));
return task.getTask();
}
Picasso.with(context)
.load(getImageUrl())
.error(getTextDrawable(context))
.into(new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
if (bitmap != null) {
task.trySetResult(bitmap);
}
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
task.trySetResult(drawableToBitmap(errorDrawable, size));
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
return task.getTask();
}
} }
package chat.rocket.android.helper; package chat.rocket.android.helper;
import android.content.Context;
import com.facebook.stetho.okhttp3.StethoInterceptor; import com.facebook.stetho.okhttp3.StethoInterceptor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import chat.rocket.android.api.rest.CookieInterceptor;
import chat.rocket.android.api.rest.DefaultCookieProvider;
import okhttp3.OkHttpClient; import okhttp3.OkHttpClient;
/** /**
* Helper class for OkHttp client. * Helper class for OkHttp client.
*/ */
public class OkHttpHelper { public class OkHttpHelper {
private static OkHttpClient sHttpClientForUplFile; private static OkHttpClient httpClientForUploadFile;
private static OkHttpClient sHttpClientForWS; private static OkHttpClient httpClientForDownloadFile;
private static OkHttpClient httpClientForWS;
public static OkHttpClient getClientForDownloadFile(Context context) {
if (httpClientForDownloadFile == null) {
httpClientForDownloadFile = new OkHttpClient.Builder()
.addNetworkInterceptor(new StethoInterceptor())
.addInterceptor(new CookieInterceptor(new DefaultCookieProvider(context)))
.build();
}
return httpClientForDownloadFile;
}
public static OkHttpClient getClientForUploadFile() { public static OkHttpClient getClientForUploadFile() {
if (sHttpClientForUplFile == null) { if (httpClientForUploadFile == null) {
sHttpClientForUplFile = new OkHttpClient.Builder() httpClientForUploadFile = new OkHttpClient.Builder()
.addNetworkInterceptor(new StethoInterceptor()) .addNetworkInterceptor(new StethoInterceptor())
.build(); .build();
} }
return sHttpClientForUplFile; return httpClientForUploadFile;
} }
/** /**
* acquire OkHttpClient instance for WebSocket connection. * acquire OkHttpClient instance for WebSocket connection.
*/ */
public static OkHttpClient getClientForWebSocket() { public static OkHttpClient getClientForWebSocket() {
if (sHttpClientForWS == null) { if (httpClientForWS == null) {
sHttpClientForWS = new OkHttpClient.Builder().readTimeout(0, TimeUnit.NANOSECONDS) httpClientForWS = new OkHttpClient.Builder().readTimeout(0, TimeUnit.NANOSECONDS)
.addNetworkInterceptor(new StethoInterceptor()) .addNetworkInterceptor(new StethoInterceptor())
.build(); .build();
} }
return sHttpClientForWS; return httpClientForWS;
} }
} }
...@@ -128,7 +128,6 @@ public class MessageRenderer extends AbstractRenderer<Message> { ...@@ -128,7 +128,6 @@ public class MessageRenderer extends AbstractRenderer<Message> {
} else { } else {
attachmentsLayout.setVisibility(View.VISIBLE); attachmentsLayout.setVisibility(View.VISIBLE);
attachmentsLayout.setHostname(hostname); attachmentsLayout.setHostname(hostname);
attachmentsLayout.setCredential(userId, token);
attachmentsLayout.setAttachments(attachments); attachmentsLayout.setAttachments(attachments);
} }
......
...@@ -14,6 +14,13 @@ ext { ...@@ -14,6 +14,13 @@ ext {
supportV13 = "com.android.support:support-v13:$supportVersion" supportV13 = "com.android.support:support-v13:$supportVersion"
supportDesign = "com.android.support:design:$supportVersion" supportDesign = "com.android.support:design:$supportVersion"
frescoVersion = '1.0.1'
frescoBase = "com.facebook.fresco:fresco:$frescoVersion"
frescoAnimatedGif = "com.facebook.fresco:animated-gif:$frescoVersion"
frescoAnimatedWebp = "com.facebook.fresco:animated-webp:$frescoVersion"
frescoWebp = "com.facebook.fresco:webpsupport:$frescoVersion"
frescoImagePipelineOkHttp3 = "com.facebook.fresco:imagepipeline-okhttp3:$frescoVersion"
rxJava = 'io.reactivex:rxjava:1.2.3' rxJava = 'io.reactivex:rxjava:1.2.3'
boltsTask = 'com.parse.bolts:bolts-tasks:1.4.0' boltsTask = 'com.parse.bolts:bolts-tasks:1.4.0'
okhttp3 = 'com.squareup.okhttp3:okhttp:3.5.0' okhttp3 = 'com.squareup.okhttp3:okhttp:3.5.0'
......
...@@ -38,7 +38,12 @@ dependencies { ...@@ -38,7 +38,12 @@ dependencies {
compile 'org.nibor.autolink:autolink:0.5.0' compile 'org.nibor.autolink:autolink:0.5.0'
compile rootProject.ext.textDrawable compile rootProject.ext.textDrawable
compile rootProject.ext.okhttp3 compile rootProject.ext.okhttp3
compile rootProject.ext.picasso
compile rootProject.ext.picasso2Okhttp3Downloader
compile rootProject.ext.boltsTask compile rootProject.ext.boltsTask
compile rootProject.ext.frescoBase
compile rootProject.ext.frescoAnimatedGif
compile rootProject.ext.frescoAnimatedWebp
compile rootProject.ext.frescoWebp
compile rootProject.ext.frescoImagePipelineOkHttp3
compile 'com.caverock:androidsvg:1.2.1'
} }
package chat.rocket.android.widget;
import android.content.Context;
import com.facebook.drawee.backends.pipeline.DraweeConfig;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.imagepipeline.backends.okhttp3.OkHttpImagePipelineConfigFactory;
import com.facebook.imagepipeline.core.ImagePipelineConfig;
import chat.rocket.android.widget.fresco.ImageFormatConfigurator;
import okhttp3.OkHttpClient;
public class RocketChatWidgets {
public static void initialize(Context context, OkHttpClient okHttpClient) {
ImagePipelineConfig config = OkHttpImagePipelineConfigFactory
.newBuilder(context, okHttpClient)
.setDownsampleEnabled(true)
.setImageDecoderConfig(ImageFormatConfigurator.createImageDecoderConfig())
.build();
DraweeConfig.Builder draweeConfigBuilder = DraweeConfig.newBuilder();
ImageFormatConfigurator.addCustomDrawableFactories(draweeConfigBuilder);
Fresco.initialize(context, config, draweeConfigBuilder.build());
}
}
package chat.rocket.android.widget.fresco;
import android.support.annotation.Nullable;
import com.facebook.drawee.backends.pipeline.DraweeConfig;
import com.facebook.imagepipeline.decoder.ImageDecoderConfig;
/**
* Based on https://github.com/facebook/fresco/blob/master/samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/CustomImageFormatConfigurator.java
*/
public class ImageFormatConfigurator {
@Nullable
public static ImageDecoderConfig createImageDecoderConfig() {
ImageDecoderConfig.Builder config = ImageDecoderConfig.newBuilder();
config.addDecodingCapability(
SvgDecoderConfig.SVG_FORMAT,
new SvgDecoderConfig.SvgFormatChecker(),
new SvgDecoderConfig.SvgDecoder());
return config.build();
}
public static void addCustomDrawableFactories(DraweeConfig.Builder draweeConfigBuilder) {
draweeConfigBuilder.addCustomDrawableFactory(new SvgDecoderConfig.SvgDrawableFactory());
}
}
package chat.rocket.android.widget.fresco;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.PictureDrawable;
import android.support.annotation.Nullable;
import com.facebook.drawee.backends.pipeline.DrawableFactory;
import com.facebook.imageformat.ImageFormat;
import com.facebook.imageformat.ImageFormatCheckerUtils;
import com.facebook.imagepipeline.common.ImageDecodeOptions;
import com.facebook.imagepipeline.decoder.ImageDecoder;
import com.facebook.imagepipeline.image.CloseableImage;
import com.facebook.imagepipeline.image.EncodedImage;
import com.facebook.imagepipeline.image.QualityInfo;
import com.caverock.androidsvg.SVG;
import com.caverock.androidsvg.SVGParseException;
/**
* Based on https://github.com/facebook/fresco/blob/master/samples/showcase/src/main/java/com/facebook/fresco/samples/showcase/imageformat/svg/SvgDecoderExample.java
*/
public class SvgDecoderConfig {
public static final ImageFormat SVG_FORMAT = new ImageFormat("SVG_FORMAT", "svg");
// We do not include the closing ">" since there can be additional information
private static final String HEADER_TAG = "<svg";
public static class SvgFormatChecker implements ImageFormat.FormatChecker {
public static final byte[] HEADER = ImageFormatCheckerUtils.asciiBytes(HEADER_TAG);
@Override
public int getHeaderSize() {
return HEADER.length;
}
@Nullable
@Override
public ImageFormat determineFormat(byte[] headerBytes, int headerSize) {
if (headerSize < getHeaderSize()) {
return null;
}
if (ImageFormatCheckerUtils.startsWithPattern(headerBytes, HEADER)) {
return SVG_FORMAT;
}
return null;
}
}
public static class CloseableSvgImage extends CloseableImage {
private final SVG mSvg;
private boolean mClosed = false;
public CloseableSvgImage(SVG svg) {
mSvg = svg;
}
public SVG getSvg() {
return mSvg;
}
@Override
public int getSizeInBytes() {
return 0;
}
@Override
public void close() {
mClosed = true;
}
@Override
public boolean isClosed() {
return mClosed;
}
@Override
public int getWidth() {
return 0;
}
@Override
public int getHeight() {
return 0;
}
}
/**
* Decodes a SVG_FORMAT image
*/
public static class SvgDecoder implements ImageDecoder {
@Override
public CloseableImage decode(
EncodedImage encodedImage,
int length,
QualityInfo qualityInfo,
ImageDecodeOptions options) {
try {
SVG svg = SVG.getFromInputStream(encodedImage.getInputStream());
return new CloseableSvgImage(svg);
} catch (SVGParseException e) {
e.printStackTrace();
}
return null;
}
}
/**
* SVG drawable factory that creates {@link PictureDrawable}s for SVG images.
*/
public static class SvgDrawableFactory implements DrawableFactory {
@Override
public boolean supportsImageType(CloseableImage image) {
return image instanceof CloseableSvgImage;
}
@Nullable
@Override
public Drawable createDrawable(CloseableImage image) {
return new SvgPictureDrawable(((CloseableSvgImage) image).getSvg());
}
}
public static class SvgPictureDrawable extends PictureDrawable {
private final SVG mSvg;
public SvgPictureDrawable(SVG svg) {
super(null);
mSvg = svg;
}
@Override
protected void onBoundsChange(Rect bounds) {
super.onBoundsChange(bounds);
setPicture(mSvg.renderToPicture(bounds.width(), bounds.height()));
}
}
}
...@@ -11,6 +11,8 @@ public interface ImageFormat { ...@@ -11,6 +11,8 @@ public interface ImageFormat {
String JPG = "image/jpg"; String JPG = "image/jpg";
String JPEG = "image/jpeg"; String JPEG = "image/jpeg";
String WEBP = "image/webp"; String WEBP = "image/webp";
String GIF = "image/gif";
String SVG = "image/svg+xml";
List<String> SUPPORTED_LIST = Collections.unmodifiableList(new ArrayList<String>() { List<String> SUPPORTED_LIST = Collections.unmodifiableList(new ArrayList<String>() {
{ {
...@@ -18,6 +20,8 @@ public interface ImageFormat { ...@@ -18,6 +20,8 @@ public interface ImageFormat {
add(JPG); add(JPG);
add(JPEG); add(JPEG);
add(WEBP); add(WEBP);
add(GIF);
add(SVG);
} }
}); });
} }
...@@ -13,21 +13,17 @@ import android.util.AttributeSet; ...@@ -13,21 +13,17 @@ import android.util.AttributeSet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import com.jakewharton.picasso.OkHttp3Downloader; import com.facebook.drawee.backends.pipeline.Fresco;
import com.squareup.picasso.Picasso; import com.facebook.drawee.generic.GenericDraweeHierarchy;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
import java.io.IOException;
import chat.rocket.android.widget.R; import chat.rocket.android.widget.R;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
/** /**
*/ */
...@@ -36,10 +32,6 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout { ...@@ -36,10 +32,6 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
private String hostname; private String hostname;
private String attachmentsString; private String attachmentsString;
private String userId;
private String token;
private OkHttp3Downloader downloader;
public RocketChatMessageAttachmentsLayout(Context context) { public RocketChatMessageAttachmentsLayout(Context context) {
super(context); super(context);
initialize(context, null); initialize(context, null);
...@@ -71,37 +63,6 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout { ...@@ -71,37 +63,6 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
this.hostname = hostname; this.hostname = hostname;
} }
public void setCredential(String userId, String token) {
this.userId = userId;
this.token = token;
}
private OkHttp3Downloader getDownloader() {
if (downloader == null) {
Interceptor interceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
// uid/token is required to download attachment files.
// see: RocketChat:lib/fileUpload.coffee
if (chain.request().url().host().equals(hostname)) {
Request newRequest = chain.request().newBuilder()
.header("Cookie", "rc_uid=" + userId + ";rc_token=" + token)
.build();
return chain.proceed(newRequest);
}
return chain.proceed(chain.request());
}
};
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
downloader = new OkHttp3Downloader(okHttpClient);
}
return downloader;
}
public void setAttachments(String attachmentsString) { public void setAttachments(String attachmentsString) {
if (this.attachmentsString != null && this.attachmentsString.equals(attachmentsString)) { if (this.attachmentsString != null && this.attachmentsString.equals(attachmentsString)) {
return; return;
...@@ -168,7 +129,7 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout { ...@@ -168,7 +129,7 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
authorBox.setVisibility(VISIBLE); authorBox.setVisibility(VISIBLE);
loadImage(attachmentObj.getString("author_icon"), loadImage(attachmentObj.getString("author_icon"),
(ImageView) attachmentView.findViewById(R.id.author_icon)); (SimpleDraweeView) attachmentView.findViewById(R.id.author_icon));
final TextView authorName = (TextView) attachmentView.findViewById(R.id.author_name); final TextView authorName = (TextView) attachmentView.findViewById(R.id.author_name);
authorName.setText(attachmentObj.getString("author_name")); authorName.setText(attachmentObj.getString("author_name"));
...@@ -225,7 +186,7 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout { ...@@ -225,7 +186,7 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
refBox.setVisibility(VISIBLE); refBox.setVisibility(VISIBLE);
final ImageView thumbImage = (ImageView) refBox.findViewById(R.id.thumb); final SimpleDraweeView thumbImage = (SimpleDraweeView) refBox.findViewById(R.id.thumb);
final String thumbUrl = attachmentObj.optString("thumb_url"); final String thumbUrl = attachmentObj.optString("thumb_url");
if (TextUtils.isEmpty(thumbUrl)) { if (TextUtils.isEmpty(thumbUrl)) {
...@@ -248,7 +209,8 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout { ...@@ -248,7 +209,8 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
private void showImageAttachment(JSONObject attachmentObj, View attachmentView) private void showImageAttachment(JSONObject attachmentObj, View attachmentView)
throws JSONException { throws JSONException {
final ImageView attachedImage = (ImageView) attachmentView.findViewById(R.id.image); final SimpleDraweeView attachedImage =
(SimpleDraweeView) attachmentView.findViewById(R.id.image);
if (attachmentObj.isNull("image_url")) { if (attachmentObj.isNull("image_url")) {
attachedImage.setVisibility(GONE); attachedImage.setVisibility(GONE);
return; return;
...@@ -286,13 +248,17 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout { ...@@ -286,13 +248,17 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
return url.startsWith("/") ? "https://" + hostname + url : url; return url.startsWith("/") ? "https://" + hostname + url : url;
} }
private void loadImage(String url, ImageView imageView) { private void loadImage(String url, SimpleDraweeView draweeView) {
new Picasso.Builder(getContext()) final GenericDraweeHierarchy hierarchy = draweeView.getHierarchy();
.downloader(getDownloader()) hierarchy.setPlaceholderImage(
.build() VectorDrawableCompat.create(getResources(), R.drawable.image_dummy, null));
.load(absolutize(url)) hierarchy.setFailureImage(
.placeholder(VectorDrawableCompat.create(getResources(), R.drawable.image_dummy, null)) VectorDrawableCompat.create(getResources(), R.drawable.image_error, null));
.error(VectorDrawableCompat.create(getResources(), R.drawable.image_error, null))
.into(imageView); final DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(Uri.parse(absolutize(url)))
.setAutoPlayAnimations(true)
.build();
draweeView.setController(controller);
} }
} }
...@@ -5,14 +5,17 @@ import android.content.Context; ...@@ -5,14 +5,17 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.support.graphics.drawable.VectorDrawableCompat;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout; import android.widget.LinearLayout;
import android.widget.TextView; import android.widget.TextView;
import com.squareup.picasso.Picasso; import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.generic.GenericDraweeHierarchy;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;
import org.json.JSONArray; import org.json.JSONArray;
import org.json.JSONException; import org.json.JSONException;
import org.json.JSONObject; import org.json.JSONObject;
...@@ -77,11 +80,7 @@ public class RocketChatMessageUrlsLayout extends LinearLayout { ...@@ -77,11 +80,7 @@ public class RocketChatMessageUrlsLayout extends LinearLayout {
if (contentType.startsWith("image/") && ImageFormat.SUPPORTED_LIST.contains(contentType)) { if (contentType.startsWith("image/") && ImageFormat.SUPPORTED_LIST.contains(contentType)) {
View inlineImage = inflater.inflate(R.layout.message_inline_image, this, false); View inlineImage = inflater.inflate(R.layout.message_inline_image, this, false);
Picasso.with(getContext()) loadImage(url, (SimpleDraweeView) inlineImage.findViewById(R.id.message_inline_image));
.load(url)
.placeholder(R.drawable.image_dummy)
.error(R.drawable.image_error)
.into((ImageView) inlineImage.findViewById(R.id.message_inline_image));
addView(inlineImage); addView(inlineImage);
} }
...@@ -131,15 +130,11 @@ public class RocketChatMessageUrlsLayout extends LinearLayout { ...@@ -131,15 +130,11 @@ public class RocketChatMessageUrlsLayout extends LinearLayout {
((TextView) embedUrl.findViewById(R.id.title)).setText(title); ((TextView) embedUrl.findViewById(R.id.title)).setText(title);
((TextView) embedUrl.findViewById(R.id.description)).setText(description); ((TextView) embedUrl.findViewById(R.id.description)).setText(description);
ImageView image = (ImageView) embedUrl.findViewById(R.id.image); final SimpleDraweeView image = (SimpleDraweeView) embedUrl.findViewById(R.id.image);
if (TextUtils.isEmpty(imageURL)) { if (TextUtils.isEmpty(imageURL)) {
image.setVisibility(View.GONE); image.setVisibility(View.GONE);
} else { } else {
Picasso.with(getContext()) loadImage(imageURL, image);
.load(imageURL)
.placeholder(R.drawable.image_dummy)
.error(R.drawable.image_error)
.into(image);
image.setVisibility(View.VISIBLE); image.setVisibility(View.VISIBLE);
} }
...@@ -155,4 +150,18 @@ public class RocketChatMessageUrlsLayout extends LinearLayout { ...@@ -155,4 +150,18 @@ public class RocketChatMessageUrlsLayout extends LinearLayout {
addView(embedUrl); addView(embedUrl);
} }
} }
private void loadImage(String imageUrl, SimpleDraweeView draweeView) {
final GenericDraweeHierarchy hierarchy = draweeView.getHierarchy();
hierarchy.setPlaceholderImage(
VectorDrawableCompat.create(getResources(), R.drawable.image_dummy, null));
hierarchy.setFailureImage(
VectorDrawableCompat.create(getResources(), R.drawable.image_error, null));
final DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(Uri.parse(imageUrl))
.setAutoPlayAnimations(true)
.build();
draweeView.setController(controller);
}
} }
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
...@@ -29,11 +30,12 @@ ...@@ -29,11 +30,12 @@
android:orientation="horizontal" android:orientation="horizontal"
android:layout_marginBottom="8dp"> android:layout_marginBottom="8dp">
<ImageView <com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/author_icon" android:id="@+id/author_icon"
android:layout_width="16dp" android:layout_width="16dp"
android:layout_height="16dp" android:layout_height="16dp"
tools:src="@drawable/circle_black" /> tools:src="@drawable/circle_black"
fresco:actualImageScaleType="fitCenter" />
<android.support.v4.widget.Space <android.support.v4.widget.Space
android:layout_width="8dp" android:layout_width="8dp"
...@@ -75,11 +77,12 @@ ...@@ -75,11 +77,12 @@
android:orientation="horizontal" android:orientation="horizontal"
android:layout_marginBottom="8dp"> android:layout_marginBottom="8dp">
<ImageView <com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/thumb" android:id="@+id/thumb"
android:layout_width="32dp" android:layout_width="32dp"
android:layout_height="32dp" android:layout_height="32dp"
tools:src="@drawable/circle_black" /> tools:src="@drawable/circle_black"
fresco:actualImageScaleType="fitCenter" />
<android.support.v4.widget.Space <android.support.v4.widget.Space
android:layout_width="8dp" android:layout_width="8dp"
...@@ -93,14 +96,12 @@ ...@@ -93,14 +96,12 @@
</LinearLayout> </LinearLayout>
<ImageView <com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/image" android:id="@+id/image"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="200dp"
android:maxHeight="200dp"
android:layout_marginBottom="8dp" android:layout_marginBottom="8dp"
android:adjustViewBounds="true" fresco:actualImageScaleType="fitCenter" />
android:scaleType="fitStart" />
<!-- audio --> <!-- audio -->
<!-- video --> <!-- video -->
......
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
...@@ -14,15 +15,13 @@ ...@@ -14,15 +15,13 @@
android:background="@color/inline_attachment_quote_line" android:background="@color/inline_attachment_quote_line"
android:layout_marginRight="5dp" /> android:layout_marginRight="5dp" />
<ImageView <com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/image" android:id="@+id/image"
android:layout_width="wrap_content" android:layout_width="60dp"
android:layout_height="wrap_content" android:layout_height="60dp"
android:maxHeight="60dp"
android:layout_marginTop="2dp" android:layout_marginTop="2dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:adjustViewBounds="true" fresco:actualImageScaleType="fitCenter"
android:scaleType="fitStart"
android:layout_marginRight="8dp" /> android:layout_marginRight="8dp" />
<LinearLayout <LinearLayout
......
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@drawable/inline_attachment_background" android:background="@drawable/inline_attachment_background"
android:layout_margin="4dp" android:layout_margin="4dp"
android:padding="4dp"> android:padding="4dp">
<ImageView <com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/message_inline_image" android:id="@+id/message_inline_image"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="200dp"
android:maxHeight="200dp" fresco:actualImageScaleType="fitCenter" />
android:adjustViewBounds="true"
android:scaleType="fitStart" />
</FrameLayout> </FrameLayout>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment