From 621d6c3903e7b64f3b0e1cab3869fceebe7c0592 Mon Sep 17 00:00:00 2001 From: Valery Miller Date: Thu, 18 Oct 2018 18:58:07 +0500 Subject: [PATCH 001/257] Refactoring chat screen --- xabber/build.gradle | 1 + .../android/ui/adapter/FilesAdapter.java | 2 +- .../ui/adapter/chat/ActionMessageVH.java | 33 +++ .../ui/adapter/chat/BasicMessageVH.java | 27 +++ .../ui/adapter/chat/FileMessageVH.java | 192 +++++++++++++++++ .../ui/adapter/chat/IncomingMessageVH.java | 124 +++++++++++ .../android/ui/adapter/chat/MessageVH.java | 197 +++++++++++++++++ .../ui/adapter/chat/MessagesAdapter.java | 201 ++++++++++++++++++ .../ui/adapter/chat/OutgoingMessageVH.java | 164 ++++++++++++++ .../android/ui/fragment/ChatFragment.java | 13 +- .../main/res/drawable/message_background.xml | 16 ++ .../main/res/layout/item_message_incoming.xml | 47 ++++ .../main/res/layout/item_message_outgoing.xml | 44 ++++ xabber/src/main/res/layout/item_msg.xml | 135 ++++++++++++ xabber/src/main/res/layout/item_msg_2.xml | 69 ++++++ 15 files changed, 1259 insertions(+), 6 deletions(-) create mode 100644 xabber/src/main/java/com/xabber/android/ui/adapter/chat/ActionMessageVH.java create mode 100644 xabber/src/main/java/com/xabber/android/ui/adapter/chat/BasicMessageVH.java create mode 100644 xabber/src/main/java/com/xabber/android/ui/adapter/chat/FileMessageVH.java create mode 100644 xabber/src/main/java/com/xabber/android/ui/adapter/chat/IncomingMessageVH.java create mode 100644 xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessageVH.java create mode 100644 xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessagesAdapter.java create mode 100644 xabber/src/main/java/com/xabber/android/ui/adapter/chat/OutgoingMessageVH.java create mode 100644 xabber/src/main/res/drawable/message_background.xml create mode 100644 xabber/src/main/res/layout/item_message_incoming.xml create mode 100644 xabber/src/main/res/layout/item_message_outgoing.xml create mode 100644 xabber/src/main/res/layout/item_msg.xml create mode 100644 xabber/src/main/res/layout/item_msg_2.xml diff --git a/xabber/build.gradle b/xabber/build.gradle index 4006849a43..7ed816be05 100644 --- a/xabber/build.gradle +++ b/xabber/build.gradle @@ -153,6 +153,7 @@ dependencies { implementation "com.android.support:support-v13:$supportVersion" implementation "com.android.support:customtabs:$supportVersion" implementation 'com.android.support:multidex:1.0.3' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' // firebase compile 'com.google.firebase:firebase-messaging:11.4.0' diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/FilesAdapter.java b/xabber/src/main/java/com/xabber/android/ui/adapter/FilesAdapter.java index 54723a91a8..29a1b396f9 100644 --- a/xabber/src/main/java/com/xabber/android/ui/adapter/FilesAdapter.java +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/FilesAdapter.java @@ -25,7 +25,7 @@ public class FilesAdapter extends RecyclerView.Adapter items; private FileListListener listener; - interface FileListListener { + public interface FileListListener { void onFileClick(int position); void onFileLongClick(Attachment attachment, View caller); void onDownloadCancel(); diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/ActionMessageVH.java b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/ActionMessageVH.java new file mode 100644 index 0000000000..70a2a48a87 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/ActionMessageVH.java @@ -0,0 +1,33 @@ +package com.xabber.android.ui.adapter.chat; + +import android.content.Context; +import android.view.View; + +import com.xabber.android.data.database.messagerealm.MessageItem; +import com.xabber.android.data.entity.AccountJid; +import com.xabber.android.data.message.ChatAction; +import com.xabber.android.data.roster.RosterManager; +import com.xabber.android.utils.StringUtils; + +import java.util.Date; + +public class ActionMessageVH extends BasicMessageVH { + + public ActionMessageVH(View itemView) { + super(itemView); + } + + public void bind(MessageItem messageItem, Context context, AccountJid account, boolean isMUC) { + ChatAction action = MessageItem.getChatAction(messageItem); + String time = StringUtils.getSmartTimeText(context, new Date(messageItem.getTimestamp())); + + String name; + if (isMUC) { + name = messageItem.getResource().toString(); + } else { + name = RosterManager.getInstance().getBestContact(account, messageItem.getUser()).getName(); + } + messageText.setText(time + ": " + + action.getText(context, name, MessageItem.getSpannable(messageItem).toString())); + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/BasicMessageVH.java b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/BasicMessageVH.java new file mode 100644 index 0000000000..0e02751f79 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/BasicMessageVH.java @@ -0,0 +1,27 @@ +package com.xabber.android.ui.adapter.chat; + +import android.support.annotation.StyleRes; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.TextView; + +import com.xabber.android.R; + +public class BasicMessageVH extends RecyclerView.ViewHolder { + + TextView messageText; + + BasicMessageVH(View itemView, @StyleRes int appearance) { + super(itemView); + + messageText = (TextView) itemView.findViewById(R.id.message_text); + messageText.setTextAppearance(itemView.getContext(), appearance); + } + + BasicMessageVH(View itemView) { + super(itemView); + + messageText = (TextView) itemView.findViewById(R.id.message_text); + } +} + diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/FileMessageVH.java b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/FileMessageVH.java new file mode 100644 index 0000000000..557281a2eb --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/FileMessageVH.java @@ -0,0 +1,192 @@ +package com.xabber.android.ui.adapter.chat; + +import android.content.Context; +import android.graphics.Bitmap; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.view.ViewGroup; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.resource.drawable.GlideDrawable; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.animation.GlideAnimation; +import com.bumptech.glide.request.target.SimpleTarget; +import com.bumptech.glide.request.target.Target; +import com.xabber.android.data.SettingsManager; +import com.xabber.android.data.database.MessageDatabaseManager; +import com.xabber.android.data.database.messagerealm.Attachment; +import com.xabber.android.data.database.messagerealm.MessageItem; +import com.xabber.android.data.entity.AccountJid; +import com.xabber.android.data.extension.file.FileManager; +import com.xabber.android.ui.adapter.FilesAdapter; +import com.xabber.android.ui.widget.ImageGridBuilder; + +import io.realm.Realm; +import io.realm.RealmList; + +public class FileMessageVH extends MessageVH { + + public FileMessageVH(View itemView, MessageClickListener onClickListener, int appearance) { + super(itemView, onClickListener, appearance); + } + + public void bind(MessageItem messageItem, boolean isMUC, boolean showOriginalOTR, + Context context, boolean unread) { + super.bind(messageItem, isMUC, showOriginalOTR, context, unread); + setupImageOrFile(messageItem, context); + } + + protected void setupImageOrFile(MessageItem messageItem, Context context) { + fileLayout.setVisibility(View.GONE); + messageImage.setVisibility(View.GONE); + imageGridContainer.removeAllViews(); + imageGridContainer.setVisibility(View.GONE); + messageText.setVisibility(View.VISIBLE); + + if (messageItem.haveAttachments()) { + setUpImage(messageItem.getAttachments()); + setUpFile(messageItem.getAttachments(), context); + } else if (messageItem.isImage()) { + prepareImage(messageItem, context); + } + } + + private void prepareImage(MessageItem messageItem, Context context) { + String filePath = messageItem.getFilePath(); + Integer imageWidth = messageItem.getImageWidth(); + Integer imageHeight = messageItem.getImageHeight(); + String imageUrl = messageItem.getText(); + final String uniqueId = messageItem.getUniqueId(); + setUpImage(filePath, imageUrl, uniqueId, imageWidth, imageHeight, context); + } + + private void setUpImage(RealmList attachments) { + final ImageGridBuilder gridBuilder = new ImageGridBuilder(); + + if (!SettingsManager.connectionLoadImages()) return; + + RealmList imageAttachments = new RealmList<>(); + for (Attachment attachment : attachments) { + if (attachment.isImage()) imageAttachments.add(attachment); + } + + if (imageAttachments.size() > 0) { + View imageGridView = gridBuilder.inflateView(imageGridContainer, imageAttachments.size()); + gridBuilder.bindView(imageGridView, imageAttachments, this); + + imageGridContainer.addView(imageGridView); + imageGridContainer.setVisibility(View.VISIBLE); + messageText.setVisibility(View.GONE); + } + } + + private void setUpFile(RealmList attachments, Context context) { + RealmList fileAttachments = new RealmList<>(); + for (Attachment attachment : attachments) { + if (!attachment.isImage()) fileAttachments.add(attachment); + } + + if (fileAttachments.size() > 0) { + RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(context); + rvFileList.setLayoutManager(layoutManager); + FilesAdapter adapter = new FilesAdapter(fileAttachments, this); + rvFileList.setAdapter(adapter); + messageText.setVisibility(View.GONE); + fileLayout.setVisibility(View.VISIBLE); + } + } + + private void setUpImage(String imagePath, String imageUrl, final String uniqueId, Integer imageWidth, + Integer imageHeight, Context context) { + + if (!SettingsManager.connectionLoadImages()) return; + + if (imagePath != null) { + boolean result = FileManager.loadImageFromFile(context, imagePath, messageImage); + + if (result) { + messageImage.setVisibility(View.VISIBLE); + messageText.setVisibility(View.GONE); + } else { + final Realm realm = MessageDatabaseManager.getInstance().getRealmUiThread(); + realm.executeTransactionAsync(new Realm.Transaction() { + @Override + public void execute(Realm realm) { + MessageItem first = realm.where(MessageItem.class) + .equalTo(MessageItem.Fields.UNIQUE_ID, uniqueId) + .findFirst(); + if (first != null) { + first.setFilePath(null); + } + } + }); + } + } else { + final ViewGroup.LayoutParams layoutParams = messageImage.getLayoutParams(); + + if (imageWidth != null && imageHeight != null) { + FileManager.scaleImage(layoutParams, imageHeight, imageWidth); + Glide.with(context) + .load(imageUrl) + .listener(new RequestListener() { + @Override + public boolean onException(Exception e, String model, Target target, boolean isFirstResource) { + messageImage.setVisibility(View.GONE); + messageText.setVisibility(View.VISIBLE); + return true; + } + + @Override + public boolean onResourceReady(GlideDrawable resource, String model, Target target, boolean isFromMemoryCache, boolean isFirstResource) { + return false; + } + }) + .into(messageImage); + + messageImage.setVisibility(View.VISIBLE); + messageText.setVisibility(View.GONE); + } else { + + Glide.with(context) + .load(imageUrl) + .asBitmap() + .into(new SimpleTarget() { + @Override + public void onResourceReady(final Bitmap resource, GlideAnimation glideAnimation) { + final int width = resource.getWidth(); + final int height = resource.getHeight(); + + if (width <= 0 || height <= 0) { + messageImage.setVisibility(View.GONE); + messageText.setVisibility(View.VISIBLE); + return; + } + + final Realm realm = MessageDatabaseManager.getInstance().getRealmUiThread(); + realm.executeTransactionAsync(new Realm.Transaction() { + @Override + public void execute(Realm realm) { + MessageItem first = realm.where(MessageItem.class) + .equalTo(MessageItem.Fields.UNIQUE_ID, uniqueId) + .findFirst(); + if (first != null) { + first.setImageWidth(width); + first.setImageHeight(height); + } + } + }); + + + FileManager.scaleImage(layoutParams, height, width); + + messageImage.setImageBitmap(resource); + + messageImage.setVisibility(View.VISIBLE); + messageText.setVisibility(View.GONE); + } + }); + } + } + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/IncomingMessageVH.java b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/IncomingMessageVH.java new file mode 100644 index 0000000000..a007868485 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/IncomingMessageVH.java @@ -0,0 +1,124 @@ +package com.xabber.android.ui.adapter.chat; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.support.annotation.StyleRes; +import android.support.v4.graphics.drawable.DrawableCompat; +import android.view.View; +import android.widget.ImageView; + +import com.xabber.android.R; +import com.xabber.android.data.SettingsManager; +import com.xabber.android.data.database.messagerealm.MessageItem; +import com.xabber.android.data.entity.AccountJid; +import com.xabber.android.data.entity.UserJid; +import com.xabber.android.data.extension.avatar.AvatarManager; +import com.xabber.android.data.extension.muc.MUCManager; +import com.xabber.android.data.log.LogManager; + +import org.jxmpp.jid.parts.Resourcepart; + +public class IncomingMessageVH extends FileMessageVH { + + public ImageView avatar; + public ImageView avatarBackground; + + IncomingMessageVH(View itemView, MessageClickListener listener, @StyleRes int appearance) { + super(itemView, listener, appearance); + avatar = (ImageView) itemView.findViewById(R.id.avatar); + avatarBackground = (ImageView) itemView.findViewById(R.id.avatarBackground); + } + + public void bind(MessageItem messageItem, boolean isMUC, boolean showOriginalOTR, + Context context, String userName, boolean unread) { + super.bind(messageItem, isMUC, showOriginalOTR, context, unread); + + // setup ARCHIVED icon + statusIcon.setVisibility(messageItem.isReceivedFromMessageArchive() ? View.VISIBLE : View.GONE); + + // setup BACKGROUND COLOR + //setUpMessageBalloonBackground(messageBalloon, backgroundColors); + + setUpAvatar(messageItem, isMUC, userName); + + // hide empty message + if (messageItem.getText().trim().isEmpty()) { + messageBalloon.setVisibility(View.GONE); + messageTime.setVisibility(View.GONE); + avatar.setVisibility(View.GONE); + avatarBackground.setVisibility(View.GONE); + LogManager.w(this, "Empty message! Hidden, but need to correct"); + } else { + messageBalloon.setVisibility(View.VISIBLE); + messageTime.setVisibility(View.VISIBLE); + } + } + + // TODO: 18.10.18 удалить +// private void setUpMessageBalloonBackground(View view, ColorStateList colorList) { +// final Drawable originalBackgroundDrawable = view.getBackground(); +// +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { +// originalBackgroundDrawable.setTintList(colorList); +// +// } else { +// Drawable wrapDrawable = DrawableCompat.wrap(originalBackgroundDrawable); +// DrawableCompat.setTintList(wrapDrawable, colorList); +// +// int pL = view.getPaddingLeft(); +// int pT = view.getPaddingTop(); +// int pR = view.getPaddingRight(); +// int pB = view.getPaddingBottom(); +// +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) +// view.setBackground(wrapDrawable); +// else view.setBackgroundDrawable(wrapDrawable); +// view.setPadding(pL, pT, pR, pB); +// } +// +// } + + private void setUpAvatar(MessageItem messageItem, boolean isMUC, String userName) { + if (SettingsManager.chatsShowAvatars() && !isMUC) { + final UserJid user = messageItem.getUser(); + avatar.setVisibility(View.VISIBLE); + avatarBackground.setVisibility(View.VISIBLE); + avatar.setImageDrawable(AvatarManager.getInstance().getUserAvatar(user, userName)); + + } else if (SettingsManager.chatsShowAvatarsMUC() && isMUC) { + final AccountJid account = messageItem.getAccount(); + final UserJid user = messageItem.getUser(); + final Resourcepart resource = messageItem.getResource(); + + avatar.setVisibility(View.VISIBLE); + avatarBackground.setVisibility(View.VISIBLE); + if ((MUCManager.getInstance().getNickname(account, user.getJid().asEntityBareJidIfPossible()).equals(resource))) { + avatar.setImageDrawable(AvatarManager.getInstance().getAccountAvatar(account)); + } else { + if (resource.equals(Resourcepart.EMPTY)) { + avatar.setImageDrawable(AvatarManager.getInstance().getRoomAvatar(user)); + } else { + + String nick = resource.toString(); + UserJid userJid = null; + + try { + userJid = UserJid.from(user.getJid().toString() + "/" + resource.toString()); + avatar.setImageDrawable(AvatarManager.getInstance() + .getOccupantAvatar(userJid, nick)); + + } catch (UserJid.UserJidCreateException e) { + LogManager.exception(this, e); + avatar.setImageDrawable(AvatarManager.getInstance() + .generateDefaultAvatar(nick, nick)); + } + } + } + } else { + avatar.setVisibility(View.GONE); + avatarBackground.setVisibility(View.GONE); + } + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessageVH.java b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessageVH.java new file mode 100644 index 0000000000..8eddbcbf71 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessageVH.java @@ -0,0 +1,197 @@ +package com.xabber.android.ui.adapter.chat; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.support.annotation.StyleRes; +import android.support.v4.graphics.drawable.DrawableCompat; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageButton; +import android.widget.ImageView; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.xabber.android.R; +import com.xabber.android.data.SettingsManager; +import com.xabber.android.data.account.AccountManager; +import com.xabber.android.data.database.messagerealm.Attachment; +import com.xabber.android.data.database.messagerealm.MessageItem; +import com.xabber.android.data.entity.AccountJid; +import com.xabber.android.data.extension.otr.OTRManager; +import com.xabber.android.data.log.LogManager; +import com.xabber.android.ui.adapter.ChatMessageAdapter; +import com.xabber.android.ui.adapter.FilesAdapter; +import com.xabber.android.utils.StringUtils; + +import java.util.Date; + +public class MessageVH extends BasicMessageVH implements View.OnClickListener, + FilesAdapter.FileListListener { + + private static final String LOG_TAG = ChatMessageAdapter.Message.class.getSimpleName(); + protected MessageClickListener onClickListener; + + TextView messageTime; + TextView messageHeader; + TextView messageNotDecrypted; + View messageBalloon; + + ImageView messageImage; + ImageView statusIcon; + ImageView ivEncrypted; + + View fileLayout; + RecyclerView rvFileList; + FrameLayout imageGridContainer; + + String messageId; + final ProgressBar uploadProgressBar; + final ImageButton ivCancelUpload; + + public MessageVH(View itemView, MessageClickListener onClickListener, @StyleRes int appearance) { + super(itemView, appearance); + this.onClickListener = onClickListener; + + uploadProgressBar = itemView.findViewById(R.id.uploadProgressBar); + ivCancelUpload = itemView.findViewById(R.id.ivCancelUpload); + if (ivCancelUpload != null) ivCancelUpload.setOnClickListener(this); + + messageTime = (TextView) itemView.findViewById(R.id.message_time); + messageHeader = (TextView) itemView.findViewById(R.id.message_header); + messageNotDecrypted = (TextView) itemView.findViewById(R.id.message_not_decrypted); + messageBalloon = itemView.findViewById(R.id.message_balloon); + + messageImage = (ImageView) itemView.findViewById(R.id.message_image); + + statusIcon = (ImageView) itemView.findViewById(R.id.message_status_icon); + ivEncrypted = (ImageView) itemView.findViewById(R.id.message_encrypted_icon); + + fileLayout = itemView.findViewById(R.id.fileLayout); + rvFileList = itemView.findViewById(R.id.rvFileList); + + imageGridContainer = itemView.findViewById(R.id.imageGridContainer); + + itemView.setOnClickListener(this); + messageImage.setOnClickListener(this); + } + + public void bind(MessageItem messageItem, boolean isMUC, boolean showOriginalOTR, + Context context, boolean unread) { + if (isMUC) { + messageHeader.setText(messageItem.getResource()); + messageHeader.setVisibility(View.VISIBLE); + } else { + messageHeader.setVisibility(View.GONE); + } + + if (messageItem.isEncrypted()) { + ivEncrypted.setVisibility(View.VISIBLE); + } else { + ivEncrypted.setVisibility(View.GONE); + } + + messageText.setText(messageItem.getText()); + if (OTRManager.getInstance().isEncrypted(messageItem.getText())) { + if (showOriginalOTR) + messageText.setVisibility(View.VISIBLE); + else messageText.setVisibility(View.GONE); + messageNotDecrypted.setVisibility(View.VISIBLE); + } else { + messageText.setVisibility(View.VISIBLE); + messageNotDecrypted.setVisibility(View.GONE); + } + + String time = StringUtils.getSmartTimeText(context, new Date(messageItem.getTimestamp())); + + Long delayTimestamp = messageItem.getDelayTimestamp(); + if (delayTimestamp != null) { + String delay = context.getString(messageItem.isIncoming() ? R.string.chat_delay : R.string.chat_typed, + StringUtils.getSmartTimeText(context, new Date(delayTimestamp))); + time += " (" + delay + ")"; + } + + messageTime.setText(time); + + /** setup UNREAD */ + if (unread) itemView.setBackgroundColor(context.getResources().getColor(R.color.unread_messages_background)); + else itemView.setBackgroundDrawable(null); + } + + @Override + public void onFileClick(int attachmentPosition) { + int messagePosition = getAdapterPosition(); + if (messagePosition == RecyclerView.NO_POSITION) { + LogManager.w(LOG_TAG, "onClick: no position"); + return; + } + + onClickListener.onFileClick(messagePosition, attachmentPosition); + } + + @Override + public void onFileLongClick(Attachment attachment, View caller) { + onClickListener.onFileLongClick(attachment, caller); + } + + @Override + public void onDownloadCancel() { + onClickListener.onDownloadCancel(); + } + + @Override + public void onDownloadError(String error) { + onClickListener.onDownloadError(error); + } + + @Override + public void onClick(View v) { + int adapterPosition = getAdapterPosition(); + if (adapterPosition == RecyclerView.NO_POSITION) { + LogManager.w(LOG_TAG, "onClick: no position"); + return; + } + + switch (v.getId()) { + case R.id.ivImage0: + onClickListener.onImageClick(adapterPosition, 0); + break; + case R.id.ivImage1: + onClickListener.onImageClick(adapterPosition, 1); + break; + case R.id.ivImage2: + onClickListener.onImageClick(adapterPosition, 2); + break; + case R.id.ivImage3: + onClickListener.onImageClick(adapterPosition, 3); + break; + case R.id.ivImage4: + onClickListener.onImageClick(adapterPosition, 4); + break; + case R.id.ivImage5: + onClickListener.onImageClick(adapterPosition, 5); + break; + case R.id.message_image: + onClickListener.onImageClick(adapterPosition, 0); + break; + case R.id.ivCancelUpload: + onClickListener.onUploadCancel(); + break; + default: + onClickListener.onMessageClick(messageBalloon, adapterPosition); + break; + } + } + + public interface MessageClickListener { + void onMessageClick(View caller, int position); + void onImageClick(int messagePosition, int attachmentPosition); + void onFileClick(int messagePosition, int attachmentPosition); + void onFileLongClick(Attachment attachment, View caller); + void onDownloadCancel(); + void onUploadCancel(); + void onDownloadError(String error); + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessagesAdapter.java b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessagesAdapter.java new file mode 100644 index 0000000000..d770415899 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessagesAdapter.java @@ -0,0 +1,201 @@ +package com.xabber.android.ui.adapter.chat; + +import android.content.Context; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.ViewGroup; + +import com.xabber.android.R; +import com.xabber.android.data.SettingsManager; +import com.xabber.android.data.database.messagerealm.MessageItem; +import com.xabber.android.data.entity.AccountJid; +import com.xabber.android.data.entity.UserJid; +import com.xabber.android.data.extension.muc.MUCManager; +import com.xabber.android.data.log.LogManager; +import com.xabber.android.data.message.AbstractChat; +import com.xabber.android.data.roster.RosterManager; + +import org.jxmpp.jid.parts.Resourcepart; + +import java.util.ArrayList; +import java.util.List; + +import io.realm.RealmRecyclerViewAdapter; +import io.realm.RealmResults; + +public class MessagesAdapter extends RealmRecyclerViewAdapter { + + private static final String LOG_TAG = MessagesAdapter.class.getSimpleName(); + + public static final int VIEW_TYPE_INCOMING_MESSAGE = 2; + public static final int VIEW_TYPE_OUTGOING_MESSAGE = 3; + private static final int VIEW_TYPE_ACTION_MESSAGE = 4; + + private final Context context; + private final MessageVH.MessageClickListener messageClickListener; + private final Listener listener; + + // message font style + private final int appearanceStyle = SettingsManager.chatsAppearanceStyle(); + //private ColorStateList incomingBackgroundColors; + private boolean isMUC; + private Resourcepart mucNickname; + private String userName; + private AccountJid account; + private UserJid user; + private int prevItemCount; + private int unreadCount = 0; + + private List itemsNeedOriginalText = new ArrayList<>(); + + public interface Listener { + void onMessageNumberChanged(int prevItemCount); + void onMessagesUpdated(); + } + + public MessagesAdapter( + Context context, RealmResults messageItems, + AbstractChat chat, MessageVH.MessageClickListener messageClickListener, Listener listener) { + super(context, messageItems, true); + + this.context = context; + this.messageClickListener = messageClickListener; + this.listener = listener; + + account = chat.getAccount(); + user = chat.getUser(); + userName = RosterManager.getInstance().getName(account, user); + prevItemCount = getItemCount(); + + isMUC = MUCManager.getInstance().hasRoom(account, user.getJid().asEntityBareJidIfPossible()); + if (isMUC) mucNickname = MUCManager.getInstance().getNickname(account, user.getJid().asEntityBareJidIfPossible()); + + //incomingBackgroundColors = ColorManager.getInstance().getChatIncomingBalloonColorsStateList(account); + } + + @Override + public int getItemCount() { + if (realmResults.isValid() && realmResults.isLoaded()) + return realmResults.size(); + else return 0; + } + + @Override + public int getItemViewType(int position) { + MessageItem messageItem = getMessageItem(position); + if (messageItem == null) return 0; + + if (messageItem.getAction() != null) + return VIEW_TYPE_ACTION_MESSAGE; + + if (messageItem.isIncoming()) { + if (isMUC && messageItem.getResource().equals(mucNickname)) { + return VIEW_TYPE_OUTGOING_MESSAGE; + } + return VIEW_TYPE_INCOMING_MESSAGE; + } else return VIEW_TYPE_OUTGOING_MESSAGE; + } + + @Override + public BasicMessageVH onCreateViewHolder(ViewGroup parent, int viewType) { + switch (viewType) { + case VIEW_TYPE_ACTION_MESSAGE: + return new ActionMessageVH(LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_action_message, parent, false)); + + case VIEW_TYPE_INCOMING_MESSAGE: + return new IncomingMessageVH(LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_message_incoming, parent, false), + messageClickListener, appearanceStyle); + + case VIEW_TYPE_OUTGOING_MESSAGE: + return new OutgoingMessageVH(LayoutInflater.from(parent.getContext()) + .inflate(R.layout.item_message_outgoing, parent, false), + messageClickListener, appearanceStyle); + default: + return null; + } + } + + @Override + public void onBindViewHolder(final BasicMessageVH holder, int position) { + + final int viewType = getItemViewType(position); + MessageItem messageItem = getMessageItem(position); + + if (messageItem == null) { + LogManager.w(LOG_TAG, "onBindViewHolder Null message item. Position: " + position); + return; + } + + // setup message uniqueId + if (holder instanceof MessageVH) + ((MessageVH)holder).messageId = messageItem.getUniqueId(); + + // setup message as unread + boolean unread = position >= getItemCount() - unreadCount; + + // need show original OTR message + boolean showOriginalOTR = itemsNeedOriginalText.contains(messageItem.getUniqueId()); + + switch (viewType) { + case VIEW_TYPE_ACTION_MESSAGE: + ((ActionMessageVH)holder).bind(messageItem, context, account, isMUC); + break; + + case VIEW_TYPE_INCOMING_MESSAGE: + ((IncomingMessageVH)holder).bind(messageItem, isMUC, showOriginalOTR, context, userName, unread); + + break; + case VIEW_TYPE_OUTGOING_MESSAGE: + ((OutgoingMessageVH)holder).bind(messageItem, isMUC, showOriginalOTR, context, unread); + break; + } + } + + @Override + public void onChange() { + notifyDataSetChanged(); + listener.onMessagesUpdated(); + + int itemCount = getItemCount(); + if (prevItemCount != itemCount) { + listener.onMessageNumberChanged(prevItemCount); + prevItemCount = itemCount; + } + } + + @Nullable + public MessageItem getMessageItem(int position) { + if (position == RecyclerView.NO_POSITION) return null; + + if (position < realmResults.size()) + return realmResults.get(position); + else return null; + } + + public int findMessagePosition(String uniqueId) { + for (int i = 0; i < realmResults.size(); i++) { + if (realmResults.get(i).getUniqueId().equals(uniqueId)) return i; + } + return RecyclerView.NO_POSITION; + } + + public boolean setUnreadCount(int unreadCount) { + if (this.unreadCount != unreadCount) { + this.unreadCount = unreadCount; + return true; + } else return false; + } + + public int getUnreadCount() { + return unreadCount; + } + + public void addOrRemoveItemNeedOriginalText(String messageId) { + if (itemsNeedOriginalText.contains(messageId)) + itemsNeedOriginalText.remove(messageId); + else itemsNeedOriginalText.add(messageId); + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/OutgoingMessageVH.java b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/OutgoingMessageVH.java new file mode 100644 index 0000000000..6a94f84ef4 --- /dev/null +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/OutgoingMessageVH.java @@ -0,0 +1,164 @@ +package com.xabber.android.ui.adapter.chat; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.support.annotation.StyleRes; +import android.support.v4.graphics.drawable.DrawableCompat; +import android.view.View; +import android.widget.ProgressBar; +import android.widget.TextView; + +import com.xabber.android.R; +import com.xabber.android.data.SettingsManager; +import com.xabber.android.data.account.AccountManager; +import com.xabber.android.data.database.messagerealm.MessageItem; +import com.xabber.android.data.entity.AccountJid; +import com.xabber.android.data.extension.httpfileupload.HttpFileUploadManager; + +import rx.functions.Action1; +import rx.subscriptions.CompositeSubscription; + +public class OutgoingMessageVH extends FileMessageVH { + + private CompositeSubscription subscriptions = new CompositeSubscription(); + + TextView messageFileInfo; + ProgressBar progressBar; + + OutgoingMessageVH(View itemView, MessageClickListener listener, @StyleRes int appearance) { + super(itemView, listener, appearance); + progressBar = (ProgressBar) itemView.findViewById(R.id.message_progress_bar); + messageFileInfo = (TextView) itemView.findViewById(R.id.message_file_info); + } + + public void bind(MessageItem messageItem, boolean isMUC, boolean showOriginalOTR, + final Context context, boolean unread) { + super.bind(messageItem, isMUC, showOriginalOTR, context, unread); + + setStatusIcon(messageItem); + + // setup PROGRESS + progressBar.setVisibility(messageItem.isInProgress() ? View.VISIBLE : View.GONE); + +// setUpMessageBalloonBackground(messageBalloon, +// context.getResources().getColorStateList(R.color.outgoing_message_color_state_dark), +// R.drawable.message_outgoing_states, account); + + itemView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(View view) { + subscribeForUploadProgress(context); + } + + @Override + public void onViewDetachedFromWindow(View v) { + unsubscribeAll(); + } + }); + } + + private void setStatusIcon(MessageItem messageItem) { + statusIcon.setVisibility(View.VISIBLE); + progressBar.setVisibility(View.GONE); + + boolean isFileUploadInProgress = MessageItem.isUploadFileMessage(messageItem); + + if (isFileUploadInProgress) + progressBar.setVisibility(View.VISIBLE); + + int messageIcon = R.drawable.ic_message_delivered_14dp; + if (messageItem.isForwarded()) { + messageIcon = R.drawable.ic_message_forwarded_14dp; + } else if (messageItem.isReceivedFromMessageArchive()) { + messageIcon = R.drawable.ic_message_synced_14dp; + } else if (messageItem.isError()) { + messageIcon = R.drawable.ic_message_has_error_14dp; + } else if (!isFileUploadInProgress && !messageItem.isSent() + && System.currentTimeMillis() - messageItem.getTimestamp() > 1000) { + messageIcon = R.drawable.ic_message_not_sent_14dp; + } else if (!messageItem.isDelivered()) { + if (messageItem.isAcknowledged()) + messageIcon = R.drawable.ic_message_acknowledged_14dp; + else statusIcon.setVisibility(View.GONE); + } + statusIcon.setImageResource(messageIcon); + } + + // TODO: 18.10.18 удалить +// private void setUpMessageBalloonBackground( +// View messageBalloon, ColorStateList darkColorStateList, +// int lightBackgroundId, AccountJid account) { +// +// if (SettingsManager.interfaceTheme() == SettingsManager.InterfaceTheme.dark) { +// final Drawable originalBackgroundDrawable = messageBalloon.getBackground(); +// +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { +// originalBackgroundDrawable.setTintList(darkColorStateList); +// } else { +// Drawable wrapDrawable = DrawableCompat.wrap(originalBackgroundDrawable); +// DrawableCompat.setTintList(wrapDrawable, darkColorStateList); +// +// int pL = messageBalloon.getPaddingLeft(); +// int pT = messageBalloon.getPaddingTop(); +// int pR = messageBalloon.getPaddingRight(); +// int pB = messageBalloon.getPaddingBottom(); +// +// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { +// messageBalloon.setBackground(wrapDrawable); +// } else { +// messageBalloon.setBackgroundDrawable(wrapDrawable); +// } +// +// messageBalloon.setPadding(pL, pT, pR, pB); +// } +// } else { +// int pL = messageBalloon.getPaddingLeft(); +// int pT = messageBalloon.getPaddingTop(); +// int pR = messageBalloon.getPaddingRight(); +// int pB = messageBalloon.getPaddingBottom(); +// +// messageBalloon.setBackgroundResource(lightBackgroundId); +// messageBalloon.getBackground().setLevel(AccountManager.getInstance().getColorLevel(account)); +// messageBalloon.setPadding(pL, pT, pR, pB); +// } +// } + + private void subscribeForUploadProgress(final Context context) { + subscriptions.add(HttpFileUploadManager.getInstance().subscribeForProgress() + .doOnNext(new Action1() { + @Override + public void call(HttpFileUploadManager.ProgressData progressData) { + setUpProgress(context, progressData); + } + }).subscribe()); + } + + private void unsubscribeAll() { + subscriptions.clear(); + } + + private void setUpProgress(Context context, HttpFileUploadManager.ProgressData progressData) { + if (progressData != null && messageId.equals(progressData.getMessageId())) { + if (progressData.isCompleted()) { + showProgress(false); + } else if (progressData.getError() != null) { + showProgress(false); + onClickListener.onDownloadError(progressData.getError()); + } else { + if (uploadProgressBar != null) uploadProgressBar.setProgress(progressData.getProgress()); + if (messageFileInfo != null) + messageFileInfo.setText(context.getString(R.string.uploaded_files_count, + progressData.getProgress() + "/" + progressData.getFileCount())); + showProgress(true); + } + } else showProgress(false); + } + + private void showProgress(boolean show) { + if (uploadProgressBar != null) uploadProgressBar.setVisibility(show ? View.VISIBLE : View.GONE); + if (ivCancelUpload != null) ivCancelUpload.setVisibility(show ? View.VISIBLE : View.GONE); + if (messageFileInfo != null) messageFileInfo.setVisibility(show ? View.VISIBLE : View.GONE); + } +} diff --git a/xabber/src/main/java/com/xabber/android/ui/fragment/ChatFragment.java b/xabber/src/main/java/com/xabber/android/ui/fragment/ChatFragment.java index aa972608a3..21f9447c27 100644 --- a/xabber/src/main/java/com/xabber/android/ui/fragment/ChatFragment.java +++ b/xabber/src/main/java/com/xabber/android/ui/fragment/ChatFragment.java @@ -95,6 +95,8 @@ import com.xabber.android.ui.adapter.ChatMessageAdapter; import com.xabber.android.ui.adapter.CustomMessageMenuAdapter; import com.xabber.android.ui.adapter.ResourceAdapter; +import com.xabber.android.ui.adapter.chat.MessageVH; +import com.xabber.android.ui.adapter.chat.MessagesAdapter; import com.xabber.android.ui.color.ColorManager; import com.xabber.android.ui.dialog.AttachDialog; import com.xabber.android.ui.dialog.ChatExportDialogFragment; @@ -132,9 +134,10 @@ public class ChatFragment extends Fragment implements PopupMenu.OnMenuItemClickListener, View.OnClickListener, Toolbar.OnMenuItemClickListener, - ChatMessageAdapter.Message.MessageClickListener, HttpUploadListener, - ChatMessageAdapter.Listener, AdapterView.OnItemClickListener, PopupWindow.OnDismissListener, - AttachDialog.Listener, OnAccountChangedListener { + MessageVH.MessageClickListener, HttpUploadListener, + MessagesAdapter.Listener, AdapterView.OnItemClickListener, PopupWindow.OnDismissListener, + AttachDialog.Listener, OnAccountChangedListener, ChatMessageAdapter.Listener, + ChatMessageAdapter.Message.MessageClickListener { public static final String ARGUMENT_ACCOUNT = "ARGUMENT_ACCOUNT"; public static final String ARGUMENT_USER = "ARGUMENT_USER"; @@ -171,7 +174,7 @@ public class ChatFragment extends Fragment implements PopupMenu.OnMenuItemClickL private TextView tvNotifyAction; private RecyclerView realmRecyclerView; - private ChatMessageAdapter chatMessageAdapter; + private MessagesAdapter chatMessageAdapter; private LinearLayoutManager layoutManager; private SwipeRefreshLayout swipeContainer; private View placeholder; @@ -375,7 +378,7 @@ public void setChat(AccountJid accountJid, UserJid userJid) { syncInfoResults = abstractChat.getSyncInfo(); } - chatMessageAdapter = new ChatMessageAdapter(getActivity(), messageItems, abstractChat, this); + chatMessageAdapter = new MessagesAdapter(getActivity(), messageItems, abstractChat, this, this); realmRecyclerView.setAdapter(chatMessageAdapter); restoreInputState(); diff --git a/xabber/src/main/res/drawable/message_background.xml b/xabber/src/main/res/drawable/message_background.xml new file mode 100644 index 0000000000..8ad69931a7 --- /dev/null +++ b/xabber/src/main/res/drawable/message_background.xml @@ -0,0 +1,16 @@ + + + + + + \ No newline at end of file diff --git a/xabber/src/main/res/layout/item_message_incoming.xml b/xabber/src/main/res/layout/item_message_incoming.xml new file mode 100644 index 0000000000..e734afbc22 --- /dev/null +++ b/xabber/src/main/res/layout/item_message_incoming.xml @@ -0,0 +1,47 @@ + + + + + + + + + + \ No newline at end of file diff --git a/xabber/src/main/res/layout/item_message_outgoing.xml b/xabber/src/main/res/layout/item_message_outgoing.xml new file mode 100644 index 0000000000..e4ef1f146b --- /dev/null +++ b/xabber/src/main/res/layout/item_message_outgoing.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/xabber/src/main/res/layout/item_msg.xml b/xabber/src/main/res/layout/item_msg.xml new file mode 100644 index 0000000000..35d6f8904a --- /dev/null +++ b/xabber/src/main/res/layout/item_msg.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xabber/src/main/res/layout/item_msg_2.xml b/xabber/src/main/res/layout/item_msg_2.xml new file mode 100644 index 0000000000..d5f880c38d --- /dev/null +++ b/xabber/src/main/res/layout/item_msg_2.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + \ No newline at end of file From 4ba0ac4ec0da8a508bf603f96cc0480e113f4b4f Mon Sep 17 00:00:00 2001 From: Valery Miller Date: Mon, 22 Oct 2018 16:58:13 +0500 Subject: [PATCH 002/257] Work on chat redesign --- .../ui/adapter/chat/IncomingMessageVH.java | 49 ++-- .../android/ui/adapter/chat/MessageVH.java | 4 +- .../ui/adapter/chat/MessagesAdapter.java | 12 +- .../ui/adapter/chat/OutgoingMessageVH.java | 84 +++---- .../com/xabber/android/utils/StringUtils.java | 4 + xabber/src/main/res/layout/item_msg.xml | 238 +++++++++--------- xabber/src/main/res/layout/item_msg_2.xml | 69 ----- 7 files changed, 198 insertions(+), 262 deletions(-) delete mode 100644 xabber/src/main/res/layout/item_msg_2.xml diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/IncomingMessageVH.java b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/IncomingMessageVH.java index a007868485..1bd79b1e4d 100644 --- a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/IncomingMessageVH.java +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/IncomingMessageVH.java @@ -32,14 +32,14 @@ public class IncomingMessageVH extends FileMessageVH { } public void bind(MessageItem messageItem, boolean isMUC, boolean showOriginalOTR, - Context context, String userName, boolean unread) { + Context context, String userName, boolean unread, ColorStateList backgroundColors) { super.bind(messageItem, isMUC, showOriginalOTR, context, unread); // setup ARCHIVED icon statusIcon.setVisibility(messageItem.isReceivedFromMessageArchive() ? View.VISIBLE : View.GONE); // setup BACKGROUND COLOR - //setUpMessageBalloonBackground(messageBalloon, backgroundColors); + setUpMessageBalloonBackground(messageBalloon, backgroundColors); setUpAvatar(messageItem, isMUC, userName); @@ -56,29 +56,28 @@ public void bind(MessageItem messageItem, boolean isMUC, boolean showOriginalOTR } } - // TODO: 18.10.18 удалить -// private void setUpMessageBalloonBackground(View view, ColorStateList colorList) { -// final Drawable originalBackgroundDrawable = view.getBackground(); -// -// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { -// originalBackgroundDrawable.setTintList(colorList); -// -// } else { -// Drawable wrapDrawable = DrawableCompat.wrap(originalBackgroundDrawable); -// DrawableCompat.setTintList(wrapDrawable, colorList); -// -// int pL = view.getPaddingLeft(); -// int pT = view.getPaddingTop(); -// int pR = view.getPaddingRight(); -// int pB = view.getPaddingBottom(); -// -// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) -// view.setBackground(wrapDrawable); -// else view.setBackgroundDrawable(wrapDrawable); -// view.setPadding(pL, pT, pR, pB); -// } -// -// } + private void setUpMessageBalloonBackground(View view, ColorStateList colorList) { + final Drawable originalBackgroundDrawable = view.getBackground(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + originalBackgroundDrawable.setTintList(colorList); + + } else { + Drawable wrapDrawable = DrawableCompat.wrap(originalBackgroundDrawable); + DrawableCompat.setTintList(wrapDrawable, colorList); + + int pL = view.getPaddingLeft(); + int pT = view.getPaddingTop(); + int pR = view.getPaddingRight(); + int pB = view.getPaddingBottom(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) + view.setBackground(wrapDrawable); + else view.setBackgroundDrawable(wrapDrawable); + view.setPadding(pL, pT, pR, pB); + } + + } private void setUpAvatar(MessageItem messageItem, boolean isMUC, String userName) { if (SettingsManager.chatsShowAvatars() && !isMUC) { diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessageVH.java b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessageVH.java index 8eddbcbf71..138023c3c4 100644 --- a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessageVH.java +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessageVH.java @@ -104,12 +104,12 @@ public void bind(MessageItem messageItem, boolean isMUC, boolean showOriginalOTR messageNotDecrypted.setVisibility(View.GONE); } - String time = StringUtils.getSmartTimeText(context, new Date(messageItem.getTimestamp())); + String time = StringUtils.getTimeText(new Date(messageItem.getTimestamp())); Long delayTimestamp = messageItem.getDelayTimestamp(); if (delayTimestamp != null) { String delay = context.getString(messageItem.isIncoming() ? R.string.chat_delay : R.string.chat_typed, - StringUtils.getSmartTimeText(context, new Date(delayTimestamp))); + StringUtils.getTimeText(new Date(delayTimestamp))); time += " (" + delay + ")"; } diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessagesAdapter.java b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessagesAdapter.java index d770415899..204e45f4d4 100644 --- a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessagesAdapter.java +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessagesAdapter.java @@ -1,6 +1,7 @@ package com.xabber.android.ui.adapter.chat; import android.content.Context; +import android.content.res.ColorStateList; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; @@ -15,6 +16,7 @@ import com.xabber.android.data.log.LogManager; import com.xabber.android.data.message.AbstractChat; import com.xabber.android.data.roster.RosterManager; +import com.xabber.android.ui.color.ColorManager; import org.jxmpp.jid.parts.Resourcepart; @@ -38,7 +40,7 @@ public class MessagesAdapter extends RealmRecyclerViewAdapter= Build.VERSION_CODES.LOLLIPOP) { -// originalBackgroundDrawable.setTintList(darkColorStateList); -// } else { -// Drawable wrapDrawable = DrawableCompat.wrap(originalBackgroundDrawable); -// DrawableCompat.setTintList(wrapDrawable, darkColorStateList); -// -// int pL = messageBalloon.getPaddingLeft(); -// int pT = messageBalloon.getPaddingTop(); -// int pR = messageBalloon.getPaddingRight(); -// int pB = messageBalloon.getPaddingBottom(); -// -// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { -// messageBalloon.setBackground(wrapDrawable); -// } else { -// messageBalloon.setBackgroundDrawable(wrapDrawable); -// } -// -// messageBalloon.setPadding(pL, pT, pR, pB); -// } -// } else { -// int pL = messageBalloon.getPaddingLeft(); -// int pT = messageBalloon.getPaddingTop(); -// int pR = messageBalloon.getPaddingRight(); -// int pB = messageBalloon.getPaddingBottom(); -// -// messageBalloon.setBackgroundResource(lightBackgroundId); -// messageBalloon.getBackground().setLevel(AccountManager.getInstance().getColorLevel(account)); -// messageBalloon.setPadding(pL, pT, pR, pB); -// } -// } + private void setUpMessageBalloonBackground( + View messageBalloon, ColorStateList darkColorStateList, + int lightBackgroundId, AccountJid account) { + + if (SettingsManager.interfaceTheme() == SettingsManager.InterfaceTheme.dark) { + final Drawable originalBackgroundDrawable = messageBalloon.getBackground(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + originalBackgroundDrawable.setTintList(darkColorStateList); + } else { + Drawable wrapDrawable = DrawableCompat.wrap(originalBackgroundDrawable); + DrawableCompat.setTintList(wrapDrawable, darkColorStateList); + + int pL = messageBalloon.getPaddingLeft(); + int pT = messageBalloon.getPaddingTop(); + int pR = messageBalloon.getPaddingRight(); + int pB = messageBalloon.getPaddingBottom(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + messageBalloon.setBackground(wrapDrawable); + } else { + messageBalloon.setBackgroundDrawable(wrapDrawable); + } + + messageBalloon.setPadding(pL, pT, pR, pB); + } + } else { + int pL = messageBalloon.getPaddingLeft(); + int pT = messageBalloon.getPaddingTop(); + int pR = messageBalloon.getPaddingRight(); + int pB = messageBalloon.getPaddingBottom(); + + messageBalloon.setBackgroundResource(lightBackgroundId); + messageBalloon.getBackground().setLevel(AccountManager.getInstance().getColorLevel(account)); + messageBalloon.setPadding(pL, pT, pR, pB); + } + } private void subscribeForUploadProgress(final Context context) { subscriptions.add(HttpFileUploadManager.getInstance().subscribeForProgress() diff --git a/xabber/src/main/java/com/xabber/android/utils/StringUtils.java b/xabber/src/main/java/com/xabber/android/utils/StringUtils.java index 5eb867d3dc..7fa6acb91f 100644 --- a/xabber/src/main/java/com/xabber/android/utils/StringUtils.java +++ b/xabber/src/main/java/com/xabber/android/utils/StringUtils.java @@ -130,6 +130,10 @@ public static String getDateTimeText(Date timeStamp) { } } + public static String getTimeText(Date timeStamp) { + return timeFormat.format(timeStamp); + } + /** * @param timeStamp * @return String with time or with date and time depend on current time. diff --git a/xabber/src/main/res/layout/item_msg.xml b/xabber/src/main/res/layout/item_msg.xml index 35d6f8904a..76e541c0ec 100644 --- a/xabber/src/main/res/layout/item_msg.xml +++ b/xabber/src/main/res/layout/item_msg.xml @@ -1,7 +1,9 @@ - + - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - \ No newline at end of file + android:layout_marginTop="4dp" + android:layout_marginBottom="8dp" + android:layout_gravity="right" + android:orientation="horizontal" + > + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xabber/src/main/res/layout/item_msg_2.xml b/xabber/src/main/res/layout/item_msg_2.xml deleted file mode 100644 index d5f880c38d..0000000000 --- a/xabber/src/main/res/layout/item_msg_2.xml +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file From 079c5a3d358fe1a9f48bd6e5676d18359fb6e829 Mon Sep 17 00:00:00 2001 From: Valery Miller Date: Tue, 23 Oct 2018 17:46:53 +0500 Subject: [PATCH 003/257] Work on new message background system --- .../ui/adapter/chat/IncomingMessageVH.java | 31 +- .../ui/adapter/chat/MessagesAdapter.java | 11 +- .../ui/adapter/chat/OutgoingMessageVH.java | 51 +-- .../xabber/android/ui/color/ColorManager.java | 2 +- .../main/res/drawable/message_background.xml | 305 +++++++++++++++++- .../res/drawable/message_background_dark.xml | 36 +++ xabber/src/main/res/layout/item_msg.xml | 2 +- xabber/src/main/res/values/attrs.xml | 2 + xabber/src/main/res/values/theme.xml | 4 + 9 files changed, 342 insertions(+), 102 deletions(-) create mode 100644 xabber/src/main/res/drawable/message_background_dark.xml diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/IncomingMessageVH.java b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/IncomingMessageVH.java index 1bd79b1e4d..91c9a61c74 100644 --- a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/IncomingMessageVH.java +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/IncomingMessageVH.java @@ -1,11 +1,7 @@ package com.xabber.android.ui.adapter.chat; import android.content.Context; -import android.content.res.ColorStateList; -import android.graphics.drawable.Drawable; -import android.os.Build; import android.support.annotation.StyleRes; -import android.support.v4.graphics.drawable.DrawableCompat; import android.view.View; import android.widget.ImageView; @@ -32,14 +28,14 @@ public class IncomingMessageVH extends FileMessageVH { } public void bind(MessageItem messageItem, boolean isMUC, boolean showOriginalOTR, - Context context, String userName, boolean unread, ColorStateList backgroundColors) { + Context context, String userName, boolean unread, int accountColorLevel) { super.bind(messageItem, isMUC, showOriginalOTR, context, unread); // setup ARCHIVED icon statusIcon.setVisibility(messageItem.isReceivedFromMessageArchive() ? View.VISIBLE : View.GONE); // setup BACKGROUND COLOR - setUpMessageBalloonBackground(messageBalloon, backgroundColors); + messageBalloon.getBackground().setLevel(accountColorLevel); setUpAvatar(messageItem, isMUC, userName); @@ -56,29 +52,6 @@ public void bind(MessageItem messageItem, boolean isMUC, boolean showOriginalOTR } } - private void setUpMessageBalloonBackground(View view, ColorStateList colorList) { - final Drawable originalBackgroundDrawable = view.getBackground(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - originalBackgroundDrawable.setTintList(colorList); - - } else { - Drawable wrapDrawable = DrawableCompat.wrap(originalBackgroundDrawable); - DrawableCompat.setTintList(wrapDrawable, colorList); - - int pL = view.getPaddingLeft(); - int pT = view.getPaddingTop(); - int pR = view.getPaddingRight(); - int pB = view.getPaddingBottom(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) - view.setBackground(wrapDrawable); - else view.setBackgroundDrawable(wrapDrawable); - view.setPadding(pL, pT, pR, pB); - } - - } - private void setUpAvatar(MessageItem messageItem, boolean isMUC, String userName) { if (SettingsManager.chatsShowAvatars() && !isMUC) { final UserJid user = messageItem.getUser(); diff --git a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessagesAdapter.java b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessagesAdapter.java index 204e45f4d4..04e403f753 100644 --- a/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessagesAdapter.java +++ b/xabber/src/main/java/com/xabber/android/ui/adapter/chat/MessagesAdapter.java @@ -1,7 +1,6 @@ package com.xabber.android.ui.adapter.chat; import android.content.Context; -import android.content.res.ColorStateList; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; @@ -40,7 +39,7 @@ public class MessagesAdapter extends RealmRecyclerViewAdapter= Build.VERSION_CODES.LOLLIPOP) { - originalBackgroundDrawable.setTintList(darkColorStateList); - } else { - Drawable wrapDrawable = DrawableCompat.wrap(originalBackgroundDrawable); - DrawableCompat.setTintList(wrapDrawable, darkColorStateList); - - int pL = messageBalloon.getPaddingLeft(); - int pT = messageBalloon.getPaddingTop(); - int pR = messageBalloon.getPaddingRight(); - int pB = messageBalloon.getPaddingBottom(); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - messageBalloon.setBackground(wrapDrawable); - } else { - messageBalloon.setBackgroundDrawable(wrapDrawable); - } - - messageBalloon.setPadding(pL, pT, pR, pB); - } - } else { - int pL = messageBalloon.getPaddingLeft(); - int pT = messageBalloon.getPaddingTop(); - int pR = messageBalloon.getPaddingRight(); - int pB = messageBalloon.getPaddingBottom(); - - messageBalloon.setBackgroundResource(lightBackgroundId); - messageBalloon.getBackground().setLevel(AccountManager.getInstance().getColorLevel(account)); - messageBalloon.setPadding(pL, pT, pR, pB); - } - } - private void subscribeForUploadProgress(final Context context) { subscriptions.add(HttpFileUploadManager.getInstance().subscribeForProgress() .doOnNext(new Action1() { diff --git a/xabber/src/main/java/com/xabber/android/ui/color/ColorManager.java b/xabber/src/main/java/com/xabber/android/ui/color/ColorManager.java index 67ce97a21b..aadf39fb93 100644 --- a/xabber/src/main/java/com/xabber/android/ui/color/ColorManager.java +++ b/xabber/src/main/java/com/xabber/android/ui/color/ColorManager.java @@ -134,7 +134,7 @@ public int getUnreadMessageBackground(AccountJid account) { return unreadMessagesBackground[getAccountColorLevel(account)]; } - private static int getAccountColorLevel(AccountJid account) { + public static int getAccountColorLevel(AccountJid account) { return AccountManager.getInstance().getColorLevel(account); } diff --git a/xabber/src/main/res/drawable/message_background.xml b/xabber/src/main/res/drawable/message_background.xml index 8ad69931a7..11ed5ade17 100644 --- a/xabber/src/main/res/drawable/message_background.xml +++ b/xabber/src/main/res/drawable/message_background.xml @@ -1,16 +1,291 @@ - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xabber/src/main/res/drawable/message_background_dark.xml b/xabber/src/main/res/drawable/message_background_dark.xml new file mode 100644 index 0000000000..52a653e613 --- /dev/null +++ b/xabber/src/main/res/drawable/message_background_dark.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/xabber/src/main/res/layout/item_msg.xml b/xabber/src/main/res/layout/item_msg.xml index 76e541c0ec..3ac4bb13bc 100644 --- a/xabber/src/main/res/layout/item_msg.xml +++ b/xabber/src/main/res/layout/item_msg.xml @@ -6,7 +6,7 @@ android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@drawable/message_background" + android:background="?attr/message_background" android:padding="0dp" android:elevation="1dp" android:clickable="true"> diff --git a/xabber/src/main/res/values/attrs.xml b/xabber/src/main/res/values/attrs.xml index 65bb18ed97..64a9960066 100644 --- a/xabber/src/main/res/values/attrs.xml +++ b/xabber/src/main/res/values/attrs.xml @@ -58,5 +58,7 @@ + + \ No newline at end of file diff --git a/xabber/src/main/res/values/theme.xml b/xabber/src/main/res/values/theme.xml index 76980fd67d..b0ca7150f1 100644 --- a/xabber/src/main/res/values/theme.xml +++ b/xabber/src/main/res/values/theme.xml @@ -83,6 +83,8 @@ @color/bottom_navigation_background @drawable/half_transparent_background @color/grey_400 + + @drawable/message_background @@ -155,6 +157,8 @@ @color/black @drawable/half_transparent_background_dark @color/grey_800 + + @drawable/message_background_dark @@ -158,7 +158,7 @@ @drawable/half_transparent_background_dark @color/grey_800 - @drawable/message_background_dark + @color/message_color_state_dark + +