Commit 3df27cb9 authored by Rafael Kellermann Streit's avatar Rafael Kellermann Streit Committed by GitHub

Merge pull request #346 from filipedelimabrito/rv-sync

RecyclerView wrong avatar solution
parents 2e9f5035 7fd1b6fc
......@@ -21,14 +21,6 @@ import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import com.fernandocejas.arrow.optional.Optional;
import com.jakewharton.rxbinding2.support.v4.widget.RxDrawerLayout;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import chat.rocket.android.BackgroundLooper;
import chat.rocket.android.R;
import chat.rocket.android.api.MethodCallHelper;
......@@ -78,10 +70,15 @@ import chat.rocket.persistence.realm.repositories.RealmSessionRepository;
import chat.rocket.persistence.realm.repositories.RealmSpotlightRoomRepository;
import chat.rocket.persistence.realm.repositories.RealmSpotlightUserRepository;
import chat.rocket.persistence.realm.repositories.RealmUserRepository;
import com.fernandocejas.arrow.optional.Optional;
import com.jakewharton.rxbinding2.support.v4.widget.RxDrawerLayout;
import io.reactivex.Single;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import permissions.dispatcher.NeedsPermission;
import permissions.dispatcher.RuntimePermissions;
......@@ -104,6 +101,7 @@ public class RoomFragment extends AbstractChatRoomFragment implements
private String roomId;
private LoadMoreScrollListener scrollListener;
private MessageFormManager messageFormManager;
private RecyclerView messageRecyclerView;
private RecyclerViewAutoScrollManager recyclerViewAutoScrollManager;
protected AbstractNewMessageIndicatorManager newMessageIndicatorManager;
protected Snackbar unreadIndicator;
......@@ -188,7 +186,7 @@ public class RoomFragment extends AbstractChatRoomFragment implements
@Override
protected void onSetupView() {
RecyclerView messageRecyclerView = (RecyclerView) rootView.findViewById(R.id.messageRecyclerView);
messageRecyclerView = rootView.findViewById(R.id.messageRecyclerView);
messageListAdapter = new MessageListAdapter(getContext());
messageRecyclerView.setAdapter(messageListAdapter);
......@@ -215,14 +213,12 @@ public class RoomFragment extends AbstractChatRoomFragment implements
}
};
messageRecyclerView.addOnScrollListener(scrollListener);
messageRecyclerView.addOnScrollListener(
new RecyclerViewScrolledToBottomListener(linearLayoutManager, 1, this::markAsReadIfNeeded));
messageRecyclerView.addOnScrollListener(new RecyclerViewScrolledToBottomListener(linearLayoutManager, 1, this::markAsReadIfNeeded));
newMessageIndicatorManager = new AbstractNewMessageIndicatorManager() {
@Override
protected void onShowIndicator(int count, boolean onlyAlreadyShown) {
if ((onlyAlreadyShown && unreadIndicator != null && unreadIndicator.isShown())
|| !onlyAlreadyShown) {
if ((onlyAlreadyShown && unreadIndicator != null && unreadIndicator.isShown()) || !onlyAlreadyShown) {
unreadIndicator = getUnreadCountIndicatorView(count);
unreadIndicator.show();
}
......@@ -249,10 +245,8 @@ public class RoomFragment extends AbstractChatRoomFragment implements
}
private void scrollToLatestMessage() {
RecyclerView listView = (RecyclerView) rootView.findViewById(R.id.messageRecyclerView);
if (listView != null) {
listView.scrollToPosition(0);
}
if (messageRecyclerView != null)
messageRecyclerView.scrollToPosition(0);
}
protected Snackbar getUnreadCountIndicatorView(int count) {
......@@ -266,13 +260,9 @@ public class RoomFragment extends AbstractChatRoomFragment implements
@Override
public void onDestroyView() {
RecyclerView listView = (RecyclerView) rootView.findViewById(R.id.messageRecyclerView);
if (listView != null) {
RecyclerView.Adapter adapter = listView.getAdapter();
if (adapter != null) {
RecyclerView.Adapter adapter = messageRecyclerView.getAdapter();
if (adapter != null)
adapter.unregisterAdapterDataObserver(recyclerViewAutoScrollManager);
}
}
compositeDisposable.clear();
......@@ -553,12 +543,11 @@ public class RoomFragment extends AbstractChatRoomFragment implements
@Override
public void updateHistoryState(boolean hasNext, boolean isLoaded) {
RecyclerView listView = (RecyclerView) rootView.findViewById(R.id.messageRecyclerView);
if (listView == null || !(listView.getAdapter() instanceof MessageListAdapter)) {
if (messageRecyclerView == null || !(messageRecyclerView.getAdapter() instanceof MessageListAdapter)) {
return;
}
MessageListAdapter adapter = (MessageListAdapter) listView.getAdapter();
MessageListAdapter adapter = (MessageListAdapter) messageRecyclerView.getAdapter();
if (isLoaded) {
scrollListener.setLoadingDone();
}
......@@ -610,4 +599,4 @@ public class RoomFragment extends AbstractChatRoomFragment implements
edittingMessage = message;
messageFormManager.setEditMessage(message.getMessage());
}
}
}
\ No newline at end of file
......@@ -230,8 +230,7 @@ public class SidebarMainFragment extends AbstractFragment implements SidebarMain
private void onRenderCurrentUser(User user, RocketChatAbsoluteUrl absoluteUrl) {
if (user != null && absoluteUrl != null) {
new UserRenderer(getContext(), user)
.avatarInto((RocketChatAvatar) rootView.findViewById(R.id.current_user_avatar),
absoluteUrl)
.avatarInto((RocketChatAvatar) rootView.findViewById(R.id.current_user_avatar), absoluteUrl)
.usernameInto((TextView) rootView.findViewById(R.id.current_user_name))
.statusColorInto((ImageView) rootView.findViewById(R.id.current_user_status));
}
......
......@@ -6,13 +6,14 @@ import android.graphics.Canvas;
import android.graphics.Typeface;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import com.amulyakhare.textdrawable.TextDrawable;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import android.support.graphics.drawable.VectorDrawableCompat;
import chat.rocket.android.R;
import chat.rocket.android.log.RCLog;
import chat.rocket.android.widget.AbsoluteUrl;
import chat.rocket.android.widget.RocketChatAvatar;
import com.amulyakhare.textdrawable.TextDrawable;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
/**
* Helper for rendering user avatar image.
......@@ -91,6 +92,14 @@ public class Avatar {
rocketChatAvatar.loadImage(getImageUrl(), getTextDrawable(context));
}
/**
* render error avatar into RocketChatAvatar.
*/
public void errorInto(final RocketChatAvatar rocketChatAvatar) {
final Context context = rocketChatAvatar.getContext();
rocketChatAvatar.loadImage(VectorDrawableCompat.create(context.getResources(), R.drawable.ic_error_outline_black_24dp, null));
}
public Drawable getTextDrawable(Context context) {
if (username == null) {
return null;
......
......@@ -11,8 +11,7 @@ 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;
......
......@@ -3,13 +3,12 @@ package chat.rocket.android.layouthelper.chatroom;
import android.support.annotation.Nullable;
import android.view.View;
import android.widget.TextView;
import chat.rocket.android.R;
import chat.rocket.android.helper.DateTime;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.widget.AbsoluteUrl;
import chat.rocket.core.SyncState;
import chat.rocket.android.widget.RocketChatAvatar;
import chat.rocket.core.SyncState;
public abstract class AbstractMessageViewHolder extends ModelViewHolder<PairedMessage> {
protected final RocketChatAvatar avatar;
......@@ -40,17 +39,14 @@ public abstract class AbstractMessageViewHolder extends ModelViewHolder<PairedMe
* bind the view model.
*/
public final void bind(PairedMessage pairedMessage, boolean autoloadImages) {
bindMessage(pairedMessage, autoloadImages);
if (pairedMessage.target != null) {
int syncState = pairedMessage.target.getSyncState();
if (syncState == SyncState.NOT_SYNCED || syncState == SyncState.SYNCING) {
if (pairedMessage.target.getSyncState() != SyncState.SYNCED)
itemView.setAlpha(0.6f);
} else {
else
itemView.setAlpha(1.0f);
}
}
bindMessage(pairedMessage, autoloadImages);
renderNewDayAndSequential(pairedMessage);
}
......@@ -73,19 +69,17 @@ public abstract class AbstractMessageViewHolder extends ModelViewHolder<PairedMe
private void setSequential(boolean sequential) {
if (avatar != null) {
if (sequential) {
if (sequential)
avatar.setVisibility(View.GONE);
} else {
else
avatar.setVisibility(View.VISIBLE);
}
}
if (userAndTimeContainer != null) {
if (sequential) {
if (sequential)
userAndTimeContainer.setVisibility(View.GONE);
} else {
else
userAndTimeContainer.setVisibility(View.VISIBLE);
}
}
}
......
......@@ -16,8 +16,7 @@ import chat.rocket.core.models.Message;
/**
* target list adapter for chat room.
*/
public class MessageListAdapter
extends ExtModelListAdapter<Message, PairedMessage, AbstractMessageViewHolder> {
public class MessageListAdapter extends ExtModelListAdapter<Message, PairedMessage, AbstractMessageViewHolder> {
private static final int VIEW_TYPE_UNKNOWN = 0;
private static final int VIEW_TYPE_NORMAL_MESSAGE = 1;
......@@ -99,8 +98,7 @@ public class MessageListAdapter
default:
return new AbstractMessageViewHolder(itemView, absoluteUrl) {
@Override
protected void bindMessage(PairedMessage pairedMessage, boolean autoloadImages) {
}
protected void bindMessage(PairedMessage pairedMessage, boolean autoloadImages) {}
};
}
}
......@@ -173,4 +171,4 @@ public class MessageListAdapter
return oldMessage.equals(newMessage);
}
}
}
}
\ No newline at end of file
package chat.rocket.android.layouthelper.chatroom;
import android.view.View;
import chat.rocket.android.R;
import chat.rocket.android.renderer.MessageRenderer;
import chat.rocket.android.widget.AbsoluteUrl;
......@@ -24,8 +23,7 @@ public class MessageNormalViewHolder extends AbstractMessageViewHolder {
super(itemView, absoluteUrl);
body = (RocketChatMessageLayout) itemView.findViewById(R.id.message_body);
urls = (RocketChatMessageUrlsLayout) itemView.findViewById(R.id.message_urls);
attachments =
(RocketChatMessageAttachmentsLayout) itemView.findViewById(R.id.message_attachments);
attachments = (RocketChatMessageAttachmentsLayout) itemView.findViewById(R.id.message_attachments);
}
@Override
......
......@@ -12,8 +12,7 @@ import android.view.ViewGroup;
import java.util.List;
@SuppressWarnings("PMD.GenericsNaming")
public abstract class ModelListAdapter<T, VM, VH extends ModelViewHolder<VM>>
extends RecyclerView.Adapter<VH> {
public abstract class ModelListAdapter<T, VM, VH extends ModelViewHolder<VM>> extends RecyclerView.Adapter<VH> {
protected final LayoutInflater inflater;
private List<VM> adapterData;
......
package chat.rocket.android.renderer;
import android.content.Context;
import android.support.graphics.drawable.VectorDrawableCompat;
import android.view.View;
import android.widget.TextView;
import java.util.List;
import chat.rocket.android.R;
import chat.rocket.android.helper.Avatar;
import chat.rocket.android.helper.DateTime;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.widget.AbsoluteUrl;
import chat.rocket.core.SyncState;
import chat.rocket.core.models.Attachment;
import chat.rocket.core.models.Message;
import chat.rocket.android.widget.RocketChatAvatar;
import chat.rocket.android.widget.message.RocketChatMessageAttachmentsLayout;
import chat.rocket.android.widget.message.RocketChatMessageLayout;
import chat.rocket.android.widget.message.RocketChatMessageUrlsLayout;
import chat.rocket.core.SyncState;
import chat.rocket.core.models.Attachment;
import chat.rocket.core.models.Message;
import chat.rocket.core.models.User;
import chat.rocket.core.models.WebContent;
import java.util.List;
/**
* Renderer for RealmMessage model.
......@@ -39,15 +37,20 @@ public class MessageRenderer extends AbstractRenderer<Message> {
* show Avatar image.
*/
public MessageRenderer avatarInto(RocketChatAvatar rocketChatAvatar, AbsoluteUrl absoluteUrl) {
if (object.getSyncState() == SyncState.FAILED) {
rocketChatAvatar.loadImage(VectorDrawableCompat.create(context.getResources(), R.drawable.ic_error_outline_black_24dp, null));
} else if (TextUtils.isEmpty(object.getAvatar())) {
if (!shouldHandle(rocketChatAvatar)) {
return this;
}
if (object.getSyncState() == SyncState.FAILED)
// rocketChatAvatar.loadImage(VectorDrawableCompat.create(context.getResources(), R.drawable.ic_error_outline_black_24dp, null));
userRenderer.errorAvatarInto(rocketChatAvatar);
else if (TextUtils.isEmpty(object.getAvatar()))
userRenderer.avatarInto(rocketChatAvatar, absoluteUrl);
} else {
else {
final User user = object.getUser();
setAvatarInto(object.getAvatar(), absoluteUrl, user == null ? null : user.getUsername(),
rocketChatAvatar);
setAvatarInto(object.getAvatar(), absoluteUrl, user == null ? null : user.getUsername(), rocketChatAvatar);
}
return this;
}
......@@ -78,6 +81,9 @@ public class MessageRenderer extends AbstractRenderer<Message> {
case SyncState.SYNCING:
textView.setText(R.string.sending);
break;
case SyncState.NOT_SYNCED:
textView.setText(R.string.not_synced);
break;
case SyncState.FAILED:
textView.setText(R.string.failed_to_sync);
break;
......@@ -142,8 +148,7 @@ public class MessageRenderer extends AbstractRenderer<Message> {
return this;
}
private void setAvatarInto(String avatar, AbsoluteUrl absoluteUrl, String username,
RocketChatAvatar imageView) {
private void setAvatarInto(String avatar, AbsoluteUrl absoluteUrl, String username, RocketChatAvatar imageView) {
imageView.loadImage(avatar, new Avatar(absoluteUrl, username).getTextDrawable(context));
}
......
......@@ -3,12 +3,11 @@ package chat.rocket.android.renderer;
import android.content.Context;
import android.widget.ImageView;
import android.widget.TextView;
import chat.rocket.android.helper.Avatar;
import chat.rocket.android.helper.TextUtils;
import chat.rocket.android.widget.AbsoluteUrl;
import chat.rocket.core.models.User;
import chat.rocket.android.widget.RocketChatAvatar;
import chat.rocket.core.models.User;
/**
* Renderer for RealmUser model.
......@@ -33,6 +32,20 @@ public class UserRenderer extends AbstractRenderer<User> {
return this;
}
/**
* show Avatar error image
*/
public UserRenderer errorAvatarInto(RocketChatAvatar rocketChatAvatar) {
if (!shouldHandle(rocketChatAvatar)) {
return this;
}
if (!TextUtils.isEmpty(object.getUsername())) {
new Avatar(null, object.getUsername()).errorInto(rocketChatAvatar);
}
return this;
}
/**
* show Username in textView
*/
......
package chat.rocket.android.service.observer;
import android.content.Context;
import io.realm.Realm;
import io.realm.RealmResults;
import io.realm.Sort;
import org.json.JSONObject;
import java.util.List;
import bolts.Task;
import chat.rocket.android.api.MethodCallHelper;
import chat.rocket.android.log.RCLog;
import chat.rocket.android.service.DDPClientRef;
import chat.rocket.core.SyncState;
import chat.rocket.persistence.realm.RealmHelper;
import chat.rocket.persistence.realm.models.ddp.RealmMessage;
import chat.rocket.persistence.realm.models.internal.LoadMessageProcedure;
import chat.rocket.persistence.realm.RealmHelper;
import chat.rocket.android.service.DDPClientRef;
import io.realm.Realm;
import io.realm.RealmResults;
import io.realm.Sort;
import java.util.List;
import org.json.JSONObject;
/**
* Background process for loading messages.
......@@ -74,13 +72,17 @@ public class LoadMessageProcedureObserver extends AbstractModelObserver<LoadMess
).continueWithTask(task -> {
if (task.isFaulted()) {
RCLog.w(task.getError());
return realmHelper.executeTransaction(realm ->
realmHelper.executeTransaction(realm ->
realm.createOrUpdateObjectFromJson(LoadMessageProcedure.class, new JSONObject()
.put(LoadMessageProcedure.ID, roomId)
.put(LoadMessageProcedure.SYNC_STATE, SyncState.FAILED)));
} else {
return Task.forResult(null);
realmHelper.executeTransaction(realm ->
realm.createOrUpdateObjectFromJson(LoadMessageProcedure.class, new JSONObject()
.put(LoadMessageProcedure.ID, roomId)
.put(LoadMessageProcedure.SYNC_STATE, SyncState.SYNCED)));
}
return null;
});
}
}
}
\ No newline at end of file
......@@ -16,7 +16,8 @@
<string name="users_of_room_title">Members List</string>
<string name="fmt_room_user_count">Total: %,d users</string>
<string name="sending">Sending…</string>
<string name="failed_to_sync">Failed to send!</string>
<string name="not_synced">Not synced…</string>
<string name="failed_to_sync">Failed to sync…</string>
<string name="resend">Resend</string>
<string name="discard">Discard</string>
......
......@@ -8,14 +8,11 @@ import android.os.Build;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
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 chat.rocket.android.widget.R;
public class RocketChatAvatar extends FrameLayout {
private SimpleDraweeView draweeView;
......@@ -49,8 +46,18 @@ public class RocketChatAvatar extends FrameLayout {
}
public void loadImage(Drawable drawable) {
// final GenericDraweeHierarchy hierarchy = draweeView.getHierarchy();
// hierarchy.setImage(drawable, 100, true); // Is there a better way?
final GenericDraweeHierarchy hierarchy = draweeView.getHierarchy();
hierarchy.setImage(drawable, 100, true); // Is there a better way?
hierarchy.setPlaceholderImage(drawable);
hierarchy.setFailureImage(drawable);
final DraweeController controller = Fresco.newDraweeControllerBuilder()
.setAutoPlayAnimations(true)
.build();
draweeView.setController(controller);
}
public void loadImage(String url, Drawable placeholder) {
......
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