Commit 9120eea0 authored by Tiago Cunha's avatar Tiago Cunha Committed by GitHub

Merge pull request #218 from RocketChat/feature/honor-auto-load-image-flag

Honor auto load image flag
parents 6cb7bfdf d43543c0
......@@ -22,6 +22,10 @@ public interface RoomContract {
void showMessages(List<Message> messages);
void showMessageSendFailure(Message message);
void autoloadImages();
void manualLoadImages();
}
interface Presenter extends BaseContract.Presenter<View> {
......
......@@ -78,14 +78,14 @@ public class RoomFragment extends AbstractChatRoomFragment
private LoadMoreScrollListener scrollListener;
private MessageFormManager messageFormManager;
private RecyclerViewAutoScrollManager autoScrollManager;
private AbstractNewMessageIndicatorManager newMessageIndicatorManager;
private Snackbar unreadIndicator;
protected AbstractNewMessageIndicatorManager newMessageIndicatorManager;
protected Snackbar unreadIndicator;
private boolean previousUnreadMessageExists;
private MessageListAdapter adapter;
private List<AbstractExtraActionItem> extraActionItems;
private RoomContract.Presenter presenter;
protected RoomContract.Presenter presenter;
public RoomFragment() {
}
......@@ -203,7 +203,7 @@ public class RoomFragment extends AbstractChatRoomFragment
}
}
private Snackbar getUnreadCountIndicatorView(int count) {
protected Snackbar getUnreadCountIndicatorView(int count) {
// TODO: replace with another custom View widget, not to hide message composer.
final String caption = getResources().getString(
R.string.fmt_dialog_view_latest_message_title, count);
......@@ -447,4 +447,14 @@ public class RoomFragment extends AbstractChatRoomFragment
(dialog, which) -> presenter.deleteMessage(message))
.show();
}
@Override
public void autoloadImages() {
adapter.setAutoloadImages(true);
}
@Override
public void manualLoadImages() {
adapter.setAutoloadImages(false);
}
}
......@@ -17,6 +17,7 @@ import chat.rocket.core.SyncState;
import chat.rocket.core.interactors.MessageInteractor;
import chat.rocket.core.models.Message;
import chat.rocket.core.models.Room;
import chat.rocket.core.models.Settings;
import chat.rocket.core.models.User;
import chat.rocket.core.repositories.RoomRepository;
import chat.rocket.core.repositories.UserRepository;
......@@ -53,6 +54,7 @@ public class RoomPresenter extends BasePresenter<RoomContract.View>
getRoomInfo();
getRoomHistoryStateInfo();
getMessages();
getUserPreferences();
}
@Override
......@@ -202,6 +204,27 @@ public class RoomPresenter extends BasePresenter<RoomContract.View>
addSubscription(subscription);
}
private void getUserPreferences() {
final Disposable subscription = userRepository.getCurrent()
.filter(Optional::isPresent)
.map(Optional::get)
.map(User::getSettings)
.filter(settings -> settings != null)
.map(Settings::getPreferences)
.distinctUntilChanged()
.subscribeOn(AndroidSchedulers.from(BackgroundLooper.get()))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(preferences -> {
if (preferences.isAutoImageLoad()) {
view.autoloadImages();
} else {
view.manualLoadImages();
}
});
addSubscription(subscription);
}
private Single<Pair<Room, User>> getRoomUserPair() {
return Single.zip(
getSingleRoom(),
......
......@@ -11,8 +11,8 @@ import chat.rocket.android.layouthelper.chatroom.ModelViewHolder;
/**
* ModelListAdapter with header and footer.
*/
public abstract class ExtModelListAdapter<T, VM,
VH extends ModelViewHolder<VM>> extends ModelListAdapter<T, VM, VH> {
public abstract class ExtModelListAdapter<T, VM, VH extends ModelViewHolder<VM>>
extends ModelListAdapter<T, VM, VH> {
protected static final int VIEW_TYPE_HEADER = -1;
protected static final int VIEW_TYPE_FOOTER = -2;
......
......@@ -38,8 +38,8 @@ public abstract class AbstractMessageViewHolder extends ModelViewHolder<PairedMe
/**
* bind the view model.
*/
public final void bind(PairedMessage pairedMessage) {
bindMessage(pairedMessage);
public final void bind(PairedMessage pairedMessage, boolean autoloadImages) {
bindMessage(pairedMessage, autoloadImages);
if (pairedMessage.target != null) {
int syncState = pairedMessage.target.getSyncState();
......@@ -53,7 +53,7 @@ public abstract class AbstractMessageViewHolder extends ModelViewHolder<PairedMe
renderNewDayAndSequential(pairedMessage);
}
protected abstract void bindMessage(PairedMessage pairedMessage);
protected abstract void bindMessage(PairedMessage pairedMessage, boolean autoloadImages);
private void renderNewDayAndSequential(PairedMessage pairedMessage) {
//see Rocket.Chat:packages/rocketchat-livechat/app/client/views/message.coffee
......
......@@ -23,6 +23,8 @@ public class MessageListAdapter
private static final int VIEW_TYPE_SYSTEM_MESSAGE = 2;
private final String hostname;
private boolean autoloadImages = false;
private boolean hasNext;
private boolean isLoaded;
......@@ -31,6 +33,10 @@ public class MessageListAdapter
this.hostname = hostname;
}
public void setAutoloadImages(boolean autoloadImages) {
this.autoloadImages = autoloadImages;
}
/**
* update Footer state considering hasNext and isLoaded.
*/
......@@ -88,7 +94,7 @@ public class MessageListAdapter
default:
return new AbstractMessageViewHolder(itemView, hostname) {
@Override
protected void bindMessage(PairedMessage pairedMessage) {
protected void bindMessage(PairedMessage pairedMessage, boolean autoloadImages) {
}
};
}
......@@ -109,6 +115,11 @@ public class MessageListAdapter
return extMessages;
}
@Override
protected boolean shouldAutoloadImages() {
return autoloadImages;
}
@Override
protected DiffUtil.Callback getDiffCallback(List<PairedMessage> oldData,
List<PairedMessage> newData) {
......
......@@ -28,8 +28,8 @@ public class MessageNormalViewHolder extends AbstractMessageViewHolder {
}
@Override
protected void bindMessage(PairedMessage pairedMessage) {
new MessageRenderer(itemView.getContext(), pairedMessage.target)
protected void bindMessage(PairedMessage pairedMessage, boolean autoloadImages) {
new MessageRenderer(itemView.getContext(), pairedMessage.target, autoloadImages)
.avatarInto(avatar, hostname)
.usernameInto(username, subUsername)
.timestampInto(timestamp)
......
......@@ -21,8 +21,8 @@ public class MessageSystemViewHolder extends AbstractMessageViewHolder {
}
@Override
protected void bindMessage(PairedMessage pairedMessage) {
new MessageRenderer(itemView.getContext(), pairedMessage.target)
protected void bindMessage(PairedMessage pairedMessage, boolean autoloadImages) {
new MessageRenderer(itemView.getContext(), pairedMessage.target, autoloadImages)
.avatarInto(avatar, hostname)
.usernameInto(username, subUsername)
.timestampInto(timestamp);
......
......@@ -32,6 +32,8 @@ public abstract class ModelListAdapter<T, VM, VH extends ModelViewHolder<VM>>
protected abstract List<VM> mapResultsToViewModel(List<T> results);
protected abstract boolean shouldAutoloadImages();
@Override
public int getItemViewType(int position) {
return getRealmModelViewType(getItem(position));
......@@ -53,7 +55,7 @@ public abstract class ModelListAdapter<T, VM, VH extends ModelViewHolder<VM>>
onItemClickListener.onItemClick(model2);
}
});
holder.bind(model);
holder.bind(model, shouldAutoloadImages());
}
@Override
......
......@@ -9,5 +9,5 @@ public abstract class ModelViewHolder<T> extends RecyclerView.ViewHolder {
super(itemView);
}
public abstract void bind(T model);
public abstract void bind(T model, boolean autoloadImages);
}
......@@ -26,10 +26,12 @@ import chat.rocket.core.models.WebContent;
public class MessageRenderer extends AbstractRenderer<Message> {
private final UserRenderer userRenderer;
private final boolean autoloadImages;
public MessageRenderer(Context context, Message message) {
public MessageRenderer(Context context, Message message, boolean autoloadImages) {
super(context, message);
userRenderer = new UserRenderer(context, message.getUser());
this.autoloadImages = autoloadImages;
}
/**
......@@ -111,7 +113,7 @@ public class MessageRenderer extends AbstractRenderer<Message> {
urlsLayout.setVisibility(View.GONE);
} else {
urlsLayout.setVisibility(View.VISIBLE);
urlsLayout.setUrls(webContents);
urlsLayout.setUrls(webContents, autoloadImages);
}
return this;
......@@ -132,7 +134,7 @@ public class MessageRenderer extends AbstractRenderer<Message> {
} else {
attachmentsLayout.setVisibility(View.VISIBLE);
attachmentsLayout.setHostname(hostname);
attachmentsLayout.setAttachments(attachments);
attachmentsLayout.setAttachments(attachments, autoloadImages);
}
return this;
......
package chat.rocket.android.widget.helper;
import android.net.Uri;
import android.support.graphics.drawable.VectorDrawableCompat;
import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.drawable.ProgressBarDrawable;
import com.facebook.drawee.generic.GenericDraweeHierarchy;
import com.facebook.drawee.interfaces.DraweeController;
import com.facebook.drawee.view.SimpleDraweeView;
import chat.rocket.android.widget.R;
public class FrescoHelper {
private FrescoHelper() {
}
public static void setupDraweeAndLoadImage(String imageUrl, SimpleDraweeView draweeView) {
setupDrawee(draweeView);
loadImage(imageUrl, draweeView);
}
public static void setupDrawee(SimpleDraweeView draweeView) {
final GenericDraweeHierarchy hierarchy = draweeView.getHierarchy();
hierarchy.setPlaceholderImage(
VectorDrawableCompat.create(draweeView.getResources(), R.drawable.image_dummy, null));
hierarchy.setFailureImage(
VectorDrawableCompat.create(draweeView.getResources(), R.drawable.image_error, null));
hierarchy.setProgressBarImage(new ProgressBarDrawable());
}
public static void loadImage(String imageUrl, SimpleDraweeView draweeView) {
final DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(Uri.parse(imageUrl))
.setAutoPlayAnimations(true)
.setTapToRetryEnabled(true)
.build();
draweeView.setController(controller);
}
}
......@@ -6,7 +6,6 @@ import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Build;
import android.support.graphics.drawable.VectorDrawableCompat;
import android.support.v4.widget.TextViewCompat;
import android.text.TextUtils;
import android.util.AttributeSet;
......@@ -15,13 +14,11 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
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 java.util.List;
import chat.rocket.android.widget.R;
import chat.rocket.android.widget.helper.FrescoHelper;
import chat.rocket.core.models.Attachment;
import chat.rocket.core.models.AttachmentAuthor;
import chat.rocket.core.models.AttachmentField;
......@@ -65,7 +62,7 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
this.hostname = hostname;
}
public void setAttachments(List<Attachment> attachments) {
public void setAttachments(List<Attachment> attachments, boolean autoloadImages) {
if (this.attachments != null && this.attachments.equals(attachments)) {
return;
}
......@@ -73,11 +70,11 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
removeAllViews();
for (int i = 0, size = attachments.size(); i < size; i++) {
appendAttachmentView(attachments.get(i));
appendAttachmentView(attachments.get(i), autoloadImages);
}
}
private void appendAttachmentView(Attachment attachment) {
private void appendAttachmentView(Attachment attachment, boolean autoloadImages) {
if (attachment == null) {
return;
}
......@@ -88,7 +85,7 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
showAuthorAttachment(attachment, attachmentView);
showTitleAttachment(attachment, attachmentView);
showReferenceAttachment(attachment, attachmentView);
showImageAttachment(attachment, attachmentView);
showImageAttachment(attachment, attachmentView, autoloadImages);
// audio
// video
showFieldsAttachment(attachment, attachmentView);
......@@ -122,7 +119,7 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
authorBox.setVisibility(VISIBLE);
loadImage(author.getIconUrl(),
FrescoHelper.setupDraweeAndLoadImage(absolutize(author.getIconUrl()),
(SimpleDraweeView) attachmentView.findViewById(R.id.author_icon));
final TextView authorName = (TextView) attachmentView.findViewById(R.id.author_name);
......@@ -186,7 +183,7 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
thumbImage.setVisibility(GONE);
} else {
thumbImage.setVisibility(VISIBLE);
loadImage(thumbUrl, thumbImage);
FrescoHelper.setupDraweeAndLoadImage(absolutize(thumbUrl), thumbImage);
}
final TextView refText = (TextView) refBox.findViewById(R.id.text);
......@@ -200,17 +197,21 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
}
}
private void showImageAttachment(Attachment attachment, View attachmentView) {
final SimpleDraweeView attachedImage =
(SimpleDraweeView) attachmentView.findViewById(R.id.image);
private void showImageAttachment(Attachment attachment, View attachmentView,
boolean autoloadImages) {
final View imageContainer = attachmentView.findViewById(R.id.image_container);
if (attachment.getImageUrl() == null) {
attachedImage.setVisibility(GONE);
imageContainer.setVisibility(GONE);
return;
}
attachedImage.setVisibility(VISIBLE);
imageContainer.setVisibility(VISIBLE);
final SimpleDraweeView attachedImage =
(SimpleDraweeView) attachmentView.findViewById(R.id.image);
final View load = attachmentView.findViewById(R.id.image_load);
loadImage(attachment.getImageUrl(), attachedImage);
loadImage(absolutize(attachment.getImageUrl()), attachedImage, load, autoloadImages);
}
private void showFieldsAttachment(Attachment attachment, View attachmentView) {
......@@ -240,17 +241,22 @@ public class RocketChatMessageAttachmentsLayout extends LinearLayout {
return url.startsWith("/") ? "https://" + hostname + url : url;
}
private void loadImage(String url, 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));
private void loadImage(final String url, final SimpleDraweeView drawee, final View load,
boolean autoloadImage) {
if (autoloadImage) {
load.setVisibility(GONE);
FrescoHelper.setupDraweeAndLoadImage(url, drawee);
return;
}
final DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(Uri.parse(absolutize(url)))
.setAutoPlayAnimations(true)
.build();
draweeView.setController(controller);
FrescoHelper.setupDrawee(drawee);
load.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
load.setVisibility(GONE);
load.setOnClickListener(null);
FrescoHelper.loadImage(url, drawee);
}
});
}
}
......@@ -5,21 +5,18 @@ import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.support.graphics.drawable.VectorDrawableCompat;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
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 java.util.List;
import java.util.Map;
import chat.rocket.android.widget.R;
import chat.rocket.android.widget.helper.FrescoHelper;
import chat.rocket.android.widget.helper.ImageFormat;
import chat.rocket.core.models.WebContent;
import chat.rocket.core.models.WebContentHeaders;
......@@ -59,7 +56,7 @@ public class RocketChatMessageUrlsLayout extends LinearLayout {
setOrientation(VERTICAL);
}
public void setUrls(List<WebContent> webContents) {
public void setUrls(List<WebContent> webContents, boolean autoloadImages) {
if (this.webContents != null && this.webContents.equals(webContents)) {
return;
}
......@@ -68,21 +65,14 @@ public class RocketChatMessageUrlsLayout extends LinearLayout {
removeAllViews();
for (int i = 0, size = webContents.size(); i < size; i++) {
appendUrlView(webContents.get(i));
appendUrlView(webContents.get(i), autoloadImages);
}
}
private void appendUrlView(WebContent webContent) {
private void appendUrlView(WebContent webContent, boolean autoloadImages) {
final String url = webContent.getUrl();
final WebContentHeaders webContentHeaders = webContent.getHeaders();
String contentType = webContentHeaders != null ? webContentHeaders.getContentType() : "";
if (contentType != null && contentType.startsWith("image/")
&& ImageFormat.SUPPORTED_LIST.contains(contentType)) {
View inlineImage = inflater.inflate(R.layout.message_inline_image, this, false);
loadImage(url, (SimpleDraweeView) inlineImage.findViewById(R.id.message_inline_image));
addView(inlineImage);
}
addMessageInlineImage(webContent, autoloadImages, url);
// see Rocket.Chat:packages/rocketchat-oembed/client/oembedUrlWidget.coffee
final Map<WebContentMeta.Type, WebContentMeta> webContentMetaMap = webContent.getMetaMap();
......@@ -90,19 +80,7 @@ public class RocketChatMessageUrlsLayout extends LinearLayout {
return;
}
String title = webContent.getMetaTitle();
String description = webContent.getMetaDescription();
if (description != null) {
if (description.startsWith("\"")) {
description = description.substring(1);
}
if (description.endsWith("\"")) {
description = description.substring(0, description.length() - 1);
}
}
String imageURL = webContent.getMetaImage();
final String imageURL = webContent.getMetaImage();
WebContentParsedUrl parsedUrl = webContent.getParsedUrl();
String host = parsedUrl != null ? parsedUrl.getHost() : null;
......@@ -110,14 +88,14 @@ public class RocketChatMessageUrlsLayout extends LinearLayout {
View embedUrl = inflater.inflate(R.layout.message_inline_embed_url, this, false);
((TextView) embedUrl.findViewById(R.id.hostname)).setText(host);
((TextView) embedUrl.findViewById(R.id.title)).setText(title);
((TextView) embedUrl.findViewById(R.id.description)).setText(description);
((TextView) embedUrl.findViewById(R.id.title)).setText(webContent.getMetaTitle());
((TextView) embedUrl.findViewById(R.id.description)).setText(removeQuote(webContent.getMetaDescription()));
final SimpleDraweeView image = (SimpleDraweeView) embedUrl.findViewById(R.id.image);
if (TextUtils.isEmpty(imageURL)) {
image.setVisibility(View.GONE);
} else {
loadImage(imageURL, image);
FrescoHelper.setupDraweeAndLoadImage(imageURL, image);
image.setVisibility(View.VISIBLE);
}
......@@ -133,17 +111,50 @@ public class RocketChatMessageUrlsLayout extends LinearLayout {
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));
private String removeQuote(String description) {
if (description != null) {
if (description.startsWith("\"")) {
description = description.substring(1);
}
if (description.endsWith("\"")) {
description = description.substring(0, description.length() - 1);
}
}
return description;
}
private void addMessageInlineImage(WebContent webContent, boolean autoloadImages, String url) {
final WebContentHeaders webContentHeaders = webContent.getHeaders();
String contentType = webContentHeaders != null ? webContentHeaders.getContentType() : "";
if (contentType != null && contentType.startsWith("image/")
&& ImageFormat.SUPPORTED_LIST.contains(contentType)) {
final View inlineImageView = inflater.inflate(R.layout.message_inline_image, this, false);
final SimpleDraweeView
inlineImage = (SimpleDraweeView) inlineImageView.findViewById(R.id.message_inline_image);
final View loadView = inlineImageView.findViewById(R.id.message_inline_image_load);
loadImage(url, inlineImage, loadView, autoloadImages);
addView(inlineImageView);
}
}
private void loadImage(final String url, final SimpleDraweeView drawee, final View load,
boolean autoloadImage) {
if (autoloadImage) {
load.setVisibility(GONE);
FrescoHelper.setupDraweeAndLoadImage(url, drawee);
return;
}
final DraweeController controller = Fresco.newDraweeControllerBuilder()
.setUri(Uri.parse(imageUrl))
.setAutoPlayAnimations(true)
.build();
draweeView.setController(controller);
FrescoHelper.setupDrawee(drawee);
load.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
load.setVisibility(GONE);
load.setOnClickListener(null);
FrescoHelper.loadImage(url, drawee);
}
});
}
}
......@@ -96,6 +96,11 @@
</LinearLayout>
<FrameLayout
android:id="@+id/image_container"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/image"
android:layout_width="match_parent"
......@@ -103,6 +108,16 @@
android:layout_marginBottom="8dp"
fresco:actualImageScaleType="fitStart" />
<TextView
android:id="@+id/image_load"
android:layout_width="match_parent"
android:layout_height="150dp"
android:gravity="center_horizontal|bottom"
android:paddingBottom="16dp"
android:text="@string/click_to_load" />
</FrameLayout>
<!-- audio -->
<!-- video -->
......
......@@ -11,4 +11,12 @@
android:layout_width="match_parent"
android:layout_height="150dp"
fresco:actualImageScaleType="fitStart" />
<TextView
android:id="@+id/message_inline_image_load"
android:layout_width="match_parent"
android:layout_height="150dp"
android:gravity="center_horizontal|bottom"
android:paddingBottom="16dp"
android:text="@string/click_to_load" />
</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="message_composer_message_hint">Message</string>
<string name="click_to_load">Click to load</string>
</resources>
\ No newline at end of file
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