diff --git a/build.gradle b/build.gradle index 80103afe..bce8b443 100644 --- a/build.gradle +++ b/build.gradle @@ -10,8 +10,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.1.3' - classpath 'com.novoda:bintray-release:0.8.0' + classpath 'com.android.tools.build:gradle:4.1.3' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/chatkit/build.gradle b/chatkit/build.gradle index f9b50b7f..9512c7eb 100644 --- a/chatkit/build.gradle +++ b/chatkit/build.gradle @@ -1,9 +1,8 @@ apply plugin: 'com.android.library' -apply plugin: 'com.novoda.bintray-release' + android { - compileSdkVersion 27 - buildToolsVersion "27.0.3" + compileSdkVersion 30 defaultConfig { minSdkVersion 14 @@ -18,16 +17,6 @@ android { } } -publish { - groupId = 'com.github.stfalcon' - artifactId = 'chatkit' - publishVersion = '0.3.3' - desc = 'ChatKit - is a library designed to simplify the development of UI for such a trivial task as chat. It have flexible possibilities for styling, customizing and data management' - licences = ['Apache-2.0'] - uploadName = 'ChatKit' - website = 'https://github.com/stfalcon-studio/ChatKit.git' -} - ext { supportVersion = '27.1.1' flexboxVersion = '1.0.0' @@ -36,7 +25,7 @@ ext { dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) - implementation "com.android.support:appcompat-v7:$supportVersion" - implementation "com.android.support:design:$supportVersion" + implementation 'androidx.appcompat:appcompat:1.2.0' + implementation 'com.google.android.material:material:1.0.0' implementation "com.google.android:flexbox:$flexboxVersion" } diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/commons/ImageLoader.java b/chatkit/src/main/java/com/stfalcon/chatkit/commons/ImageLoader.java index a0f7f44f..9043cb6c 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/commons/ImageLoader.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/commons/ImageLoader.java @@ -16,7 +16,7 @@ package com.stfalcon.chatkit.commons; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import android.widget.ImageView; /** diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/commons/Style.java b/chatkit/src/main/java/com/stfalcon/chatkit/commons/Style.java index fcbd8a77..80489b71 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/commons/Style.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/commons/Style.java @@ -20,11 +20,11 @@ import android.content.res.Resources; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; -import android.support.annotation.AttrRes; -import android.support.annotation.ColorRes; -import android.support.annotation.DimenRes; -import android.support.annotation.DrawableRes; -import android.support.v4.content.ContextCompat; +import androidx.annotation.AttrRes; +import androidx.annotation.ColorRes; +import androidx.annotation.DimenRes; +import androidx.annotation.DrawableRes; +import androidx.core.content.ContextCompat; import android.util.AttributeSet; import android.util.TypedValue; diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/commons/ViewHolder.java b/chatkit/src/main/java/com/stfalcon/chatkit/commons/ViewHolder.java index dff3193c..e5451012 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/commons/ViewHolder.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/commons/ViewHolder.java @@ -16,7 +16,7 @@ package com.stfalcon.chatkit.commons; -import android.support.v7.widget.RecyclerView; +import androidx.recyclerview.widget.RecyclerView; import android.view.View; /** diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/commons/models/IMessage.java b/chatkit/src/main/java/com/stfalcon/chatkit/commons/models/IMessage.java index 4605aab3..52beca0e 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/commons/models/IMessage.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/commons/models/IMessage.java @@ -50,4 +50,5 @@ public interface IMessage { * @return the message creation date */ Date getCreatedAt(); + } diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/commons/models/MessageContentType.java b/chatkit/src/main/java/com/stfalcon/chatkit/commons/models/MessageContentType.java index b8f2675a..8737d5c0 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/commons/models/MessageContentType.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/commons/models/MessageContentType.java @@ -16,7 +16,7 @@ package com.stfalcon.chatkit.commons.models; -import android.support.annotation.Nullable; +import androidx.annotation.Nullable; import com.stfalcon.chatkit.messages.MessageHolders; /* diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogsList.java b/chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogsList.java index 6336203d..4bb5ff75 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogsList.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogsList.java @@ -17,11 +17,11 @@ package com.stfalcon.chatkit.dialogs; import android.content.Context; -import android.support.annotation.Nullable; -import android.support.v7.widget.DefaultItemAnimator; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.SimpleItemAnimator; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.SimpleItemAnimator; import android.util.AttributeSet; import com.stfalcon.chatkit.commons.models.IDialog; diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogsListAdapter.java b/chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogsListAdapter.java index dc48e7f0..6f255ca9 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogsListAdapter.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/dialogs/DialogsListAdapter.java @@ -18,9 +18,9 @@ import android.graphics.Typeface; import android.graphics.drawable.GradientDrawable; -import android.support.annotation.LayoutRes; -import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; +import androidx.annotation.LayoutRes; +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.RecyclerView; import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageHolders.java b/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageHolders.java index c089cbdf..f367647a 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageHolders.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageHolders.java @@ -1,8 +1,9 @@ package com.stfalcon.chatkit.messages; -import android.support.annotation.LayoutRes; -import android.support.annotation.NonNull; -import android.support.v4.view.ViewCompat; +import androidx.annotation.LayoutRes; +import androidx.annotation.NonNull; +import androidx.core.view.ViewCompat; + import android.text.Spannable; import android.text.method.LinkMovementMethod; import android.util.SparseArray; @@ -564,6 +565,7 @@ protected ViewHolder getHolder(ViewGroup parent, int viewType, MessagesListStyle @SuppressWarnings("unchecked") protected void bind(final ViewHolder holder, final Object item, boolean isSelected, + boolean isContinuous, boolean isLastItemInGroup, final ImageLoader imageLoader, final View.OnClickListener onMessageClickListener, final View.OnLongClickListener onMessageLongClickListener, @@ -573,6 +575,8 @@ protected void bind(final ViewHolder holder, final Object item, boolean isSelect if (item instanceof IMessage) { ((MessageHolders.BaseMessageViewHolder) holder).isSelected = isSelected; ((MessageHolders.BaseMessageViewHolder) holder).imageLoader = imageLoader; + ((BaseMessageViewHolder) holder).isFirstItemInGroup = isContinuous; + ((BaseMessageViewHolder) holder).isLastItemInGroup = isLastItemInGroup; holder.itemView.setOnLongClickListener(onMessageLongClickListener); holder.itemView.setOnClickListener(onMessageClickListener); @@ -676,6 +680,9 @@ public static abstract class BaseMessageViewHolder ext boolean isSelected; + boolean isFirstItemInGroup; + + boolean isLastItemInGroup; /** * For setting custom data to ViewHolder */ @@ -705,6 +712,31 @@ public boolean isSelected() { return isSelected; } + /** + * Returns whether item belongs to the same user + * + * @return weather item belongs to the same user. + */ + public boolean isFirstItemInGroup() { + return isFirstItemInGroup; + } + + /** + * Returns whether the current item and the next belongs to the same user + */ + public boolean isLastItemInGroup() { + return isLastItemInGroup; + } + + public List getVisibleViewsForFirstItemInGroup() { + return new ArrayList<>(); + } + + public List getVisibleViewsForLastItemInGroup() { + return new ArrayList<>(); + } + + /** * Returns weather is selection mode enabled * @@ -769,6 +801,26 @@ public void onBind(MESSAGE message) { if (text != null) { text.setText(message.getText()); } + + if (isLastItemInGroup()) { + for (View continousView : getVisibleViewsForLastItemInGroup()) { + continousView.setVisibility(View.VISIBLE); + } + } else { + for (View continousView : getVisibleViewsForLastItemInGroup()) { + continousView.setVisibility(View.GONE); + } + } + + if (isFirstItemInGroup()) { + for (View continousView : getVisibleViewsForFirstItemInGroup()) { + continousView.setVisibility(View.VISIBLE); + } + } else { + for (View continousView : getVisibleViewsForFirstItemInGroup()) { + continousView.setVisibility(View.INVISIBLE); + } + } } @Override @@ -828,6 +880,26 @@ public void onBind(MESSAGE message) { if (text != null) { text.setText(message.getText()); } + + if (isLastItemInGroup()) { + for (View continousView : getVisibleViewsForLastItemInGroup()) { + continousView.setVisibility(View.VISIBLE); + } + } else { + for (View continousView : getVisibleViewsForLastItemInGroup()) { + continousView.setVisibility(View.GONE); + } + } + + if (isFirstItemInGroup()) { + for (View continousView : getVisibleViewsForFirstItemInGroup()) { + continousView.setVisibility(View.VISIBLE); + } + } else { + for (View continousView : getVisibleViewsForFirstItemInGroup()) { + continousView.setVisibility(View.INVISIBLE); + } + } } @Override diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageInput.java b/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageInput.java index 16e42a35..80383041 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageInput.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageInput.java @@ -19,8 +19,8 @@ import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.v4.view.ViewCompat; -import android.support.v4.widget.Space; +import androidx.core.view.ViewCompat; +import androidx.legacy.widget.Space; import android.text.Editable; import android.text.TextWatcher; import android.util.AttributeSet; diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageInputStyle.java b/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageInputStyle.java index 1cea99c8..424e8a14 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageInputStyle.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessageInputStyle.java @@ -20,9 +20,9 @@ import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.drawable.Drawable; -import android.support.annotation.ColorInt; -import android.support.annotation.DrawableRes; -import android.support.v4.graphics.drawable.DrawableCompat; +import androidx.annotation.ColorInt; +import androidx.annotation.DrawableRes; +import androidx.core.graphics.drawable.DrawableCompat; import android.util.AttributeSet; import com.stfalcon.chatkit.R; diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesList.java b/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesList.java index 17b3f8ed..422818fc 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesList.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesList.java @@ -17,11 +17,13 @@ package com.stfalcon.chatkit.messages; import android.content.Context; -import android.support.annotation.Nullable; -import android.support.v7.widget.DefaultItemAnimator; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.SimpleItemAnimator; + +import androidx.annotation.Nullable; +import androidx.recyclerview.widget.DefaultItemAnimator; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.SimpleItemAnimator; + import android.util.AttributeSet; import com.stfalcon.chatkit.commons.models.IMessage; @@ -75,13 +77,8 @@ void setAdapter(MessagesListAdapter adapter) { */ public void setAdapter(MessagesListAdapter adapter, boolean reverseLayout) { - SimpleItemAnimator itemAnimator = new DefaultItemAnimator(); - itemAnimator.setSupportsChangeAnimations(false); - LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, reverseLayout); - - setItemAnimator(itemAnimator); setLayoutManager(layoutManager); adapter.setLayoutManager(layoutManager); adapter.setStyle(messagesListStyle); diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesListAdapter.java b/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesListAdapter.java index e0fcb8a2..ec9eed57 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesListAdapter.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesListAdapter.java @@ -19,8 +19,10 @@ import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; -import android.support.annotation.LayoutRes; -import android.support.v7.widget.RecyclerView; + +import androidx.annotation.LayoutRes; +import androidx.recyclerview.widget.RecyclerView; + import android.text.Spannable; import android.text.method.LinkMovementMethod; import android.util.SparseArray; @@ -34,6 +36,7 @@ import com.stfalcon.chatkit.commons.ImageLoader; import com.stfalcon.chatkit.commons.ViewHolder; import com.stfalcon.chatkit.commons.models.IMessage; +import com.stfalcon.chatkit.commons.models.IUser; import com.stfalcon.chatkit.utils.DateFormatter; import java.util.ArrayList; @@ -103,13 +106,70 @@ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { @Override public void onBindViewHolder(ViewHolder holder, int position) { Wrapper wrapper = items.get(position); - holders.bind(holder, wrapper.item, wrapper.isSelected, imageLoader, + boolean isFirstItemInGroup = true; + boolean isLastItemInGroup = true; + if (position < items.size() - 1) { + isFirstItemInGroup = isFirstItemInGroup(items.get(position), items.get(position + 1)); + } + + if (position > 0) { + isLastItemInGroup = isLastItemInGroup(items.get(position), items.get(position - 1)); + } + holders.bind(holder, wrapper.item, wrapper.isSelected, isFirstItemInGroup, isLastItemInGroup, imageLoader, getMessageClickListener(wrapper), getMessageLongClickListener(wrapper), dateHeadersFormatter, viewClickListenersArray); } + private boolean isFirstItemInGroup(Wrapper currentMsg, Wrapper precedingMsg) { + // null check + if (currentMsg == null || precedingMsg == null) { + return true; + } + + IUser currentUser, precedingUser; + if (currentMsg.item instanceof IMessage) { + currentUser = ((IMessage) currentMsg.item).getUser(); + } else { + return true; + } + if (precedingMsg.item instanceof IMessage) { + precedingUser = ((IMessage) precedingMsg.item).getUser(); + } else { + return true; + } + + // If admin message or + if (currentUser == null || precedingUser == null) return true; + return !(currentUser.getId().equals(precedingUser.getId())); + } + + private boolean isLastItemInGroup(Wrapper currentMsg, Wrapper nextMessage) { + // null check + if (currentMsg == null || nextMessage == null) { + return true; + } + + IUser currentUser, nextUser; + if (currentMsg.item instanceof IMessage) { + currentUser = ((IMessage) currentMsg.item).getUser(); + } else { + return true; + } + if (nextMessage.item instanceof IMessage) { + nextUser = ((IMessage) nextMessage.item).getUser(); + } else { + return true; + } + + // If admin message or + if (currentUser == null || nextUser == null) { + return true; + } + return !currentUser.getId().equals(nextUser.getId()); + } + @Override public int getItemCount() { return items.size(); @@ -155,7 +215,11 @@ public void addToStart(MESSAGE message, boolean scroll) { } Wrapper element = new Wrapper<>(message); items.add(0, element); + boolean isContinuous = isPreviousSameAuthor(message.getUser().getId(), 0); notifyItemRangeInserted(0, isNewMessageToday ? 2 : 1); + if (isContinuous) { + notifyItemChanged(1); + } if (layoutManager != null && scroll) { layoutManager.scrollToPosition(0); } diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesListStyle.java b/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesListStyle.java index 88c6fe15..7bb7182f 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesListStyle.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/messages/MessagesListStyle.java @@ -22,9 +22,9 @@ import android.graphics.Color; import android.graphics.Typeface; import android.graphics.drawable.Drawable; -import android.support.annotation.ColorInt; -import android.support.annotation.DrawableRes; -import android.support.v4.graphics.drawable.DrawableCompat; +import androidx.annotation.ColorInt; +import androidx.annotation.DrawableRes; +import androidx.core.graphics.drawable.DrawableCompat; import android.util.AttributeSet; import com.stfalcon.chatkit.R; diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/messages/RecyclerScrollMoreListener.java b/chatkit/src/main/java/com/stfalcon/chatkit/messages/RecyclerScrollMoreListener.java index 00012084..f6e61998 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/messages/RecyclerScrollMoreListener.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/messages/RecyclerScrollMoreListener.java @@ -16,10 +16,10 @@ package com.stfalcon.chatkit.messages; -import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.StaggeredGridLayoutManager; +import androidx.recyclerview.widget.GridLayoutManager; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import androidx.recyclerview.widget.StaggeredGridLayoutManager; class RecyclerScrollMoreListener extends RecyclerView.OnScrollListener { diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/utils/RoundedImageView.java b/chatkit/src/main/java/com/stfalcon/chatkit/utils/RoundedImageView.java index 7770fb13..62954e99 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/utils/RoundedImageView.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/utils/RoundedImageView.java @@ -18,12 +18,11 @@ import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.net.Uri; -import android.support.annotation.DimenRes; -import android.support.annotation.NonNull; -import android.support.v4.content.ContextCompat; -import android.support.v7.widget.AppCompatImageView; +import androidx.annotation.DimenRes; +import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; +import androidx.appcompat.widget.AppCompatImageView; import android.util.AttributeSet; -import android.widget.ImageView; /** * Thanks to Joonho Kim (https://github.com/pungrue26) for his lightweight SelectableRoundedImageView, diff --git a/chatkit/src/main/java/com/stfalcon/chatkit/utils/ShapeImageView.java b/chatkit/src/main/java/com/stfalcon/chatkit/utils/ShapeImageView.java index b9f054c5..f212468a 100644 --- a/chatkit/src/main/java/com/stfalcon/chatkit/utils/ShapeImageView.java +++ b/chatkit/src/main/java/com/stfalcon/chatkit/utils/ShapeImageView.java @@ -26,7 +26,7 @@ * ImageView with mask what described with Bézier Curves */ -public class ShapeImageView extends android.support.v7.widget.AppCompatImageView { +public class ShapeImageView extends androidx.appcompat.widget.AppCompatImageView { private Path path; public ShapeImageView(Context context) { diff --git a/chatkit/src/main/res/layout/item_incoming_text_message.xml b/chatkit/src/main/res/layout/item_incoming_text_message.xml index 3c35437d..275084eb 100644 --- a/chatkit/src/main/res/layout/item_incoming_text_message.xml +++ b/chatkit/src/main/res/layout/item_incoming_text_message.xml @@ -3,10 +3,10 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="8dp" + android:layout_marginBottom="4dp" android:layout_marginLeft="16dp" android:layout_marginRight="16dp" - android:layout_marginTop="8dp"> + android:layout_marginTop="4dp"> - - - - \ No newline at end of file + \ No newline at end of file diff --git a/sample/src/main/res/layout/fragment_demo_card.xml b/sample/src/main/res/layout/fragment_demo_card.xml index 87290af0..f20809f1 100644 --- a/sample/src/main/res/layout/fragment_demo_card.xml +++ b/sample/src/main/res/layout/fragment_demo_card.xml @@ -1,4 +1,4 @@ - - + diff --git a/sample/src/main/res/layout/item_custom_incoming_text_message.xml b/sample/src/main/res/layout/item_custom_incoming_text_message.xml index bc1bbd96..52d52e7c 100644 --- a/sample/src/main/res/layout/item_custom_incoming_text_message.xml +++ b/sample/src/main/res/layout/item_custom_incoming_text_message.xml @@ -9,7 +9,7 @@ diff --git a/sample/src/main/res/layout/item_sample.xml b/sample/src/main/res/layout/item_sample.xml index f970b2e6..8bfce6df 100644 --- a/sample/src/main/res/layout/item_sample.xml +++ b/sample/src/main/res/layout/item_sample.xml @@ -1,4 +1,4 @@ - - \ No newline at end of file + \ No newline at end of file