diff --git a/library/build.gradle b/library/build.gradle index 7c9ed42d9d7..d533d3c13e5 100644 --- a/library/build.gradle +++ b/library/build.gradle @@ -45,7 +45,7 @@ dependencies { implementation 'com.google.code.gson:gson:2.8.5' implementation 'com.github.bumptech.glide:glide:4.9.0' - + implementation 'com.github.duanhong169:drawabletoolbox:1.0.7' implementation "io.noties.markwon:core:$markwon_version" implementation "io.noties.markwon:linkify:$markwon_version" diff --git a/library/src/main/java/com/getstream/sdk/chat/adapter/AttachmentViewHolder.java b/library/src/main/java/com/getstream/sdk/chat/adapter/AttachmentViewHolder.java index c9bea20a8c8..6ae627debf5 100644 --- a/library/src/main/java/com/getstream/sdk/chat/adapter/AttachmentViewHolder.java +++ b/library/src/main/java/com/getstream/sdk/chat/adapter/AttachmentViewHolder.java @@ -145,7 +145,7 @@ private void configFileAttach() { lv_attachment_file.setAdapter(attachAdapter); lv_attachment_file.setOnItemClickListener((AdapterView parent, View view, int position, long id) -> { - Log.d(TAG, "Attach onClick: " + position); + Log.d(TAG, "Attach onMessageClick: " + position); SelectAttachmentModel attachmentModel = new SelectAttachmentModel(); attachmentModel.setAttachmentIndex(position); @@ -250,12 +250,12 @@ private void configMediaAttach() { private void triggerLongClick(Message message, Attachment attachment) { if (this.longClickListener != null) { - this.longClickListener.onClick(message, attachment); + this.longClickListener.onAttachmentClick(message, attachment); } } private void triggerClick(Message message, Attachment attachment) { if (this.clickListener != null) { - this.clickListener.onClick(message, attachment); + this.clickListener.onAttachmentClick(message, attachment); } } diff --git a/library/src/main/java/com/getstream/sdk/chat/adapter/AttachmentViewHolderFile.java b/library/src/main/java/com/getstream/sdk/chat/adapter/AttachmentViewHolderFile.java index 10825589cae..8e07c655961 100644 --- a/library/src/main/java/com/getstream/sdk/chat/adapter/AttachmentViewHolderFile.java +++ b/library/src/main/java/com/getstream/sdk/chat/adapter/AttachmentViewHolderFile.java @@ -60,13 +60,13 @@ public void bind(Context context, MessageListItem messageListItem, Attachment at private void triggerLongClick(Message message, Attachment attachment) { if (this.longClickListener != null) { - this.longClickListener.onClick(message, attachment); + this.longClickListener.onAttachmentClick(message, attachment); } } private void triggerClick(Message message, Attachment attachment) { if (this.clickListener != null) { - this.clickListener.onClick(message, attachment); + this.clickListener.onAttachmentClick(message, attachment); } } diff --git a/library/src/main/java/com/getstream/sdk/chat/adapter/AttachmentViewHolderMedia.java b/library/src/main/java/com/getstream/sdk/chat/adapter/AttachmentViewHolderMedia.java index af7f19e6fe0..d8320c95d43 100644 --- a/library/src/main/java/com/getstream/sdk/chat/adapter/AttachmentViewHolderMedia.java +++ b/library/src/main/java/com/getstream/sdk/chat/adapter/AttachmentViewHolderMedia.java @@ -142,7 +142,7 @@ private void configMediaAttach() { private void triggerClick(Message message, Attachment attachment) { if (this.clickListener != null) { - this.clickListener.onClick(message, attachment); + this.clickListener.onAttachmentClick(message, attachment); } } diff --git a/library/src/main/java/com/getstream/sdk/chat/adapter/ChannelListItemViewHolder.java b/library/src/main/java/com/getstream/sdk/chat/adapter/ChannelListItemViewHolder.java index 96260b749d9..f6d759bdea1 100644 --- a/library/src/main/java/com/getstream/sdk/chat/adapter/ChannelListItemViewHolder.java +++ b/library/src/main/java/com/getstream/sdk/chat/adapter/ChannelListItemViewHolder.java @@ -144,7 +144,7 @@ public void bind(Context context, ChannelState channelState, int position) { } // read indicators - read_state.setReads(lastMessageReads); + read_state.setReads(lastMessageReads,true, style); // apply unread style or read style if (unreadCount == 0) { diff --git a/library/src/main/java/com/getstream/sdk/chat/adapter/MessageListItemViewHolder.java b/library/src/main/java/com/getstream/sdk/chat/adapter/MessageListItemViewHolder.java index 37da4abacdb..755dcbf1bb5 100644 --- a/library/src/main/java/com/getstream/sdk/chat/adapter/MessageListItemViewHolder.java +++ b/library/src/main/java/com/getstream/sdk/chat/adapter/MessageListItemViewHolder.java @@ -37,8 +37,8 @@ import io.noties.markwon.core.CorePlugin; import io.noties.markwon.linkify.LinkifyPlugin; - public class MessageListItemViewHolder extends BaseMessageListItemViewHolder { + final String TAG = MessageListItemViewHolder.class.getSimpleName(); private ConstraintLayout cl_message, headerView; @@ -54,7 +54,7 @@ public class MessageListItemViewHolder extends BaseMessageListItemViewHolder { private TextView tv_username, tv_messagedate; // Delivered Indicator - private ReadStateView view_read_indicator; + private ReadStateView read_state; private TextView tv_indicator_initials, tv_read_count; private ImageView cv_indicator_avatar; private ProgressBar pb_indicator; @@ -123,7 +123,7 @@ public MessageListItemViewHolder(int resId, ViewGroup viewGroup) { alv_attachments = itemView.findViewById(R.id.cl_attachment); - view_read_indicator = itemView.findViewById(R.id.view_read_indicator); + read_state = itemView.findViewById(R.id.read_state); tv_indicator_initials = itemView.findViewById(R.id.tv_indicator_initials); tv_read_count = itemView.findViewById(R.id.tv_read_count); @@ -149,7 +149,6 @@ public void bind(Context context, ChannelState channelState, MessageListItem mes this.positions = messageListItem.getPositions(); - if (this.message.getAttachments() == null || this.message.getAttachments().size() == 0) { alv_attachments.setVisibility(View.GONE); } else { @@ -172,7 +171,6 @@ public void bind(Context context, ChannelState channelState, MessageListItem mes this.applyPositionsStyle(); - // TODO: hook up click and longclick // Configure UIs @@ -187,10 +185,11 @@ public void bind(Context context, ChannelState channelState, MessageListItem mes configParamsDeletedMessage(); configParamsUserAvatar(); configParamsReactionRecycleView(); - configPramsDeliveredIndicator(); + configParamsDeliveredIndicator(); configParamsReactionTail(); configParamsMessageDate(); configParamsReply(); + configParamsReadState(); // configParamsAttachment(); } // endregion @@ -262,7 +261,7 @@ private void configSendFailed() { if (messageClickListener != null) { String tag = TextUtils.isEmpty(message.getCommand()) ? Constant.TAG_MESSAGE_RESEND : Constant.TAG_MESSAGE_INVALID_COMMAND; v.setTag(new MessageTagModel(tag, position)); - messageClickListener.onClick(message); + messageClickListener.onMessageClick(message, position); } }); @@ -306,12 +305,11 @@ private void configMessageText() { markwon.setMarkdown(tv_text, Global.getMentionedText(message)); - // Set Click Listener tv_text.setOnClickListener((View v) -> { - Log.d(TAG, "onClick: " + position); + Log.d(TAG, "onMessageClick: " + position); if (messageClickListener != null) { - messageClickListener.onClick(message); + messageClickListener.onMessageClick(message, position); } }); @@ -368,9 +366,6 @@ private void configReplyView() { } - - - // endregion // region Layout Params @@ -419,15 +414,14 @@ private void configParamsReactionRecycleView() { } - - private void configPramsDeliveredIndicator() { + private void configParamsDeliveredIndicator() { List readBy = messageListItem.getMessageReadBy(); if (readBy.size() == 0) { - view_read_indicator.setVisibility(View.GONE); + read_state.setVisibility(View.GONE); } else { - view_read_indicator.setReads(readBy); - view_read_indicator.setVisibility(View.VISIBLE); + read_state.setVisibility(View.VISIBLE); + read_state.setReads(readBy, messageListItem.isTheirs(), style); } } @@ -493,7 +487,36 @@ private void configParamsReply() { tv_reply.setLayoutParams(paramsText); } + public void configParamsReadState(){ + if (read_state.getVisibility() != View.VISIBLE) return; + + ConstraintSet set = new ConstraintSet(); + set.clone(cl_message); + set.clear(R.id.read_state, ConstraintSet.START); + set.clear(R.id.read_state, ConstraintSet.END); + set.applyTo(cl_message); + + ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) read_state.getLayoutParams(); + + if (this.message.getAttachments() == null || this.message.getAttachments().isEmpty()) { + if (messageListItem.isMine()){ + params.endToStart = alv_attachments.getId(); + }else{ + params.startToEnd = alv_attachments.getId(); + } + }else { + if (messageListItem.isMine()){ + params.endToStart = tv_text.getId(); + }else{ + params.startToEnd = tv_text.getId(); + } + } + read_state.setLayoutParams(params); + } + public void setViewHolderFactory(MessageViewHolderFactory viewHolderFactory) { this.viewHolderFactory = viewHolderFactory; } + + } diff --git a/library/src/main/java/com/getstream/sdk/chat/adapter/ReactionDialogAdapter.java b/library/src/main/java/com/getstream/sdk/chat/adapter/ReactionDialogAdapter.java index 8d91d128844..336ccda8173 100644 --- a/library/src/main/java/com/getstream/sdk/chat/adapter/ReactionDialogAdapter.java +++ b/library/src/main/java/com/getstream/sdk/chat/adapter/ReactionDialogAdapter.java @@ -1,6 +1,7 @@ package com.getstream.sdk.chat.adapter; import android.util.Log; +import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -19,6 +20,7 @@ import com.getstream.sdk.chat.rest.response.MessageResponse; import com.getstream.sdk.chat.utils.StringUtility; import com.getstream.sdk.chat.utils.Utils; +import com.getstream.sdk.chat.view.MessageListViewStyle; import java.util.Arrays; import java.util.List; @@ -33,12 +35,14 @@ public class ReactionDialogAdapter extends RecyclerView.Adapter types = Arrays.asList("like", "love", "haha", "wow", "sad", "angry"); - + private MessageListViewStyle style; public ReactionDialogAdapter(Channel channel, Message message, boolean showAvatar, + MessageListViewStyle style, View.OnClickListener clickListener) { this.channel = channel; this.message = message; + this.style = style; this.clickListener = clickListener; this.showAvatar = showAvatar; } @@ -56,6 +60,7 @@ public MyViewHolder onCreateViewHolder(ViewGroup parent, @Override public void onBindViewHolder(final MyViewHolder holder, int position) { + applyStyle(holder); String type = types.get(position); holder.tv_emoji.setText(ReactionEmoji.valueOf(type).get()); @@ -93,6 +98,9 @@ public void onBindViewHolder(final MyViewHolder holder, int position) { holder.tv_count.setText(""); } + private void applyStyle(final MyViewHolder holder){ + holder.tv_emoji.setTextSize(TypedValue.COMPLEX_UNIT_PX, style.getReactionDlgEmojiSize()); + } @Override public int getItemCount() { return types.size(); diff --git a/library/src/main/java/com/getstream/sdk/chat/function/ReactionFunction.java b/library/src/main/java/com/getstream/sdk/chat/function/ReactionFunction.java index b1dd2b7fdbf..9583133d243 100644 --- a/library/src/main/java/com/getstream/sdk/chat/function/ReactionFunction.java +++ b/library/src/main/java/com/getstream/sdk/chat/function/ReactionFunction.java @@ -2,8 +2,10 @@ import android.app.Dialog; import android.content.Context; + import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; + import android.view.Gravity; import android.view.View; import android.view.Window; @@ -16,27 +18,18 @@ import com.getstream.sdk.chat.rest.Message; import com.getstream.sdk.chat.utils.Constant; import com.getstream.sdk.chat.utils.Utils; +import com.getstream.sdk.chat.view.MessageListViewStyle; +import com.getstream.sdk.chat.view.ReactionDlgView; public class ReactionFunction { - Channel channel; - public ReactionFunction(Channel channel){ - this.channel = channel; - } - public void showReactionDialog(Context context, Message message, int originY) { + public static void showReactionDialog(Context context, Channel channel, Message message, MessageListViewStyle style, int originY) { final Dialog dialog = new Dialog(context); // Context, this, etc. - dialog.setContentView(R.layout.dialog_reaction); + ReactionDlgView reactionDlgView = new ReactionDlgView(context); + reactionDlgView.setMessagewithStyle(channel, message, view -> dialog.dismiss(), style); + dialog.setContentView(reactionDlgView); dialog.getWindow().setBackgroundDrawableResource(android.R.color.transparent); - RecyclerView rv_reaction = dialog.findViewById(R.id.rv_reaction); - RecyclerView.LayoutManager mLayoutManager; - mLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false); - rv_reaction.setLayoutManager(mLayoutManager); - ReactionDialogAdapter reactionAdapter = new ReactionDialogAdapter(channel,message, true, (View v) -> { - dialog.dismiss(); - }); - rv_reaction.setAdapter(reactionAdapter); - dialog.show(); Window window = dialog.getWindow(); @@ -48,7 +41,7 @@ public void showReactionDialog(Context context, Message message, int originY) { window.setAttributes(wlp); } - public void showMoreActionDialog(Context context, + public static void showMoreActionDialog(Context context, Channel channel, final Message message, final View.OnClickListener clickListener) { final Dialog dialog = new Dialog(context); @@ -78,7 +71,7 @@ public void showMoreActionDialog(Context context, RecyclerView.LayoutManager mLayoutManager; mLayoutManager = new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false); rv_reaction.setLayoutManager(mLayoutManager); - ReactionDialogAdapter reactionAdapter = new ReactionDialogAdapter(channel, message, false, (View v) -> { + ReactionDialogAdapter reactionAdapter = new ReactionDialogAdapter(channel, message, false,null, (View v) -> { dialog.dismiss(); }); rv_reaction.setAdapter(reactionAdapter); diff --git a/library/src/main/java/com/getstream/sdk/chat/rest/request/UpdateMessageRequest.java b/library/src/main/java/com/getstream/sdk/chat/rest/request/UpdateMessageRequest.java index 745ac54a92a..aac0ba16c51 100644 --- a/library/src/main/java/com/getstream/sdk/chat/rest/request/UpdateMessageRequest.java +++ b/library/src/main/java/com/getstream/sdk/chat/rest/request/UpdateMessageRequest.java @@ -69,5 +69,6 @@ public UpdateMessageRequest(Message message, List attachments, List< this.message.remove("differentTime"); this.message.remove("TimeElapsed"); this.message.remove("equals"); + this.message.remove("getUserId"); } } diff --git a/library/src/main/java/com/getstream/sdk/chat/utils/BaseStyle.java b/library/src/main/java/com/getstream/sdk/chat/utils/BaseStyle.java index f9145ac5171..67b5830e771 100644 --- a/library/src/main/java/com/getstream/sdk/chat/utils/BaseStyle.java +++ b/library/src/main/java/com/getstream/sdk/chat/utils/BaseStyle.java @@ -67,6 +67,7 @@ protected final int getColor(@ColorRes int color) { } protected final Drawable getDrawable(@DrawableRes int drawable) { + if (drawable == -1) return null; return ContextCompat.getDrawable(context, drawable); } @@ -74,27 +75,35 @@ protected final Drawable getVectorDrawable(@DrawableRes int drawable) { return ContextCompat.getDrawable(context, drawable); } + protected int avatarWidth; + protected int avatarHeight; - protected float avatarWidth; - protected float avatarHeight; - - protected float avatarBorderWidth; + protected int avatarBorderWidth; protected int avatarBorderColor; protected int avatarBackGroundColor; - protected float avatarInitialTextSize; + protected int avatarInitialTextSize; protected int avatarInitialTextColor; protected int avatarInitialTextStyle; - public float getAvatarWidth() { + protected boolean showReadState; + + protected int readStateAvatarWidth; + protected int readStateAvatarHeight; + + protected int readStateTextSize; + protected int readStateTextColor; + protected int readStateTextStyle; + + public int getAvatarWidth() { return avatarWidth; } - public float getAvatarHeight() { + public int getAvatarHeight() { return avatarHeight; } - public float getAvatarInitialTextSize() { + public int getAvatarInitialTextSize() { return avatarInitialTextSize; } @@ -106,7 +115,7 @@ public int getAvatarInitialTextStyle() { return avatarInitialTextStyle; } - public float getAvatarBorderWidth() { + public int getAvatarBorderWidth() { return avatarBorderWidth; } @@ -117,4 +126,28 @@ public int getAvatarBorderColor() { public int getAvatarBackGroundColor() { return avatarBackGroundColor; } + + public boolean isShowReadState() { + return showReadState; + } + + public int getReadStateAvatarWidth() { + return readStateAvatarWidth; + } + + public int getReadStateAvatarHeight() { + return readStateAvatarHeight; + } + + public int getReadStateTextSize() { + return readStateTextSize; + } + + public int getReadStateTextColor() { + return readStateTextColor; + } + + public int getReadStateTextStyle() { + return readStateTextStyle; + } } diff --git a/library/src/main/java/com/getstream/sdk/chat/utils/Utils.java b/library/src/main/java/com/getstream/sdk/chat/utils/Utils.java index a95e69a1ac5..0b3846c33a5 100644 --- a/library/src/main/java/com/getstream/sdk/chat/utils/Utils.java +++ b/library/src/main/java/com/getstream/sdk/chat/utils/Utils.java @@ -3,11 +3,14 @@ import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; +import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Handler; import android.provider.MediaStore; + import androidx.core.graphics.drawable.RoundedBitmapDrawable; import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory; + import android.util.DisplayMetrics; import android.view.Display; import android.view.View; @@ -23,6 +26,8 @@ import java.io.InputStream; import java.util.Scanner; +import top.defaults.drawabletoolbox.DrawableBuilder; + public class Utils { public static String TAG = "Utils"; @@ -75,8 +80,30 @@ public static int getScreenResolution(Context context) { return height; } - public static void setButtonDelayEnable(View v){ + public static void setButtonDelayEnable(View v) { v.setEnabled(false); new Handler().postDelayed(() -> v.setEnabled(true), 1000); } + + public static Drawable getDrawable(boolean isRect, int strokeColor, int strokeWidth, int solidColor, int topLeftRadius, int topRightRadius ) { + if (isRect) + return new DrawableBuilder() + .rectangle() + .strokeColor(strokeColor) + .strokeWidth(strokeWidth) + .solidColor(solidColor) + .cornerRadii(0, 0, 20, 20) // the same as the two lines above + .build(); + else + return new DrawableBuilder() + .oval() + .strokeColor(0) + .strokeWidth(0) + .cornerRadii(0, 0, 0, 0) + .solidColor(0) + .build(); + + } + + } diff --git a/library/src/main/java/com/getstream/sdk/chat/view/AttachmentListView.java b/library/src/main/java/com/getstream/sdk/chat/view/AttachmentListView.java index a297571d796..95b83db2712 100644 --- a/library/src/main/java/com/getstream/sdk/chat/view/AttachmentListView.java +++ b/library/src/main/java/com/getstream/sdk/chat/view/AttachmentListView.java @@ -12,7 +12,6 @@ import com.getstream.sdk.chat.adapter.MessageViewHolderFactory; import com.getstream.sdk.chat.rest.Message; - public class AttachmentListView extends RecyclerView { final String TAG = AttachmentListView.class.getSimpleName(); private MessageViewHolderFactory viewHolderFactory; diff --git a/library/src/main/java/com/getstream/sdk/chat/view/AvatarGroupView.java b/library/src/main/java/com/getstream/sdk/chat/view/AvatarGroupView.java index f53f3d6b534..773aea6fc68 100644 --- a/library/src/main/java/com/getstream/sdk/chat/view/AvatarGroupView.java +++ b/library/src/main/java/com/getstream/sdk/chat/view/AvatarGroupView.java @@ -67,7 +67,7 @@ private void configUIs() { params.height = (int) style.getAvatarHeight(); this.setLayoutParams(params); - this.removeAllViews(); + removeAllViews(); if (user != null) { configAvatar(user.getImage(), user.getInitials()); } else if (!TextUtils.isEmpty(channel.getImage())) { diff --git a/library/src/main/java/com/getstream/sdk/chat/view/ChannelHeaderView.java b/library/src/main/java/com/getstream/sdk/chat/view/ChannelHeaderView.java index dd175d78a7b..8fc034c224c 100644 --- a/library/src/main/java/com/getstream/sdk/chat/view/ChannelHeaderView.java +++ b/library/src/main/java/com/getstream/sdk/chat/view/ChannelHeaderView.java @@ -55,7 +55,7 @@ public void setViewModel(ChannelViewModel model, LifecycleOwner lifecycleOwner) private ToolbarChannelHeaderBinding initBinding(Context context) { LayoutInflater inflater = LayoutInflater.from(context); binding = ToolbarChannelHeaderBinding.inflate(inflater, this, true); - // setup the onClick listener for the back button + // setup the onMessageClick listener for the back button binding.tvBack.setOnClickListener(this); return binding; } diff --git a/library/src/main/java/com/getstream/sdk/chat/view/ChannelHeaderViewStyle.java b/library/src/main/java/com/getstream/sdk/chat/view/ChannelHeaderViewStyle.java index acd7e504ac0..06ee704adb4 100644 --- a/library/src/main/java/com/getstream/sdk/chat/view/ChannelHeaderViewStyle.java +++ b/library/src/main/java/com/getstream/sdk/chat/view/ChannelHeaderViewStyle.java @@ -37,14 +37,14 @@ public ChannelHeaderViewStyle(Context c, AttributeSet attrs) { // Back Button Show/Hide backButtonShow = a.getBoolean(R.styleable.ChannelHeaderView_backButtonShow, false); // Avatar - avatarWidth = a.getDimension(R.styleable.ChannelHeaderView_channelHeaderAvatarWidth, getDimension(R.dimen.stream_channel_avatar_width)); - avatarHeight = a.getDimension(R.styleable.ChannelHeaderView_channelHeaderAvatarHeight, getDimension(R.dimen.stream_channel_avatar_height)); + avatarWidth = a.getDimensionPixelSize(R.styleable.ChannelHeaderView_channelHeaderAvatarWidth, getDimension(R.dimen.stream_channel_avatar_width)); + avatarHeight = a.getDimensionPixelSize(R.styleable.ChannelHeaderView_channelHeaderAvatarHeight, getDimension(R.dimen.stream_channel_avatar_height)); - avatarBorderWidth = a.getDimension(R.styleable.ChannelHeaderView_channelHeaderAvatarBorderWidth, getDimension(R.dimen.stream_channel_avatar_border_width)); + avatarBorderWidth = a.getDimensionPixelSize(R.styleable.ChannelHeaderView_channelHeaderAvatarBorderWidth, getDimension(R.dimen.stream_channel_avatar_border_width)); avatarBorderColor = a.getColor(R.styleable.ChannelHeaderView_channelHeaderAvatarBorderColor, Color.WHITE); avatarBackGroundColor = a.getColor(R.styleable.ChannelHeaderView_channelHeaderAvatarBackGroundColor, getColor(R.color.stream_gray_dark)); - avatarInitialTextSize = a.getDimension(R.styleable.ChannelHeaderView_channelHeaderAvatarTextSize, getDimension(R.dimen.stream_channel_initials)); + avatarInitialTextSize = a.getDimensionPixelSize(R.styleable.ChannelHeaderView_channelHeaderAvatarTextSize, getDimension(R.dimen.stream_channel_initials)); avatarInitialTextColor = a.getColor(R.styleable.ChannelHeaderView_channelHeaderAvatarTextColor, Color.WHITE); avatarInitialTextStyle = a.getInt(R.styleable.ChannelHeaderView_channelHeaderAvatarTextStyle, Typeface.BOLD); diff --git a/library/src/main/java/com/getstream/sdk/chat/view/ChannelListViewStyle.java b/library/src/main/java/com/getstream/sdk/chat/view/ChannelListViewStyle.java index 41e65980fb8..99a9b7a7f01 100644 --- a/library/src/main/java/com/getstream/sdk/chat/view/ChannelListViewStyle.java +++ b/library/src/main/java/com/getstream/sdk/chat/view/ChannelListViewStyle.java @@ -59,16 +59,24 @@ public ChannelListViewStyle(Context c, AttributeSet attrs) { channelPreviewLayout = a.getResourceId(R.styleable.ChannelListView_channelPreviewLayout, R.layout.list_item_channel); // Avatar - avatarWidth = a.getDimension(R.styleable.ChannelListView_channelAvatarWidth, getDimension(R.dimen.stream_channel_avatar_width)); - avatarHeight = a.getDimension(R.styleable.ChannelListView_channelAvatarHeight, getDimension(R.dimen.stream_channel_avatar_height)); + avatarWidth = a.getDimensionPixelSize(R.styleable.ChannelListView_channelAvatarWidth, getDimension(R.dimen.stream_channel_avatar_width)); + avatarHeight = a.getDimensionPixelSize(R.styleable.ChannelListView_channelAvatarHeight, getDimension(R.dimen.stream_channel_avatar_height)); - avatarBorderWidth = a.getDimension(R.styleable.ChannelListView_channelAvatarBorderWidth, getDimension(R.dimen.stream_channel_avatar_border_width)); - avatarBorderColor = a.getColor(R.styleable.ChannelListView_channelAvatarBorderColor, -1); - avatarBackGroundColor = a.getColor(R.styleable.ChannelListView_channelAvatarBackGroundColor, getColor(R.color.stream_gray_dark)); + avatarBorderWidth = a.getDimensionPixelSize(R.styleable.ChannelListView_channelAvatarBorderWidth, getDimension(R.dimen.stream_channel_avatar_border_width)); + avatarBorderColor = a.getColor(R.styleable.ChannelListView_channelAvatarBorderColor, Color.WHITE); + avatarBackGroundColor = a.getColor(R.styleable.ChannelListView_channelAvatarBackGroundColor, getColor(R.color.user_intials_background)); - avatarInitialTextSize = a.getDimension(R.styleable.ChannelListView_channelAvatarTextSize, getDimension(R.dimen.stream_channel_initials)); - avatarInitialTextColor = a.getColor(R.styleable.ChannelListView_channelAvatarTextColor, Color.WHITE); + avatarInitialTextSize = a.getDimensionPixelSize(R.styleable.ChannelListView_channelAvatarTextSize, getDimension(R.dimen.stream_channel_initials)); + avatarInitialTextColor = a.getColor(R.styleable.ChannelListView_channelAvatarTextColor, Color.BLACK); avatarInitialTextStyle = a.getInt(R.styleable.ChannelListView_channelAvatarTextStyle, Typeface.BOLD); + // Read State + showReadState = a.getBoolean(R.styleable.ChannelListView_channelShowReadState, true); + readStateAvatarWidth = a.getDimensionPixelSize(R.styleable.ChannelListView_channelReadStateAvatarWidth, getDimension(R.dimen.read_state_avatar_width)); + readStateAvatarHeight = a.getDimensionPixelSize(R.styleable.ChannelListView_channelReadStateAvatarHeight, getDimension(R.dimen.read_state_avatar_height)); + + readStateTextSize = a.getDimensionPixelSize(R.styleable.ChannelListView_channelRreadStateTextSize, getDimension(R.dimen.read_state_text_size)); + readStateTextColor = a.getColor(R.styleable.ChannelListView_channelReadStateTextColor, Color.BLACK); + readStateTextStyle = a.getColor(R.styleable.ChannelListView_channelReadStateTextStyle, Typeface.NORMAL); a.recycle(); } diff --git a/library/src/main/java/com/getstream/sdk/chat/view/MessageInputView.java b/library/src/main/java/com/getstream/sdk/chat/view/MessageInputView.java index 11c0818255c..333052c43da 100644 --- a/library/src/main/java/com/getstream/sdk/chat/view/MessageInputView.java +++ b/library/src/main/java/com/getstream/sdk/chat/view/MessageInputView.java @@ -26,7 +26,6 @@ import com.getstream.sdk.chat.databinding.ViewMessageInputBinding; import com.getstream.sdk.chat.enums.InputType; import com.getstream.sdk.chat.function.SendFileFunction; -import com.getstream.sdk.chat.model.Attachment; import com.getstream.sdk.chat.rest.Message; import com.getstream.sdk.chat.rest.interfaces.MessageCallback; import com.getstream.sdk.chat.rest.response.MessageResponse; @@ -212,6 +211,7 @@ private void initAttachmentUI() { // endregion public void progressCapturedMedia(int requestCode, int resultCode, Intent data) { if (requestCode == Constant.CAPTURE_IMAGE_REQUEST_CODE) { + if (data == null) return; try { Object object = data.getExtras().get("data"); if (object.getClass().equals(Bitmap.class)) { diff --git a/library/src/main/java/com/getstream/sdk/chat/view/MessageListView.java b/library/src/main/java/com/getstream/sdk/chat/view/MessageListView.java index 58c473f04e8..cfe32f963b5 100644 --- a/library/src/main/java/com/getstream/sdk/chat/view/MessageListView.java +++ b/library/src/main/java/com/getstream/sdk/chat/view/MessageListView.java @@ -14,6 +14,7 @@ import com.getstream.sdk.chat.adapter.MessageListItem; import com.getstream.sdk.chat.adapter.MessageListItemAdapter; import com.getstream.sdk.chat.adapter.MessageViewHolderFactory; +import com.getstream.sdk.chat.function.ReactionFunction; import com.getstream.sdk.chat.model.Attachment; import com.getstream.sdk.chat.model.Channel; import com.getstream.sdk.chat.rest.Message; @@ -22,7 +23,6 @@ import java.util.List; - /** * MessageListView renders a list of messages and extends the RecyclerView * The most common customizations are @@ -48,6 +48,9 @@ public class MessageListView extends RecyclerView { private boolean hasScrolledUp; private BubbleHelper bubbleHelper; + private ReactionFunction reactionFunction; + + // region Constructor public MessageListView(Context context) { super(context); this.setLayoutManager(new LinearLayoutManager(context)); @@ -70,6 +73,13 @@ public MessageListView(Context context, @Nullable AttributeSet attrs, int defSty hasScrolledUp = false; initDefaultBubbleHelper(); } + // endregion + + // region Init + private void parseAttr(Context context, @Nullable AttributeSet attrs) { + // parse the attributes + style = new MessageListViewStyle(context, attrs); + } public void initDefaultBubbleHelper() { this.setBubbleHelper(new BubbleHelper() { @@ -107,16 +117,55 @@ public Drawable getDrawableForAttachment(Message message, Boolean mine, List { + int firstListItemPosition = ((LinearLayoutManager) this.getLayoutManager()).findFirstVisibleItemPosition(); + final int lastListItemPosition = firstListItemPosition + this.getChildCount() - 1; + int childIndex; + if (position < firstListItemPosition || position > lastListItemPosition) { + childIndex = position; + } else { + childIndex = position - firstListItemPosition; + } + int originY = this.getChildAt(childIndex).getBottom(); + ReactionFunction.showReactionDialog(getContext(),viewModel.getChannel(),message, style, originY); + }); + } + this.addOnScrollListener(new RecyclerView.OnScrollListener() { + + @Override + public void onScrolled(RecyclerView recyclerView, int dx, int dy) { + super.onScrolled(recyclerView, dx, dy); + + LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); + + if (linearLayoutManager != null) { + firstVisible = linearLayoutManager.findFirstVisibleItemPosition(); + lastVisible = linearLayoutManager.findLastVisibleItemPosition(); + hasScrolledUp = lastVisible < (adapter.getItemCount() - 3); + if (!hasScrolledUp) { + viewModel.setHasNewMessages(false); + } + Boolean reachedTheBeginning = firstVisible <= 2; + Log.i(TAG, String.format("Scroll: First visible is %d last visible is %s", firstVisible, lastVisible)); + if (reachedTheBeginning) { + viewModel.loadMore(); + } + } + } + }); - @Override - public void setAdapter(Adapter adapter) { - throw new IllegalArgumentException("Use setAdapterWithStyle instead please"); } public void setViewModel(ChannelViewModel viewModel, LifecycleOwner lifecycleOwner) { @@ -161,7 +210,7 @@ public void setViewModel(ChannelViewModel viewModel, LifecycleOwner lifecycleOwn Log.i(TAG, String.format("Scroll: Moving down")); if (!hasScrolledUp) { - this.getLayoutManager().scrollToPosition(adapter.getItemCount()-1); + this.getLayoutManager().scrollToPosition(adapter.getItemCount() - 1); viewModel.setHasNewMessages(false); } else { viewModel.setHasNewMessages(true); @@ -173,49 +222,21 @@ public void setViewModel(ChannelViewModel viewModel, LifecycleOwner lifecycleOwn this.setAdapterWithStyle(adapter); } - // set the adapter and apply the style. - public void setAdapterWithStyle(MessageListItemAdapter adapter) { - super.setAdapter(adapter); - adapter.setStyle(style); - - - if (this.attachmentClickListener != null) { - adapter.setAttachmentClickListener(this.attachmentClickListener); - } - if (this.messageClickListener != null) { - this.adapter.setMessageClickListener(this.messageClickListener); + public void setViewHolderFactory(MessageViewHolderFactory factory) { + this.viewHolderFactory = factory; + if (this.adapter != null) { + this.adapter.setFactory(factory); } - this.addOnScrollListener(new RecyclerView.OnScrollListener() { - - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - super.onScrolled(recyclerView, dx, dy); - - LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); - - if (linearLayoutManager != null) { - firstVisible = linearLayoutManager.findFirstVisibleItemPosition(); - lastVisible = linearLayoutManager.findLastVisibleItemPosition(); - hasScrolledUp = lastVisible < (adapter.getItemCount() -3); - if (!hasScrolledUp) { - viewModel.setHasNewMessages(false); - } - Boolean reachedTheBeginning = firstVisible <= 2; - Log.i(TAG, String.format("Scroll: First visible is %d last visible is %s", firstVisible, lastVisible)); - if (reachedTheBeginning) { - viewModel.loadMore(); - } - } - } - }); - } - private void parseAttr(Context context, @Nullable AttributeSet attrs) { - // parse the attributes - style = new MessageListViewStyle(context, attrs); + @Override + public void setAdapter(Adapter adapter) { + throw new IllegalArgumentException("Use setAdapterWithStyle instead please"); } + // endregion + + // region Listener public void setAttachmentClickListener(AttachmentClickListener attachmentClickListener) { this.attachmentClickListener = attachmentClickListener; if (this.adapter != null) { @@ -238,15 +259,17 @@ public void setBubbleHelper(BubbleHelper bubbleHelper) { } public interface MessageClickListener { - void onClick(Message message); + void onMessageClick(Message message, int position); } public interface BubbleHelper { Drawable getDrawableForMessage(Message message, Boolean mine, List positions); + Drawable getDrawableForAttachment(Message message, Boolean mine, List positions, Attachment attachment); } public interface AttachmentClickListener { - void onClick(Message message, Attachment attachment); + void onAttachmentClick(Message message, Attachment attachment); } + // endregion } \ No newline at end of file diff --git a/library/src/main/java/com/getstream/sdk/chat/view/MessageListViewStyle.java b/library/src/main/java/com/getstream/sdk/chat/view/MessageListViewStyle.java index 3ef1d41877e..dd7a97dae50 100644 --- a/library/src/main/java/com/getstream/sdk/chat/view/MessageListViewStyle.java +++ b/library/src/main/java/com/getstream/sdk/chat/view/MessageListViewStyle.java @@ -14,38 +14,60 @@ public class MessageListViewStyle extends BaseStyle { final String TAG = MessageListViewStyle.class.getSimpleName(); - // Dimension + // Dimension private int messageTextColorMine; private int messageTextColorTheirs; // Drawable private Drawable messageBubbleDrawableMine; private Drawable messageBubbleDrawableTheirs; - + // Reaction + private boolean showReactionDlg; + private boolean showUsersReactionDlg; + private Drawable reactionDlgBgDrawable; + private int reactionDlgBgColor; + private int reactionDlgEmojiSize; + private int reactionDlgEmojiMargin; public MessageListViewStyle(Context c, AttributeSet attrs) { // parse the attributes setContext(c); - TypedArray a = this.getContext().obtainStyledAttributes(attrs, R.styleable.MessageListView, 0, 0); + messageTextColorMine = a.getColor(R.styleable.MessageListView_messageTextColorMine, Color.BLACK); messageTextColorTheirs = a.getColor(R.styleable.MessageListView_messageTextColorTheirs, Color.BLACK); messageBubbleDrawableMine = getDrawable(a.getResourceId(R.styleable.MessageListView_messageBubbleDrawableMine, R.drawable.message_bubble_mine)); messageBubbleDrawableTheirs = getDrawable(a.getResourceId(R.styleable.MessageListView_messageBubbleDrawableTheirs, R.drawable.message_bubble_theirs)); + // Reaction Dialog + showReactionDlg = a.getBoolean(R.styleable.MessageListView_showReactionDlg, true); + showUsersReactionDlg = a.getBoolean(R.styleable.MessageListView_showUsersReactionDlg, true); + reactionDlgBgDrawable = getDrawable(a.getResourceId(R.styleable.MessageListView_reactionDlgBgDrawable, -1)); + reactionDlgBgColor = a.getColor(R.styleable.MessageListView_reactionDlgbgColor, getColor(R.color.reaction_dialog_background)); + reactionDlgEmojiSize = a.getDimensionPixelSize(R.styleable.MessageListView_reactionDlgEmojiSize, getDimension(R.dimen.reaction_dialog_emoji_size)); + reactionDlgEmojiMargin = a.getDimensionPixelSize(R.styleable.MessageListView_reactionDlgEmojiMargin, getDimension(R.dimen.reaction_dialog_emoji_margin)); // Avatar - avatarWidth = a.getDimension(R.styleable.MessageListView_userAvatarWidth, getDimension(R.dimen.message_avatar_width)); - avatarHeight = a.getDimension(R.styleable.MessageListView_userAvatarHeight, getDimension(R.dimen.message_avatar_height)); + avatarWidth = a.getDimensionPixelSize(R.styleable.MessageListView_userAvatarWidth, getDimension(R.dimen.message_avatar_width)); + avatarHeight = a.getDimensionPixelSize(R.styleable.MessageListView_userAvatarHeight, getDimension(R.dimen.message_avatar_height)); - avatarBorderWidth = a.getDimension(R.styleable.MessageListView_userAvatarBorderWidth, getDimension(R.dimen.stream_channel_avatar_border_width)); + avatarBorderWidth = a.getDimensionPixelSize(R.styleable.MessageListView_userAvatarBorderWidth, getDimension(R.dimen.stream_channel_avatar_border_width)); avatarBorderColor = a.getColor(R.styleable.MessageListView_userAvatarBorderColor, Color.WHITE); avatarBackGroundColor = a.getColor(R.styleable.MessageListView_userAvatarBackGroundColor, getColor(R.color.stream_gray_dark)); - avatarInitialTextSize = a.getDimension(R.styleable.MessageListView_userAvatarTextSize, getDimension(R.dimen.stream_channel_initials)); + avatarInitialTextSize = a.getDimensionPixelSize(R.styleable.MessageListView_userAvatarTextSize, getDimension(R.dimen.stream_channel_initials)); avatarInitialTextColor = a.getColor(R.styleable.MessageListView_userAvatarTextColor, Color.WHITE); avatarInitialTextStyle = a.getInt(R.styleable.MessageListView_userAvatarTextStyle, Typeface.BOLD); + // Read State + showReadState = a.getBoolean(R.styleable.MessageListView_userShowReadState, true); + readStateAvatarWidth = a.getDimensionPixelSize(R.styleable.MessageListView_userReadStateAvatarWidth, getDimension(R.dimen.read_state_avatar_width)); + readStateAvatarHeight = a.getDimensionPixelSize(R.styleable.MessageListView_userReadStateAvatarHeight, getDimension(R.dimen.read_state_avatar_height)); + + readStateTextSize = a.getDimensionPixelSize(R.styleable.MessageListView_userRreadStateTextSize, getDimension(R.dimen.read_state_text_size)); + readStateTextColor = a.getColor(R.styleable.MessageListView_userReadStateTextColor, Color.BLACK); + readStateTextStyle = a.getColor(R.styleable.MessageListView_userReadStateTextStyle, Typeface.NORMAL); + a.recycle(); } @@ -83,4 +105,30 @@ public Drawable getMessageBubbleDrawableTheirs() { public void setMessageBubbleDrawableTheirs(Drawable messageBubbleDrawableTheirs) { this.messageBubbleDrawableTheirs = messageBubbleDrawableTheirs; } + + // Reaction Dialog + + public boolean isShowReactionDlg() { + return showReactionDlg; + } + + public boolean isShowUsersReactionDlg() { + return showUsersReactionDlg; + } + + public Drawable getReactionDlgBgDrawable() { + return reactionDlgBgDrawable; + } + + public int getReactionDlgBgColor() { + return reactionDlgBgColor; + } + + public int getReactionDlgEmojiSize() { + return reactionDlgEmojiSize; + } + + public int getReactionDlgEmojiMargin() { + return reactionDlgEmojiMargin; + } } \ No newline at end of file diff --git a/library/src/main/java/com/getstream/sdk/chat/view/ReactionDlgView.java b/library/src/main/java/com/getstream/sdk/chat/view/ReactionDlgView.java new file mode 100644 index 00000000000..2b18e658239 --- /dev/null +++ b/library/src/main/java/com/getstream/sdk/chat/view/ReactionDlgView.java @@ -0,0 +1,81 @@ +package com.getstream.sdk.chat.view; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.RelativeLayout; + +import androidx.annotation.DimenRes; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.getstream.sdk.chat.R; +import com.getstream.sdk.chat.adapter.ReactionDialogAdapter; +import com.getstream.sdk.chat.model.Channel; +import com.getstream.sdk.chat.rest.Message; + +import top.defaults.drawabletoolbox.DrawableBuilder; + +public class ReactionDlgView extends RelativeLayout { + + final String TAG = ReactionDlgView.class.getSimpleName(); + MessageListViewStyle style; + + public ReactionDlgView(Context context) { + super(context); + initView(); + + } + + public ReactionDlgView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + initView(); + } + + public ReactionDlgView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + initView(); + } + + public void setMessagewithStyle(Channel channel, Message message, + View.OnClickListener clickListener, + MessageListViewStyle style) { + this.style = style; + init(channel, message, clickListener); + } + + private void initView() { + View view = inflate(getContext(), R.layout.dialog_reaction, null); + addView(view); + } + + private void init(Channel channel, Message message, View.OnClickListener clickListener) { + RecyclerView rv_reaction = this.findViewById(R.id.rv_reaction); + ImageView iv_bg = this.findViewById(R.id.iv_bg); + + RecyclerView.LayoutManager mLayoutManager; + mLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false); + rv_reaction.setLayoutManager(mLayoutManager); + ReactionDialogAdapter reactionAdapter = new ReactionDialogAdapter(channel, message, + style.isShowUsersReactionDlg(), style, clickListener); + rv_reaction.setAdapter(reactionAdapter); + + if (style.getReactionDlgBgDrawable() != null) { + this.setBackground(style.getReactionDlgBgDrawable()); + iv_bg.setBackgroundResource(0); + } else { + @DimenRes int conerRadius = R.dimen.reaction_dialog_corner_radius; + Drawable drawable = new DrawableBuilder() + .rectangle() + .strokeColor(0) + .strokeWidth(0) + .solidColor(style.getReactionDlgBgColor()) + .cornerRadii(conerRadius, conerRadius, conerRadius, conerRadius) // the same as the two lines above + .build(); + iv_bg.setBackground(drawable); + } + } +} diff --git a/library/src/main/java/com/getstream/sdk/chat/view/ReadStateView.java b/library/src/main/java/com/getstream/sdk/chat/view/ReadStateView.java index 545e042fa0a..005862ad11b 100644 --- a/library/src/main/java/com/getstream/sdk/chat/view/ReadStateView.java +++ b/library/src/main/java/com/getstream/sdk/chat/view/ReadStateView.java @@ -1,48 +1,104 @@ package com.getstream.sdk.chat.view; +import android.annotation.SuppressLint; import android.content.Context; +import android.graphics.Typeface; import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.Gravity; +import android.widget.RelativeLayout; +import android.widget.TextView; -import androidx.appcompat.widget.AppCompatImageView; - +import com.bumptech.glide.Glide; +import com.getstream.sdk.chat.R; import com.getstream.sdk.chat.rest.User; import com.getstream.sdk.chat.rest.response.ChannelUserRead; -import com.getstream.sdk.chat.utils.Utils; +import com.getstream.sdk.chat.utils.BaseStyle; +import com.getstream.sdk.chat.utils.roundedImageView.CircularImageView; import java.util.Collections; import java.util.List; -public class ReadStateView extends AppCompatImageView { +public class ReadStateView