From afaf89f6730ad72ae387387f8461324797b91def Mon Sep 17 00:00:00 2001 From: dwarsh Date: Wed, 19 Aug 2020 20:10:35 +0530 Subject: [PATCH] Android UI Kit v2.0.2 --- app/build.gradle | 7 +- .../pro/androiduikit/CreateUserActivity.java | 2 - .../pro/androiduikit/MainActivity.java | 5 +- .../pro/androiduikit/UIKitApplication.java | 18 +- .../pro/androiduikit/constants/AppConfig.java | 4 +- uikit/build.gradle | 2 +- uikit/src/main/AndroidManifest.xml | 24 +- .../java/adapter/ConversationListAdapter.java | 15 + .../main/java/adapter/GroupListAdapter.java | 25 +- .../src/main/java/adapter/MessageAdapter.java | 747 +++++-- .../main/java/adapter/SharedMediaAdapter.java | 82 +- .../src/main/java/adapter/ThreadAdapter.java | 1386 +++++++++++++ .../pro/uikit/CometChatConversationList.java | 1 - .../pro/uikit/CometChatGroupList.java | 6 +- .../com/cometchat/pro/uikit/ComposeBox.java | 36 +- .../SharedMedia/SharedFilesFragment.java | 8 +- .../SharedMedia/SharedImagesFragment.java | 20 +- .../SharedMedia/SharedVideosFragment.java | 8 +- .../main/java/constant/StringContract.java | 19 +- .../listeners/MessageActionCloseListener.java | 8 + .../java/listeners/OnMessageLongClick.java | 10 + .../CometChatConversationListScreen.java | 7 +- ...CometChatForwardMessageScreenActivity.java | 69 +- .../CometChatGroupDetailScreenActivity.java | 72 +- .../java/screen/CometChatGroupListScreen.java | 1 - .../java/screen/CometChatUserInfoScreen.java | 4 +- .../java/screen/MessageActionFragment.java | 217 ++ .../CometChatGroupMemberListScreen.java | 3 +- .../CometChatMessageListActivity.java | 11 +- .../messagelist/CometChatMessageScreen.java | 512 +++-- .../CometChatThreadMessageActivity.java | 204 ++ .../CometChatThreadMessageScreen.java | 1831 +++++++++++++++++ .../java/screen/unified/CometChatUnified.java | 12 +- uikit/src/main/java/utils/Extensions.java | 156 ++ uikit/src/main/java/utils/Utils.java | 111 +- .../java/viewmodel/ConversationViewModel.java | 3 +- .../java/viewmodel/GroupListViewModel.java | 4 +- uikit/src/main/res/drawable/bottom_border.xml | 3 +- .../main/res/drawable/ic_baseline_edit_24.xml | 10 + .../res/drawable/ic_baseline_forward_24.xml | 10 + .../res/drawable/ic_baseline_more_vert_24.xml | 10 + uikit/src/main/res/drawable/ic_hand.xml | 5 + uikit/src/main/res/drawable/ic_lock_24dp.xml | 5 + uikit/src/main/res/drawable/ic_nav_chat.xml | 4 +- uikit/src/main/res/drawable/ic_reply_24dp.xml | 10 + uikit/src/main/res/drawable/ic_share_24dp.xml | 9 + .../res/drawable/left_border_lmessage.xml | 10 + .../res/drawable/left_border_rmessage.xml | 10 + .../src/main/res/drawable/rounded_border.xml | 10 + .../src/main/res/drawable/rounded_dialog.xml | 8 + ...ctivity_comet_chat_group_detail_screen.xml | 13 +- .../activity_comet_chat_thread_message.xml | 124 ++ .../main/res/layout/alert_reply_layout.xml | 31 + .../res/layout/block_user_message_layout.xml | 37 + .../main/res/layout/chat_screen_toolbar.xml | 12 +- .../layout/cometchat_audio_layout_left.xml | 33 +- .../layout/cometchat_audio_layout_right.xml | 34 +- .../layout/cometchat_left_file_message.xml | 33 +- .../layout/cometchat_right_file_message.xml | 32 +- .../main/res/layout/conversation_list_row.xml | 8 +- .../main/res/layout/edit_message_layout.xml | 39 + .../main/res/layout/fragment_chat_screen.xml | 145 +- .../res/layout/fragment_message_actions.xml | 105 + .../res/layout/fragment_thread_message.xml | 234 +++ uikit/src/main/res/layout/group_list_row.xml | 4 +- .../res/layout/join_ongoing_call_layout.xml | 27 + .../src/main/res/layout/left_message_item.xml | 73 +- .../res/layout/left_reply_message_item.xml | 48 + .../res/layout/message_left_link_item.xml | 34 +- .../layout/message_left_list_image_item.xml | 63 +- .../layout/message_left_list_video_item.xml | 33 +- .../res/layout/message_right_link_item.xml | 34 +- .../layout/message_right_list_image_item.xml | 65 +- .../layout/message_right_list_video_item.xml | 35 +- .../src/main/res/layout/messages_shimmer.xml | 1 + .../main/res/layout/reply_message_layout.xml | 49 + .../main/res/layout/right_message_item.xml | 55 +- .../res/layout/right_reply_message_item.xml | 52 + .../res/layout/shared_media_image_row.xml | 28 +- .../layout/thread_message_audio_layout.xml | 143 ++ .../res/layout/thread_message_file_item.xml | 110 + .../res/layout/thread_message_image_item.xml | 105 + .../main/res/layout/thread_message_item.xml | 119 ++ .../res/layout/thread_message_link_item.xml | 132 ++ .../res/layout/thread_message_video_item.xml | 86 + .../main/res/layout/thread_screen_toolbar.xml | 49 + uikit/src/main/res/menu/group_action_menu.xml | 6 +- uikit/src/main/res/values/strings.xml | 28 +- uikit/src/main/res/values/styles.xml | 10 + 89 files changed, 7274 insertions(+), 749 deletions(-) create mode 100644 uikit/src/main/java/adapter/ThreadAdapter.java create mode 100644 uikit/src/main/java/listeners/MessageActionCloseListener.java create mode 100644 uikit/src/main/java/listeners/OnMessageLongClick.java create mode 100644 uikit/src/main/java/screen/MessageActionFragment.java create mode 100644 uikit/src/main/java/screen/threadconversation/CometChatThreadMessageActivity.java create mode 100644 uikit/src/main/java/screen/threadconversation/CometChatThreadMessageScreen.java create mode 100644 uikit/src/main/java/utils/Extensions.java create mode 100644 uikit/src/main/res/drawable/ic_baseline_edit_24.xml create mode 100644 uikit/src/main/res/drawable/ic_baseline_forward_24.xml create mode 100644 uikit/src/main/res/drawable/ic_baseline_more_vert_24.xml create mode 100644 uikit/src/main/res/drawable/ic_hand.xml create mode 100644 uikit/src/main/res/drawable/ic_lock_24dp.xml create mode 100644 uikit/src/main/res/drawable/ic_reply_24dp.xml create mode 100644 uikit/src/main/res/drawable/ic_share_24dp.xml create mode 100644 uikit/src/main/res/drawable/left_border_lmessage.xml create mode 100644 uikit/src/main/res/drawable/left_border_rmessage.xml create mode 100644 uikit/src/main/res/drawable/rounded_border.xml create mode 100644 uikit/src/main/res/drawable/rounded_dialog.xml create mode 100644 uikit/src/main/res/layout/activity_comet_chat_thread_message.xml create mode 100644 uikit/src/main/res/layout/alert_reply_layout.xml create mode 100644 uikit/src/main/res/layout/block_user_message_layout.xml create mode 100644 uikit/src/main/res/layout/edit_message_layout.xml create mode 100644 uikit/src/main/res/layout/fragment_message_actions.xml create mode 100644 uikit/src/main/res/layout/fragment_thread_message.xml create mode 100644 uikit/src/main/res/layout/join_ongoing_call_layout.xml create mode 100644 uikit/src/main/res/layout/left_reply_message_item.xml create mode 100644 uikit/src/main/res/layout/reply_message_layout.xml create mode 100644 uikit/src/main/res/layout/right_reply_message_item.xml create mode 100644 uikit/src/main/res/layout/thread_message_audio_layout.xml create mode 100644 uikit/src/main/res/layout/thread_message_file_item.xml create mode 100644 uikit/src/main/res/layout/thread_message_image_item.xml create mode 100644 uikit/src/main/res/layout/thread_message_item.xml create mode 100644 uikit/src/main/res/layout/thread_message_link_item.xml create mode 100644 uikit/src/main/res/layout/thread_message_video_item.xml create mode 100644 uikit/src/main/res/layout/thread_screen_toolbar.xml diff --git a/app/build.gradle b/app/build.gradle index b2922936..233ddbd0 100755 --- a/app/build.gradle +++ b/app/build.gradle @@ -15,7 +15,7 @@ android { manifestPlaceholders = [file_provider: "com.cometchat.pro.androiduikit"] ndk { - abiFilters "armeabi-v7a", "x86" + abiFilters "armeabi-v7a", "x86", "arm64-v8a", "x86_64" } } dataBinding { @@ -55,8 +55,11 @@ dependencies { androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' implementation project(path: ':uikit') + implementation 'androidx.emoji:emoji:1.1.0-rc01' + implementation 'androidx.emoji:emoji-bundled:1.1.0' + implementation 'com.google.android.material:material:1.2.0-alpha05' implementation 'com.facebook.shimmer:shimmer:0.4.0' // - implementation 'com.cometchat:pro-android-chat-sdk:2.0.6' + implementation 'com.cometchat:pro-android-chat-sdk:2.0.7' } diff --git a/app/src/main/java/com/cometchat/pro/androiduikit/CreateUserActivity.java b/app/src/main/java/com/cometchat/pro/androiduikit/CreateUserActivity.java index 4b0fc02a..cd2b885b 100644 --- a/app/src/main/java/com/cometchat/pro/androiduikit/CreateUserActivity.java +++ b/app/src/main/java/com/cometchat/pro/androiduikit/CreateUserActivity.java @@ -65,7 +65,6 @@ public void onSuccess(User user) { @Override public void onError(CometChatException e) { - progressBar.setVisibility(View.GONE); createUserBtn.setClickable(true); Toast.makeText(CreateUserActivity.this,"Failed to create user",Toast.LENGTH_LONG).show(); } @@ -111,7 +110,6 @@ public void onSuccess(User user) { @Override public void onError(CometChatException e) { - progressBar.setVisibility(View.GONE); if (uid!=null) Snackbar.make(uid.getRootView(),"Unable to login",Snackbar.LENGTH_INDEFINITE).setAction("Try Again", new View.OnClickListener() { @Override diff --git a/app/src/main/java/com/cometchat/pro/androiduikit/MainActivity.java b/app/src/main/java/com/cometchat/pro/androiduikit/MainActivity.java index b9ade5de..c3ccf14d 100644 --- a/app/src/main/java/com/cometchat/pro/androiduikit/MainActivity.java +++ b/app/src/main/java/com/cometchat/pro/androiduikit/MainActivity.java @@ -40,7 +40,10 @@ public class MainActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); - + if (CometChat.getLoggedInUser()!=null) + { + startActivity(new Intent(MainActivity.this,SelectActivity.class)); + } loginBtn = findViewById(R.id.login); superhero1 = findViewById(R.id.superhero1); superhero2 = findViewById(R.id.superhero2); diff --git a/app/src/main/java/com/cometchat/pro/androiduikit/UIKitApplication.java b/app/src/main/java/com/cometchat/pro/androiduikit/UIKitApplication.java index 06e7211a..f1c82a25 100644 --- a/app/src/main/java/com/cometchat/pro/androiduikit/UIKitApplication.java +++ b/app/src/main/java/com/cometchat/pro/androiduikit/UIKitApplication.java @@ -11,12 +11,17 @@ import android.util.Log; import android.view.WindowManager; import android.widget.Toast; + +import androidx.emoji.bundled.BundledEmojiCompatConfig; +import androidx.emoji.text.EmojiCompat; + import com.cometchat.pro.core.AppSettings; import com.cometchat.pro.core.CometChat; import com.cometchat.pro.exceptions.CometChatException; import com.cometchat.pro.androiduikit.constants.AppConfig; import com.cometchat.pro.helpers.Logger; +import constant.StringContract; import listeners.CometChatCallListener; import utils.PreferenceUtil; @@ -27,13 +32,16 @@ public class UIKitApplication extends Application { @Override public void onCreate() { super.onCreate(); - AppSettings appSettings = new AppSettings.AppSettingsBuilder().subscribePresenceForAllUsers().setRegion(AppConfig.AppDetails.REGION).build(); - CometChat.init(this, AppConfig.AppDetails.APP_ID, appSettings, new CometChat.CallbackListener() { + EmojiCompat.Config config = new BundledEmojiCompatConfig(this); + EmojiCompat.init(config); + AppSettings appSettings = new AppSettings.AppSettingsBuilder(). + subscribePresenceForAllUsers().setRegion(AppConfig.AppDetails.REGION).build(); + CometChat.init(this, AppConfig.AppDetails.APP_ID, appSettings, + new CometChat.CallbackListener() { @Override public void onSuccess(String s) { - PreferenceUtil preferenceUtil = PreferenceUtil.getInstance(UIKitApplication.this); - preferenceUtil.saveString("apikey",AppConfig.AppDetails.API_KEY); - CometChat.setSource("ui-kit-sampleapp","android","java"); + StringContract.AppInfo.API_KEY = AppConfig.AppDetails.API_KEY; + CometChat.setSource("ui-kit","android","java"); Log.d(TAG, "onSuccess: "+s); } diff --git a/app/src/main/java/com/cometchat/pro/androiduikit/constants/AppConfig.java b/app/src/main/java/com/cometchat/pro/androiduikit/constants/AppConfig.java index 5cb17fa6..8d1caed1 100644 --- a/app/src/main/java/com/cometchat/pro/androiduikit/constants/AppConfig.java +++ b/app/src/main/java/com/cometchat/pro/androiduikit/constants/AppConfig.java @@ -4,9 +4,9 @@ public class AppConfig { public class AppDetails { - public static final String APP_ID = "XXXXXXXXXXX"; + public static final String APP_ID = "XXXXXXXXXXXXXXXX"; - public static final String API_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXX"; + public static final String API_KEY = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; public static final String REGION = "XX"; } diff --git a/uikit/build.gradle b/uikit/build.gradle index 4521e519..30225cd8 100644 --- a/uikit/build.gradle +++ b/uikit/build.gradle @@ -61,5 +61,5 @@ dependencies { implementation 'com.facebook.shimmer:shimmer:0.4.0' //cometchat - compileOnly 'com.cometchat:pro-android-chat-sdk:2.0.6' + compileOnly 'com.cometchat:pro-android-chat-sdk:2.0.7' } diff --git a/uikit/src/main/AndroidManifest.xml b/uikit/src/main/AndroidManifest.xml index 4842c141..6b520ded 100644 --- a/uikit/src/main/AndroidManifest.xml +++ b/uikit/src/main/AndroidManifest.xml @@ -16,7 +16,9 @@ android:usesCleartextTraffic="true" tools:node="merge" tools:targetApi="m"> - + + - + android:windowSoftInputMode="adjustPan" /> + @@ -49,7 +52,18 @@ android:screenOrientation="portrait" /> + android:screenOrientation="portrait"> + + + + + + + + + + + diff --git a/uikit/src/main/java/adapter/ConversationListAdapter.java b/uikit/src/main/java/adapter/ConversationListAdapter.java index fa016bdc..3ea3dcd6 100644 --- a/uikit/src/main/java/adapter/ConversationListAdapter.java +++ b/uikit/src/main/java/adapter/ConversationListAdapter.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.List; +import utils.Extensions; import utils.FontUtils; import utils.Utils; @@ -111,6 +112,7 @@ public void onBindViewHolder(@NonNull ConversationViewHolder conversationViewHol String avatar; String name; + String status; String lastMessageText = null; BaseMessage baseMessage = conversation.getLastMessage(); conversationViewHolder.conversationListRowBinding.setConversation(conversation); @@ -133,6 +135,12 @@ public void onBindViewHolder(@NonNull ConversationViewHolder conversationViewHol conversationViewHolder.conversationListRowBinding.messageTime.setVisibility(View.GONE); } conversationViewHolder.conversationListRowBinding.txtUserMessage.setText(lastMessageText); + if (baseMessage!=null) { + boolean isSentimentNegative = Extensions.checkSentiment(baseMessage); + if (isSentimentNegative && !baseMessage.getSender().getUid().equals(CometChat.getLoggedInUser().getUid())) { + conversationViewHolder.conversationListRowBinding.txtUserMessage.setText(context.getResources().getString(R.string.sentimment_content)); + } + } conversationViewHolder.conversationListRowBinding.txtUserMessage.setTypeface(fontUtils.getTypeFace(FontUtils.robotoRegular)); conversationViewHolder.conversationListRowBinding.txtUserName.setTypeface(fontUtils.getTypeFace(FontUtils.robotoMedium)); conversationViewHolder.conversationListRowBinding.messageTime.setTypeface(fontUtils.getTypeFace(FontUtils.robotoRegular)); @@ -140,9 +148,16 @@ public void onBindViewHolder(@NonNull ConversationViewHolder conversationViewHol if (conversation.getConversationType().equals(CometChatConstants.RECEIVER_TYPE_USER)) { name = ((User) conversation.getConversationWith()).getName(); avatar = ((User) conversation.getConversationWith()).getAvatar(); + status = ((User)conversation.getConversationWith()).getStatus(); + if (status.equals(CometChatConstants.USER_STATUS_ONLINE)) { + conversationViewHolder.conversationListRowBinding.userStatus.setVisibility(View.VISIBLE); + conversationViewHolder.conversationListRowBinding.userStatus.setUserStatus(status); + } else + conversationViewHolder.conversationListRowBinding.userStatus.setVisibility(View.GONE); } else { name = ((Group) conversation.getConversationWith()).getName(); avatar = ((Group) conversation.getConversationWith()).getIcon(); + conversationViewHolder.conversationListRowBinding.userStatus.setVisibility(View.GONE); } conversationViewHolder.conversationListRowBinding.messageCount.setCount(conversation.getUnreadMessageCount()); diff --git a/uikit/src/main/java/adapter/GroupListAdapter.java b/uikit/src/main/java/adapter/GroupListAdapter.java index 734b4fef..f719937f 100644 --- a/uikit/src/main/java/adapter/GroupListAdapter.java +++ b/uikit/src/main/java/adapter/GroupListAdapter.java @@ -1,6 +1,7 @@ package adapter; import android.content.Context; +import android.content.res.ColorStateList; import android.view.LayoutInflater; import android.view.ViewGroup; @@ -8,6 +9,7 @@ import androidx.databinding.DataBindingUtil; import androidx.recyclerview.widget.RecyclerView; +import com.cometchat.pro.constants.CometChatConstants; import com.cometchat.pro.uikit.R; import com.cometchat.pro.uikit.databinding.GroupListRowBinding; import com.cometchat.pro.models.Group; @@ -81,6 +83,16 @@ public GroupViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewTyp public void onBindViewHolder(@NonNull GroupViewHolder groupViewHolder, int position) { Group group = groupList.get(position); groupViewHolder.groupListRowBinding.setGroup(group); + groupViewHolder.groupListRowBinding.executePendingBindings(); + groupViewHolder.groupListRowBinding.txtUserMessage.setText("Members: "+group.getMembersCount()); + + if (group.getGroupType().equals(CometChatConstants.GROUP_TYPE_PRIVATE)) + groupViewHolder.groupListRowBinding.txtUserName.setCompoundDrawablesWithIntrinsicBounds(0,0,R.drawable.ic_security_24dp,0); + else if (group.getGroupType().equals(CometChatConstants.GROUP_TYPE_PASSWORD)) + groupViewHolder.groupListRowBinding.txtUserName.setCompoundDrawablesWithIntrinsicBounds(0,0,R.drawable.ic_lock_24dp,0); + else + groupViewHolder.groupListRowBinding.txtUserName.setCompoundDrawablesWithIntrinsicBounds(0,0,0,0); + groupViewHolder.groupListRowBinding.executePendingBindings(); groupViewHolder.groupListRowBinding.avGroup.setBackgroundColor(context.getResources().getColor(R.color.colorPrimary)); groupViewHolder.groupListRowBinding.getRoot().setTag(R.string.group, group); @@ -88,9 +100,11 @@ public void onBindViewHolder(@NonNull GroupViewHolder groupViewHolder, int posit groupViewHolder.groupListRowBinding.txtUserName.setTypeface(fontUtils.getTypeFace(FontUtils.robotoMedium)); if(Utils.isDarkMode(context)) { + groupViewHolder.groupListRowBinding.txtUserName.setCompoundDrawableTintList(ColorStateList.valueOf(context.getResources().getColor(R.color.grey))); groupViewHolder.groupListRowBinding.txtUserName.setTextColor(context.getResources().getColor(R.color.textColorWhite)); groupViewHolder.groupListRowBinding.tvSeprator.setBackgroundColor(context.getResources().getColor(R.color.grey)); } else { + groupViewHolder.groupListRowBinding.txtUserName.setCompoundDrawableTintList(ColorStateList.valueOf(context.getResources().getColor(R.color.message_bubble_grey))); groupViewHolder.groupListRowBinding.txtUserName.setTextColor(context.getResources().getColor(R.color.primaryTextColor)); groupViewHolder.groupListRowBinding.tvSeprator.setBackgroundColor(context.getResources().getColor(R.color.light_grey)); } @@ -103,7 +117,7 @@ public void onBindViewHolder(@NonNull GroupViewHolder groupViewHolder, int posit public void updateGroupList(List groupList) { for (int i = 0; i groupList) { * * @param group is an object of Group. It will be updated with previous group in a list. */ - public void updateGroup(Group group) { + public void updateGroup(Group group,int i) { if (group != null) { if (groupList.contains(group)) { - int index = groupList.indexOf(group); + int index = groupList.indexOf(groupList.get(i)); groupList.remove(index); - groupList.add(group); + groupList.add(index,group); notifyItemChanged(index); } else { groupList.add(group); @@ -172,7 +186,8 @@ public void searchGroup(List groups) { */ public void add(Group group) { if (group != null) { - updateGroup(group); + groupList.add(group); + notifyItemInserted(getItemCount()-1); } } diff --git a/uikit/src/main/java/adapter/MessageAdapter.java b/uikit/src/main/java/adapter/MessageAdapter.java index 43ee9fe6..2606deff 100644 --- a/uikit/src/main/java/adapter/MessageAdapter.java +++ b/uikit/src/main/java/adapter/MessageAdapter.java @@ -3,8 +3,10 @@ import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; +import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.res.ColorStateList; import android.graphics.Bitmap; @@ -12,12 +14,14 @@ import android.graphics.PorterDuff; import android.graphics.Typeface; import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.Drawable; import android.media.MediaPlayer; import android.net.Uri; import android.os.AsyncTask; import android.os.Build; import android.os.Handler; import android.os.Looper; +import android.text.Spannable; import android.text.TextUtils; import android.util.Log; import android.util.LongSparseArray; @@ -25,6 +29,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.ProgressBar; import android.widget.RelativeLayout; import android.widget.SeekBar; @@ -33,14 +38,18 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.cardview.widget.CardView; +import androidx.emoji.text.EmojiCompat; +import androidx.emoji.text.EmojiSpan; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.request.target.SimpleTarget; import com.bumptech.glide.request.transition.Transition; import com.cometchat.pro.constants.CometChatConstants; import com.cometchat.pro.core.Call; import com.cometchat.pro.core.CometChat; +import com.cometchat.pro.helpers.CometChatHelper; import com.cometchat.pro.helpers.Logger; import com.cometchat.pro.models.Action; import com.cometchat.pro.uikit.R; @@ -51,6 +60,7 @@ import com.cometchat.pro.models.TextMessage; import com.cometchat.pro.models.User; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -63,6 +73,7 @@ import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -70,6 +81,9 @@ import constant.StringContract; import listeners.StickyHeaderAdapter; import screen.messagelist.CometChatMessageListActivity; +import screen.messagelist.CometChatMessageScreen; +import screen.threadconversation.CometChatThreadMessageActivity; +import utils.Extensions; import utils.FontUtils; import utils.MediaUtils; import utils.Utils; @@ -110,6 +124,10 @@ public class MessageAdapter extends RecyclerView.Adapter messageList, String typ setMessageList(messageList); this.context = context; try { - messageLongClick = (CometChatMessageListActivity)context; + messageLongClick = (CometChatMessageListActivity) context; }catch (Exception e) { e.printStackTrace(); } @@ -239,6 +257,16 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int view.setTag(RIGHT_TEXT_MESSAGE); return new TextMessageViewHolder(view); + case LEFT_REPLY_TEXT_MESSAGE: + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.left_message_item, parent, false); + view.setTag(LEFT_REPLY_TEXT_MESSAGE); + return new TextMessageViewHolder(view); + + case RIGHT_REPLY_TEXT_MESSAGE: + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.right_message_item, parent, false); + view.setTag(RIGHT_REPLY_TEXT_MESSAGE); + return new TextMessageViewHolder(view); + case RIGHT_LINK_MESSAGE: view = LayoutInflater.from(parent.getContext()).inflate(R.layout.message_right_link_item,parent,false); view.setTag(RIGHT_LINK_MESSAGE); @@ -378,8 +406,10 @@ else if(!isNextMessage) { setDeleteData((DeleteMessageViewHolder)viewHolder,i); break; case LEFT_TEXT_MESSAGE: + case LEFT_REPLY_TEXT_MESSAGE: ((TextMessageViewHolder) viewHolder).ivUser.setVisibility(View.GONE); case RIGHT_TEXT_MESSAGE: + case RIGHT_REPLY_TEXT_MESSAGE: setTextData((TextMessageViewHolder) viewHolder, i); break; case LEFT_LINK_MESSAGE: @@ -437,11 +467,77 @@ private void setAudioData(AudioMessageViewHolder viewHolder, int i) { viewHolder.tvUser.setText(baseMessage.getSender().getName()); } } + + if (baseMessage.getReplyCount()!=0) { + try { + if (baseMessage.getMetadata()!=null && baseMessage.getMetadata().has("replyAvatars")) { + JSONArray jsonArray = baseMessage.getMetadata().getJSONArray("replyAvatars"); + viewHolder.lvReplyAvatar.setVisibility(View.VISIBLE); + for (int m = 0;m { + Intent intent = new Intent(context, CometChatThreadMessageActivity.class); + intent.putExtra(StringContract.IntentStrings.NAME,baseMessage.getSender().getName()); + intent.putExtra(StringContract.IntentStrings.AVATAR,baseMessage.getSender().getAvatar()); + intent.putExtra(StringContract.IntentStrings.REPLY_COUNT,baseMessage.getReplyCount()); + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getSender().getName()); + intent.putExtra(StringContract.IntentStrings.PARENT_ID,baseMessage.getId()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE,baseMessage.getType()); + intent.putExtra(StringContract.IntentStrings.SENTAT,baseMessage.getSentAt()); + if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) + intent.putExtra(StringContract.IntentStrings.TEXTMESSAGE,((TextMessage)baseMessage).getText()); + else { + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME,((MediaMessage)baseMessage).getAttachment().getFileName()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION,((MediaMessage)baseMessage).getAttachment().getFileExtension()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL,((MediaMessage)baseMessage).getAttachment().getFileUrl()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE,((MediaMessage)baseMessage).getAttachment().getFileSize()); + } + intent.putExtra(StringContract.IntentStrings.TYPE,baseMessage.getReceiverType()); + if (baseMessage.getReceiverType().equals(CometChatConstants.RECEIVER_TYPE_GROUP)) { + intent.putExtra(StringContract.IntentStrings.GUID,baseMessage.getReceiverUid()); + } + else { + if (baseMessage.getReceiverUid().equals(loggedInUser.getUid())) + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getSender().getUid()); + else + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getReceiverUid()); + } + context.startActivity(intent); + }); + + showMessageTime(viewHolder,baseMessage); if (selectedItemList.contains(baseMessage.getId())) viewHolder.txtTime.setVisibility(View.VISIBLE); else viewHolder.txtTime.setVisibility(View.GONE); + viewHolder.length.setText(Utils.getFileSize(((MediaMessage)baseMessage).getAttachment().getFileSize())); viewHolder.playBtn.setImageResource(R.drawable.ic_play_arrow_black_24dp); viewHolder.playBtn.setOnClickListener(new View.OnClickListener() { @@ -530,6 +626,71 @@ private void setFileData(FileMessageViewHolder viewHolder, int i) { viewHolder.fileSize.setText(Utils.getFileSize(fileSize)); + viewHolder.lvReplyAvatar.setVisibility(View.GONE); + if (baseMessage.getReplyCount()!=0) { + try { + if (baseMessage.getMetadata()!=null && baseMessage.getMetadata().has("replyAvatars")) { + JSONArray jsonArray = baseMessage.getMetadata().getJSONArray("replyAvatars"); + viewHolder.lvReplyAvatar.setVisibility(View.VISIBLE); + for (int m = 0;m { + Intent intent = new Intent(context, CometChatThreadMessageActivity.class); + intent.putExtra(StringContract.IntentStrings.NAME,baseMessage.getSender().getName()); + intent.putExtra(StringContract.IntentStrings.AVATAR,baseMessage.getSender().getAvatar()); + intent.putExtra(StringContract.IntentStrings.REPLY_COUNT,baseMessage.getReplyCount()); + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getSender().getName()); + intent.putExtra(StringContract.IntentStrings.PARENT_ID,baseMessage.getId()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE,baseMessage.getType()); + intent.putExtra(StringContract.IntentStrings.SENTAT,baseMessage.getSentAt()); + if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) + intent.putExtra(StringContract.IntentStrings.TEXTMESSAGE,((TextMessage)baseMessage).getText()); + else { + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME,((MediaMessage)baseMessage).getAttachment().getFileName()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION,((MediaMessage)baseMessage).getAttachment().getFileExtension()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL,((MediaMessage)baseMessage).getAttachment().getFileUrl()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE,((MediaMessage)baseMessage).getAttachment().getFileSize()); + } + intent.putExtra(StringContract.IntentStrings.TYPE,baseMessage.getReceiverType()); + if (baseMessage.getReceiverType().equals(CometChatConstants.RECEIVER_TYPE_GROUP)) { + intent.putExtra(StringContract.IntentStrings.GUID,baseMessage.getReceiverUid()); + } + else { + if (baseMessage.getReceiverUid().equals(loggedInUser.getUid())) + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getSender().getUid()); + else + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getReceiverUid()); + } + context.startActivity(intent); + }); + + showMessageTime(viewHolder, baseMessage); if (selectedItemList.contains(baseMessage.getId())) @@ -595,21 +756,133 @@ private void setImageData(ImageMessageViewHolder viewHolder, int i) { viewHolder.tvUser.setText(baseMessage.getSender().getName()); } } - if (((MediaMessage)baseMessage).getAttachment()!=null) - Glide.with(context).load(((MediaMessage) baseMessage).getAttachment().getFileUrl()).into(viewHolder.imageView); + + boolean isImageNotSafe = Extensions.getImageModeration(context,baseMessage); + String smallUrl = Extensions.getThumbnailGeneration(context,baseMessage); + viewHolder.imageView.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_defaulf_image)); + if (smallUrl!=null) { + Glide.with(context).asBitmap().diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true).load(smallUrl).into(new SimpleTarget() { + @Override + public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition transition) { + if (isImageNotSafe) + viewHolder.imageView.setImageBitmap(Utils.blur(context,resource)); + else + viewHolder.imageView.setImageBitmap(resource); + } + }); + } else { + Glide.with(context).asBitmap().diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true).load(((MediaMessage)baseMessage).getAttachment().getFileUrl()).into(new SimpleTarget() { + @Override + public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition transition) { + if (isImageNotSafe) + viewHolder.imageView.setImageBitmap(Utils.blur(context,resource)); + else + viewHolder.imageView.setImageBitmap(resource); + } + }); + } + if (isImageNotSafe) { + viewHolder.sensitiveLayout.setVisibility(View.VISIBLE); + } else { + viewHolder.sensitiveLayout.setVisibility(View.GONE); + } + + if (baseMessage.getReplyCount()!=0) { + try { + if (baseMessage.getMetadata()!=null && baseMessage.getMetadata().has("replyAvatars")) { + JSONArray jsonArray = baseMessage.getMetadata().getJSONArray("replyAvatars"); + viewHolder.lvReplyAvatar.setVisibility(View.VISIBLE); + for (int m = 0;m { + Intent intent = new Intent(context, CometChatThreadMessageActivity.class); + intent.putExtra(StringContract.IntentStrings.NAME,baseMessage.getSender().getName()); + intent.putExtra(StringContract.IntentStrings.AVATAR,baseMessage.getSender().getAvatar()); + intent.putExtra(StringContract.IntentStrings.REPLY_COUNT,baseMessage.getReplyCount()); + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getSender().getName()); + intent.putExtra(StringContract.IntentStrings.PARENT_ID,baseMessage.getId()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE,baseMessage.getType()); + intent.putExtra(StringContract.IntentStrings.SENTAT,baseMessage.getSentAt()); + if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) + intent.putExtra(StringContract.IntentStrings.TEXTMESSAGE,((TextMessage)baseMessage).getText()); + else { + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME,((MediaMessage)baseMessage).getAttachment().getFileName()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION,((MediaMessage)baseMessage).getAttachment().getFileExtension()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL,((MediaMessage)baseMessage).getAttachment().getFileUrl()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE,((MediaMessage)baseMessage).getAttachment().getFileSize()); + } + intent.putExtra(StringContract.IntentStrings.TYPE,baseMessage.getReceiverType()); + if (baseMessage.getReceiverType().equals(CometChatConstants.RECEIVER_TYPE_GROUP)) { + intent.putExtra(StringContract.IntentStrings.GUID,baseMessage.getReceiverUid()); + } + else { + if (baseMessage.getReceiverUid().equals(loggedInUser.getUid())) + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getSender().getUid()); + else + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getReceiverUid()); + } + context.startActivity(intent); + }); + + showMessageTime(viewHolder, baseMessage); if (selectedItemList.contains(baseMessage.getId())) viewHolder.txtTime.setVisibility(View.VISIBLE); else viewHolder.txtTime.setVisibility(View.GONE); -// viewHolder.rlMessageBubble.setOnClickListener(view -> { - displayImage(baseMessage); - setSelectedMessage(baseMessage.getId()); - notifyDataSetChanged(); + if (isImageNotSafe) { + AlertDialog.Builder alert = new AlertDialog.Builder(context); + alert.setTitle("Unsafe Content"); + alert.setIcon(R.drawable.ic_hand); + alert.setMessage("Are you surely want to see this unsafe content"); + alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + MediaUtils.openFile(((MediaMessage) baseMessage).getAttachment().getFileUrl(), context); + } + }); + alert.setNegativeButton("No", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + alert.create().show(); + } else { + setSelectedMessage(baseMessage.getId()); + notifyDataSetChanged(); + MediaUtils.openFile(((MediaMessage) baseMessage).getAttachment().getFileUrl(), context); + } }); viewHolder.rlMessageBubble.setOnLongClickListener(new View.OnLongClickListener() { @@ -666,6 +939,69 @@ private void setVideoData(VideoMessageViewHolder viewHolder, int i) { } if (((MediaMessage)baseMessage).getAttachment()!=null) Glide.with(context).load(((MediaMessage) baseMessage).getAttachment().getFileUrl()).into(viewHolder.imageView); + if (baseMessage.getReplyCount()!=0) { + try { + if (baseMessage.getMetadata()!=null && baseMessage.getMetadata().has("replyAvatars")) { + JSONArray jsonArray = baseMessage.getMetadata().getJSONArray("replyAvatars"); + viewHolder.lvReplyAvatar.setVisibility(View.VISIBLE); + for (int m = 0;m { + Intent intent = new Intent(context, CometChatThreadMessageActivity.class); + intent.putExtra(StringContract.IntentStrings.NAME,baseMessage.getSender().getName()); + intent.putExtra(StringContract.IntentStrings.AVATAR,baseMessage.getSender().getAvatar()); + intent.putExtra(StringContract.IntentStrings.REPLY_COUNT,baseMessage.getReplyCount()); + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getSender().getName()); + intent.putExtra(StringContract.IntentStrings.PARENT_ID,baseMessage.getId()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE,baseMessage.getType()); + intent.putExtra(StringContract.IntentStrings.SENTAT,baseMessage.getSentAt()); + if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) + intent.putExtra(StringContract.IntentStrings.TEXTMESSAGE,((TextMessage)baseMessage).getText()); + else { + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME,((MediaMessage)baseMessage).getAttachment().getFileName()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION,((MediaMessage)baseMessage).getAttachment().getFileExtension()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL,((MediaMessage)baseMessage).getAttachment().getFileUrl()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE,((MediaMessage)baseMessage).getAttachment().getFileSize()); + } + intent.putExtra(StringContract.IntentStrings.TYPE,baseMessage.getReceiverType()); + if (baseMessage.getReceiverType().equals(CometChatConstants.RECEIVER_TYPE_GROUP)) { + intent.putExtra(StringContract.IntentStrings.GUID,baseMessage.getReceiverUid()); + } + else { + if (baseMessage.getReceiverUid().equals(loggedInUser.getUid())) + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getSender().getUid()); + else + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getReceiverUid()); + } + context.startActivity(intent); + }); + showMessageTime(viewHolder, baseMessage); if (selectedItemList.contains(baseMessage.getId())) @@ -728,6 +1064,8 @@ private void setDeleteData(DeleteMessageViewHolder viewHolder, int i) { } } if (baseMessage.getDeletedAt()!=0) { + viewHolder.tvThreadReplyCount.setVisibility(View.GONE); + viewHolder.lvReplyAvatar.setVisibility(View.GONE); viewHolder.txtMessage.setText(R.string.message_deleted); viewHolder.txtMessage.setTextColor(context.getResources().getColor(R.color.secondaryTextColor)); viewHolder.txtMessage.setTypeface(null, Typeface.ITALIC); @@ -862,13 +1200,154 @@ private void setTextData(TextMessageViewHolder viewHolder, int i) { setAvatar(viewHolder.ivUser, baseMessage.getSender().getAvatar(), baseMessage.getSender().getName()); viewHolder.tvUser.setText(baseMessage.getSender().getName()); } + boolean isSentimentNegative = Extensions.checkSentiment(baseMessage); + if (isSentimentNegative) { + viewHolder.txtMessage.setVisibility(View.GONE); + viewHolder.sentimentVw.setVisibility(View.VISIBLE); + } + else { + viewHolder.txtMessage.setVisibility(View.VISIBLE); + viewHolder.sentimentVw.setVisibility(View.GONE); + } + viewHolder.viewSentimentMessage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + AlertDialog.Builder sentimentAlert = new AlertDialog.Builder(context) + .setTitle(context.getResources().getString(R.string.sentiment_alert)) + .setMessage(context.getResources().getString(R.string.sentiment_alert_message)) + .setPositiveButton(context.getResources().getString(R.string.yes), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + viewHolder.txtMessage.setVisibility(View.VISIBLE); + viewHolder.sentimentVw.setVisibility(View.GONE); + } + }) + .setNegativeButton(context.getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + sentimentAlert.create().show(); + } + }); } + if (baseMessage.getMetadata()!=null && baseMessage.getMetadata().has("reply")) { + try { + JSONObject metaData = baseMessage.getMetadata().getJSONObject("reply"); + String messageType = metaData.getString("type"); + String message = metaData.getString("message"); + viewHolder.replyLayout.setVisibility(View.VISIBLE); + viewHolder.replyUser.setText(metaData.getString("name")); + if (messageType.equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + viewHolder.replyMessage.setText(message); + viewHolder.replyMessage.setCompoundDrawablesWithIntrinsicBounds(0,0,0,0); + } else if (messageType.equals(CometChatConstants.MESSAGE_TYPE_IMAGE)) { + viewHolder.replyMessage.setText(context.getResources().getString(R.string.shared_a_image)); + viewHolder.replyMessage.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_photo,0,0,0); + } else if (messageType.equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + viewHolder.replyMessage.setText(String.format(context.getResources().getString(R.string.shared_a_audio),"")); + viewHolder.replyMessage.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_library_music_24dp,0,0,0); + } else if (messageType.equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + viewHolder.replyMessage.setText(context.getResources().getString(R.string.shared_a_video)); + viewHolder.replyMessage.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_videocam_24dp,0,0,0); + } else if (messageType.equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + viewHolder.replyMessage.setText(String.format(context.getResources().getString(R.string.shared_a_file),"")); + viewHolder.replyMessage.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_insert_drive_file_black_24dp,0,0,0); + } + }catch (Exception e) { + Log.e(TAG, "setTextData: "+e.getMessage()); + } + } + + if (baseMessage.getReplyCount()!=0) { + try { + if (baseMessage.getMetadata()!=null && baseMessage.getMetadata().has("replyAvatars")) { + JSONArray jsonArray = baseMessage.getMetadata().getJSONArray("replyAvatars"); + viewHolder.lvReplyAvatar.setVisibility(View.VISIBLE); + for (int m = 0;m { + Intent intent = new Intent(context, CometChatThreadMessageActivity.class); + intent.putExtra(StringContract.IntentStrings.NAME,baseMessage.getSender().getName()); + intent.putExtra(StringContract.IntentStrings.AVATAR,baseMessage.getSender().getAvatar()); + intent.putExtra(StringContract.IntentStrings.REPLY_COUNT,baseMessage.getReplyCount()); + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getSender().getName()); + intent.putExtra(StringContract.IntentStrings.PARENT_ID,baseMessage.getId()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE,baseMessage.getType()); + intent.putExtra(StringContract.IntentStrings.SENTAT,baseMessage.getSentAt()); + if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) + intent.putExtra(StringContract.IntentStrings.TEXTMESSAGE,((TextMessage)baseMessage).getText()); + else { + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME,((MediaMessage)baseMessage).getAttachment().getFileName()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION,((MediaMessage)baseMessage).getAttachment().getFileExtension()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL,((MediaMessage)baseMessage).getAttachment().getFileUrl()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE,((MediaMessage)baseMessage).getAttachment().getFileSize()); + } + intent.putExtra(StringContract.IntentStrings.TYPE,baseMessage.getReceiverType()); + if (baseMessage.getReceiverType().equals(CometChatConstants.RECEIVER_TYPE_GROUP)) { + intent.putExtra(StringContract.IntentStrings.GUID,baseMessage.getReceiverUid()); + } + else { + if (baseMessage.getReceiverUid().equals(loggedInUser.getUid())) + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getSender().getUid()); + else + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getReceiverUid()); + } + context.startActivity(intent); + }); + + String txtMessage = ((TextMessage) baseMessage).getText().trim(); + viewHolder.txtMessage.setTextSize(16f); + int count = 0; + CharSequence processed = EmojiCompat.get().process(txtMessage, 0, + txtMessage.length() -1, Integer.MAX_VALUE, EmojiCompat.REPLACE_STRATEGY_ALL); + if (processed instanceof Spannable) { + Spannable spannable = (Spannable) processed; + count = spannable.getSpans(0, spannable.length() - 1, EmojiSpan.class).length; + if (Utils.removeEmojiAndSymbol(txtMessage).trim().length() == 0) { + if (count == 1) { + viewHolder.txtMessage.setTextSize((int) Utils.dpToPx(context, 32)); + } else if (count == 2) { + viewHolder.txtMessage.setTextSize((int) Utils.dpToPx(context, 24)); + } + } + } + + viewHolder.txtMessage.setText(txtMessage); + String profanityFilter = Extensions.checkProfanityMessage(baseMessage); + viewHolder.txtMessage.setText(profanityFilter); + viewHolder.txtMessage.setTypeface(fontUtils.getTypeFace(FontUtils.robotoRegular)); - viewHolder.txtMessage.setText(((TextMessage) baseMessage).getText().trim()); - viewHolder.txtMessage.setTypeface(fontUtils.getTypeFace(FontUtils.robotoRegular)); - if (baseMessage.getSender().getUid().equals(loggedInUser.getUid())) + if (baseMessage.getSender().getUid().equals(loggedInUser.getUid())) viewHolder.txtMessage.setTextColor(context.getResources().getColor(R.color.textColorWhite)); - else + else viewHolder.txtMessage.setTextColor(context.getResources().getColor(R.color.primaryTextColor)); showMessageTime(viewHolder, baseMessage); @@ -894,6 +1373,7 @@ private void setTextData(TextMessageViewHolder viewHolder, int i) { notifyDataSetChanged(); }); + viewHolder.rlMessageBubble.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View view) { @@ -1007,7 +1487,7 @@ private void setLinkData(LinkMessageViewHolder viewHolder, int i) { } } if (baseMessage.getDeletedAt() == 0) { - HashMap extensionList = Utils.extensionCheck(baseMessage); + HashMap extensionList = Extensions.extensionCheck(baseMessage); if (extensionList!=null) { if (extensionList.containsKey("linkPreview")) { JSONObject linkPreviewJsonObject = extensionList.get("linkPreview"); @@ -1041,6 +1521,69 @@ private void setLinkData(LinkMessageViewHolder viewHolder, int i) { } } + if (baseMessage.getReplyCount()!=0) { + try { + if (baseMessage.getMetadata()!=null && baseMessage.getMetadata().has("replyAvatars")) { + JSONArray jsonArray = baseMessage.getMetadata().getJSONArray("replyAvatars"); + viewHolder.lvReplyAvatar.setVisibility(View.VISIBLE); + for (int m = 0;m { + Intent intent = new Intent(context, CometChatThreadMessageActivity.class); + intent.putExtra(StringContract.IntentStrings.NAME,baseMessage.getSender().getName()); + intent.putExtra(StringContract.IntentStrings.AVATAR,baseMessage.getSender().getAvatar()); + intent.putExtra(StringContract.IntentStrings.REPLY_COUNT,baseMessage.getReplyCount()); + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getSender().getName()); + intent.putExtra(StringContract.IntentStrings.PARENT_ID,baseMessage.getId()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE,baseMessage.getType()); + intent.putExtra(StringContract.IntentStrings.SENTAT,baseMessage.getSentAt()); + if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) + intent.putExtra(StringContract.IntentStrings.TEXTMESSAGE,((TextMessage)baseMessage).getText()); + else { + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME,((MediaMessage)baseMessage).getAttachment().getFileName()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION,((MediaMessage)baseMessage).getAttachment().getFileExtension()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL,((MediaMessage)baseMessage).getAttachment().getFileUrl()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE,((MediaMessage)baseMessage).getAttachment().getFileSize()); + } + intent.putExtra(StringContract.IntentStrings.TYPE,baseMessage.getReceiverType()); + if (baseMessage.getReceiverType().equals(CometChatConstants.RECEIVER_TYPE_GROUP)) { + intent.putExtra(StringContract.IntentStrings.GUID,baseMessage.getReceiverUid()); + } + else { + if (baseMessage.getReceiverUid().equals(loggedInUser.getUid())) + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getSender().getUid()); + else + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getReceiverUid()); + } + context.startActivity(intent); + }); + showMessageTime(viewHolder, baseMessage); String finalUrl = url; viewHolder.linkVisit.setOnClickListener(new View.OnClickListener() { @@ -1175,7 +1718,7 @@ public void onBindHeaderViewHolder(DateItemHolder var1, int var2, long var3) { */ private int getItemViewTypes(int position) { BaseMessage baseMessage = messageList.get(position); - HashMap extensionList = Utils.extensionCheck(baseMessage); + HashMap extensionList = Extensions.extensionCheck(baseMessage); if (baseMessage.getDeletedAt()==0) { if (baseMessage.getCategory().equals(CometChatConstants.CATEGORY_MESSAGE)) { switch (baseMessage.getType()) { @@ -1184,11 +1727,15 @@ private int getItemViewTypes(int position) { if (baseMessage.getSender().getUid().equals(loggedInUser.getUid())) { if (extensionList != null && extensionList.containsKey("linkPreview") && extensionList.get("linkPreview") != null) return RIGHT_LINK_MESSAGE; + else if (baseMessage.getMetadata()!=null && baseMessage.getMetadata().has("reply")) + return RIGHT_REPLY_TEXT_MESSAGE; else return RIGHT_TEXT_MESSAGE; } else { if (extensionList != null && extensionList.containsKey("linkPreview") && extensionList.get("linkPreview") != null) return LEFT_LINK_MESSAGE; + else if (baseMessage.getMetadata()!=null && baseMessage.getMetadata().has("reply")) + return LEFT_REPLY_TEXT_MESSAGE; else return LEFT_TEXT_MESSAGE; } @@ -1353,16 +1900,15 @@ public int getPosition(BaseMessage baseMessage){ class ImageMessageViewHolder extends RecyclerView.ViewHolder { private ImageView imageView; - private CardView cardView; - private ProgressBar progressBar; - private Avatar ivUser; - public TextView txtTime,tvUser; - private RelativeLayout rlMessageBubble; + private TextView tvThreadReplyCount; + private LinearLayout lvReplyAvatar; + + private RelativeLayout sensitiveLayout; public ImageMessageViewHolder(@NonNull View view) { super(view); @@ -1374,7 +1920,9 @@ public ImageMessageViewHolder(@NonNull View view) { txtTime = view.findViewById(R.id.txt_time); ivUser = view.findViewById(R.id.iv_user); rlMessageBubble = view.findViewById(R.id.rl_message); - + tvThreadReplyCount = view.findViewById(R.id.thread_reply_count); + lvReplyAvatar = view.findViewById(R.id.reply_avatar_layout); + sensitiveLayout = view.findViewById(R.id.sensitive_layout); } } @@ -1392,18 +1940,14 @@ public ActionMessageViewHolder(@NonNull View view) { class VideoMessageViewHolder extends RecyclerView.ViewHolder { private ImageView imageView; - private ImageView playBtn; - private CardView cardView; - private ProgressBar progressBar; - private Avatar ivUser; - public TextView txtTime,tvUser; - private RelativeLayout rlMessageBubble; + private TextView tvThreadReplyCount; + private LinearLayout lvReplyAvatar; public VideoMessageViewHolder(@NonNull View view) { super(view); @@ -1416,13 +1960,13 @@ public VideoMessageViewHolder(@NonNull View view) { txtTime = view.findViewById(R.id.txt_time); ivUser = view.findViewById(R.id.iv_user); rlMessageBubble = view.findViewById(R.id.rl_message); - + tvThreadReplyCount = view.findViewById(R.id.thread_reply_count); + lvReplyAvatar = view.findViewById(R.id.reply_avatar_layout); } } public class FileMessageViewHolder extends RecyclerView.ViewHolder { - private TextView fileName; private TextView fileExt; public TextView txtTime; @@ -1431,6 +1975,8 @@ public class FileMessageViewHolder extends RecyclerView.ViewHolder { private View view; private Avatar ivUser; private RelativeLayout rlMessageBubble; + private TextView tvThreadReplyCount; + private LinearLayout lvReplyAvatar; FileMessageViewHolder(@NonNull View itemView) { super(itemView); @@ -1441,6 +1987,8 @@ public class FileMessageViewHolder extends RecyclerView.ViewHolder { txtTime = itemView.findViewById(R.id.txt_time); fileName = itemView.findViewById(R.id.tvFileName); rlMessageBubble = itemView.findViewById(R.id.rl_message); + tvThreadReplyCount = itemView.findViewById(R.id.thread_reply_count); + lvReplyAvatar = itemView.findViewById(R.id.reply_avatar_layout); this.view = itemView; } } @@ -1448,113 +1996,87 @@ public class FileMessageViewHolder extends RecyclerView.ViewHolder { public class DeleteMessageViewHolder extends RecyclerView.ViewHolder { private TextView txtMessage; - private RelativeLayout cardView; - private View view; - public TextView txtTime; - public TextView tvUser; - private ImageView imgStatus; - private int type; - private Avatar ivUser; - private RelativeLayout rlMessageBubble; - + private TextView tvThreadReplyCount; + private LinearLayout lvReplyAvatar; DeleteMessageViewHolder(@NonNull View view) { super(view); - type = (int) view.getTag(); - tvUser = view.findViewById(R.id.tv_user); - txtMessage = view.findViewById(R.id.go_txt_message); - cardView = view.findViewById(R.id.cv_message_container); - txtTime = view.findViewById(R.id.txt_time); - imgStatus = view.findViewById(R.id.img_pending); - ivUser = view.findViewById(R.id.iv_user); - rlMessageBubble = view.findViewById(R.id.rl_message); - + tvThreadReplyCount = view.findViewById(R.id.thread_reply_count); + lvReplyAvatar = view.findViewById(R.id.reply_avatar_layout); this.view = view; - - } } public class TextMessageViewHolder extends RecyclerView.ViewHolder { private TextView txtMessage; - + private TextView tvThreadReplyCount; private RelativeLayout cardView; - private View view; - public TextView txtTime; - public TextView tvUser; - private ImageView imgStatus; - private int type; - private Avatar ivUser; - private RelativeLayout rlMessageBubble; + private RelativeLayout sentimentVw; + + private TextView viewSentimentMessage; + private RelativeLayout replyLayout; + private TextView replyUser; + private TextView replyMessage; + private LinearLayout lvReplyAvatar; TextMessageViewHolder(@NonNull View view) { super(view); type = (int) view.getTag(); - tvUser = view.findViewById(R.id.tv_user); - txtMessage = view.findViewById(R.id.go_txt_message); - cardView = view.findViewById(R.id.cv_message_container); - txtTime = view.findViewById(R.id.txt_time); - imgStatus = view.findViewById(R.id.img_pending); - ivUser = view.findViewById(R.id.iv_user); - rlMessageBubble = view.findViewById(R.id.rl_message); - + replyLayout = view.findViewById(R.id.replyLayout); + replyUser = view.findViewById(R.id.reply_user); + replyMessage = view.findViewById(R.id.reply_message); + tvThreadReplyCount = view.findViewById(R.id.thread_reply_count); + lvReplyAvatar = view.findViewById(R.id.reply_avatar_layout); + sentimentVw = view.findViewById(R.id.sentiment_layout); + viewSentimentMessage = view.findViewById(R.id.view_sentiment); this.view = view; - } } public class CustomMessageViewHolder extends RecyclerView.ViewHolder { private TextView txtMessage; - private RelativeLayout cardView; - private View view; - public TextView txtTime; - public TextView tvUser; - private ImageView imgStatus; - private int type; - private Avatar ivUser; - private RelativeLayout rlMessageBubble; @@ -1562,63 +2084,19 @@ public class CustomMessageViewHolder extends RecyclerView.ViewHolder { super(view); type = (int) view.getTag(); - tvUser = view.findViewById(R.id.tv_user); - txtMessage = view.findViewById(R.id.go_txt_message); - cardView = view.findViewById(R.id.cv_message_container); - txtTime = view.findViewById(R.id.txt_time); - imgStatus = view.findViewById(R.id.img_pending); - ivUser = view.findViewById(R.id.iv_user); - rlMessageBubble = view.findViewById(R.id.rl_message); - this.view = view; - - } } public class AudioMessageViewHolder extends RecyclerView.ViewHolder { -// private TextView audioLength; -// -// private TextView tvUser; -// -// private Avatar ivUser; -// -// private RelativeLayout rlMessageBubble; -// -// private SeekBar audioSeekBar; -// -// private ImageView downloadBtn; -// -// private ImageView playBtn; -// -// private ProgressBar downloadProgress; -// -// private TextView txtTime; -// private int type; -// -// public AudioMessageViewHolder(@NonNull View itemView) { -// super(itemView); -// -// type = (int)itemView.getTag(); -// audioLength = itemView.findViewById(R.id.audioLength); -// rlMessageBubble = itemView.findViewById(R.id.cv_message_container); -// tvUser = itemView.findViewById(R.id.tv_user); -// ivUser = itemView.findViewById(R.id.iv_user); -// txtTime = itemView.findViewById(R.id.txt_time); -// audioSeekBar = itemView.findViewById(R.id.audioSeekBar); -// playBtn = itemView.findViewById(R.id.playBtn); -// downloadBtn = itemView.findViewById(R.id.download); -// downloadProgress = itemView.findViewById(R.id.progressBar); -// } - private TextView length; private ImageView playBtn; private int type; @@ -1626,6 +2104,8 @@ public class AudioMessageViewHolder extends RecyclerView.ViewHolder { private Avatar ivUser; private RelativeLayout rlMessageBubble; private TextView txtTime; + private TextView tvThreadReplyCount; + private LinearLayout lvReplyAvatar; public AudioMessageViewHolder(@NonNull View itemView) { super(itemView); type = (int)itemView.getTag(); @@ -1635,71 +2115,48 @@ public AudioMessageViewHolder(@NonNull View itemView) { tvUser = itemView.findViewById(R.id.tv_user); ivUser = itemView.findViewById(R.id.iv_user); txtTime = itemView.findViewById(R.id.txt_time); + tvThreadReplyCount = itemView.findViewById(R.id.thread_reply_count); + lvReplyAvatar = itemView.findViewById(R.id.reply_avatar_layout); } } public class LinkMessageViewHolder extends RecyclerView.ViewHolder { private TextView linkTitle; - private TextView linkVisit; - private TextView linkSubtitle; - private TextView message; - private ImageView videoLink; - private RelativeLayout cardView; - private View view; - public TextView txtTime; - private ImageView imgStatus; - private ImageView linkImg; - private int type; - private TextView tvUser; - private Avatar ivUser; - private RelativeLayout rlMessageBubble; - + private TextView tvThreadReplyCount; + private LinearLayout lvReplyAvatar; LinkMessageViewHolder(@NonNull View view) { super(view); type = (int) view.getTag(); - tvUser = view.findViewById(R.id.tv_user); - linkTitle = view.findViewById(R.id.link_title); - linkSubtitle = view.findViewById(R.id.link_subtitle); - linkVisit = view.findViewById(R.id.visitLink); - linkImg = view.findViewById(R.id.link_img); - message = view.findViewById(R.id.message); - videoLink = view.findViewById(R.id.videoLink); - cardView = view.findViewById(R.id.cv_message_container); - txtTime = view.findViewById(R.id.txt_time); - imgStatus = view.findViewById(R.id.img_pending); - ivUser = view.findViewById(R.id.iv_user); - rlMessageBubble = view.findViewById(R.id.rl_message); - + tvThreadReplyCount = view.findViewById(R.id.thread_reply_count); + lvReplyAvatar = view.findViewById(R.id.reply_avatar_layout); this.view = view; - - } } diff --git a/uikit/src/main/java/adapter/SharedMediaAdapter.java b/uikit/src/main/java/adapter/SharedMediaAdapter.java index a50071a7..e33736bc 100644 --- a/uikit/src/main/java/adapter/SharedMediaAdapter.java +++ b/uikit/src/main/java/adapter/SharedMediaAdapter.java @@ -1,17 +1,24 @@ package adapter; +import android.app.AlertDialog; import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Bitmap; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; +import android.widget.RelativeLayout; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.databinding.DataBindingUtil; import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.SimpleTarget; +import com.bumptech.glide.request.transition.Transition; import com.cometchat.pro.constants.CometChatConstants; import com.cometchat.pro.models.BaseMessage; import com.cometchat.pro.models.MediaMessage; @@ -23,7 +30,10 @@ import java.util.List; import listeners.StickyHeaderAdapter; +import utils.Extensions; import utils.FontUtils; +import utils.MediaUtils; +import utils.Utils; /** * Purpose - UserListAdapter is a subclass of RecyclerView Adapter which is used to display @@ -138,21 +148,79 @@ public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) private void setVideoData(VideoViewHolder viewHolder, int i) { BaseMessage message = messageArrayList.get(i); - Glide.with(context).load(((MediaMessage) message).getAttachment().getFileUrl()).into(viewHolder.imageView); - viewHolder.itemView.setTag(R.string.baseMessage, message); + Glide.with(context).load(((MediaMessage) message).getAttachment().getFileUrl()).into(viewHolder.imageView); + viewHolder.imageView.setOnClickListener(view ->{ + MediaUtils.openFile(((MediaMessage) message).getAttachment().getFileUrl(), context); + }); + viewHolder.itemView.setTag(R.string.baseMessage, message); } private void setFileData(FileViewHolder viewHolder, int i) { BaseMessage message = messageArrayList.get(i); - viewHolder.fileName.setText(((MediaMessage) message).getAttachment().getFileName()); - viewHolder.fileExtension.setText(((MediaMessage) message).getAttachment().getFileExtension()); - viewHolder.itemView.setTag(R.string.baseMessage, message); + viewHolder.fileName.setText(((MediaMessage) message).getAttachment().getFileName()); + viewHolder.fileExtension.setText(((MediaMessage) message).getAttachment().getFileExtension()); + viewHolder.itemView.setOnClickListener(view -> { + MediaUtils.openFile(((MediaMessage) message).getAttachment().getFileUrl(), context); + }); + viewHolder.itemView.setTag(R.string.baseMessage, message); } private void setImageData(ImageViewHolder viewHolder, int i) { BaseMessage message = messageArrayList.get(i); - Glide.with(context).load(((MediaMessage) message).getAttachment().getFileUrl()).into(viewHolder.imageView); + boolean isImageNotSafe = Extensions.getImageModeration(context,message); + String smallUrl = Extensions.getThumbnailGeneration(context,message); + + if (smallUrl!=null) { + Glide.with(context).asBitmap().load(smallUrl).into(new SimpleTarget() { + @Override + public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition transition) { + if (isImageNotSafe) + viewHolder.imageView.setImageBitmap(Utils.blur(context,resource)); + else + viewHolder.imageView.setImageBitmap(resource); + } + }); + } else { + Glide.with(context).asBitmap().load(((MediaMessage)message).getAttachment().getFileUrl()).into(new SimpleTarget() { + @Override + public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition transition) { + if (isImageNotSafe) + viewHolder.imageView.setImageBitmap(Utils.blur(context,resource)); + else + viewHolder.imageView.setImageBitmap(resource); + } + }); + } + if (isImageNotSafe) { + viewHolder.sensitiveLayout.setVisibility(View.VISIBLE); + } else { + viewHolder.sensitiveLayout.setVisibility(View.GONE); + } + viewHolder.imageView.setOnClickListener(view -> { + if (isImageNotSafe) { + AlertDialog.Builder alert = new AlertDialog.Builder(context); + alert.setTitle("Unsafe Content"); + alert.setIcon(R.drawable.ic_hand); + alert.setMessage("Are you surely want to see this unsafe content"); + alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + MediaUtils.openFile(((MediaMessage) message).getAttachment().getFileUrl(), context); + } + }); + alert.setNegativeButton("No", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + alert.create().show(); + } else { + MediaUtils.openFile(((MediaMessage) message).getAttachment().getFileUrl(), context); + } + + }); viewHolder.itemView.setTag(R.string.baseMessage, message); } @@ -169,10 +237,12 @@ public void updateMessageList(List baseMessageList) { class ImageViewHolder extends RecyclerView.ViewHolder { private ImageView imageView; + private RelativeLayout sensitiveLayout; public ImageViewHolder(@NonNull View itemView) { super(itemView); imageView = itemView.findViewById(R.id.imageView); + sensitiveLayout = itemView.findViewById(R.id.sensitive_layout); } } diff --git a/uikit/src/main/java/adapter/ThreadAdapter.java b/uikit/src/main/java/adapter/ThreadAdapter.java new file mode 100644 index 00000000..f0b6518e --- /dev/null +++ b/uikit/src/main/java/adapter/ThreadAdapter.java @@ -0,0 +1,1386 @@ +package adapter; + +import android.app.AlertDialog; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.res.ColorStateList; +import android.graphics.Bitmap; +import android.graphics.Color; +import android.graphics.PorterDuff; +import android.graphics.Typeface; +import android.graphics.drawable.ColorDrawable; +import android.media.MediaPlayer; +import android.net.Uri; +import android.text.Spannable; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.cardview.widget.CardView; +import androidx.emoji.text.EmojiCompat; +import androidx.emoji.text.EmojiSpan; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.request.target.SimpleTarget; +import com.bumptech.glide.request.transition.Transition; +import com.cometchat.pro.constants.CometChatConstants; +import com.cometchat.pro.core.Call; +import com.cometchat.pro.core.CometChat; +import com.cometchat.pro.models.Action; +import com.cometchat.pro.models.BaseMessage; +import com.cometchat.pro.models.MediaMessage; +import com.cometchat.pro.models.MessageReceipt; +import com.cometchat.pro.models.TextMessage; +import com.cometchat.pro.models.User; +import com.cometchat.pro.uikit.Avatar; +import com.cometchat.pro.uikit.R; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; + +import constant.StringContract; +import listeners.StickyHeaderAdapter; +import screen.threadconversation.CometChatThreadMessageActivity; +import utils.Extensions; +import utils.FontUtils; +import utils.MediaUtils; +import utils.Utils; +import utils.ZoomIv; + +/** + * Purpose - ThreadeAdapter is a subclass of RecyclerView Adapter which is used to display + * the list of messages in thread. It helps to organize the messages based on its type i.e TextMessage, + * MediaMessage, Actions. It also helps to manage whether message is sent or recieved and organizes + * view based on it. It is single adapter used to manage group thread messages and user thread messages. + * + * Created on - 17th July 2020 + * + * Modified on - 17th July 2020 + * + */ + + +public class ThreadAdapter extends RecyclerView.Adapter {// implements StickyHeaderAdapter { + + private static final int IMAGE_MESSAGE = 11; + + private static final int VIDEO_MESSAGE = 12; + + private static final int AUDIO_MESSAGE = 13; + + private List messageList = new ArrayList<>(); + + private static final int TEXT_MESSAGE = 14; + + private static final int REPLY_TEXT_MESSAGE = 15; + + private static final int FILE_MESSAGE = 16; + + private static final int LINK_MESSAGE = 17; + + private static final int DELETE_MESSAGE = 18; + + private static final int CUSTOM_MESSAGE = 19; + + public Context context; + + private User loggedInUser = CometChat.getLoggedInUser(); + + private boolean isLongClickEnabled; + + private List selectedItemList = new ArrayList<>(); + + public List longselectedItemList = new ArrayList<>(); + + private FontUtils fontUtils; + + private MediaPlayer mediaPlayer; + + private int messagePosition=0; + + private OnMessageLongClick messageLongClick; + + private String TAG = "MessageAdapter"; + + private boolean isSent; + + private boolean isTextMessageClick; + + private boolean isImageMessageClick; + /** + * It is used to initialize the adapter wherever we needed. It has parameter like messageList + * which contains list of messages and it will be used in adapter and paramter type is a String + * whose values will be either CometChatConstants.RECEIVER_TYPE_USER + * CometChatConstants.RECEIVER_TYPE_GROUP. + * + * + * @param context is a object of Context. + * @param messageList is a list of messages used in this adapter. + * @param type is a String which identifies whether it is a user messages or a group messages. + * + */ + public ThreadAdapter(Context context, List messageList, String type) { + setMessageList(messageList); + this.context = context; + try { + messageLongClick = (CometChatThreadMessageActivity)context; + }catch (Exception e) { + e.printStackTrace(); + } + + if (null == mediaPlayer) { + mediaPlayer = new MediaPlayer(); + } + + fontUtils=FontUtils.getInstance(context); + } + + /** + * This method is used to return the different view types to adapter based on item position. + * It uses getItemViewTypes() method to identify the view type of item. + * @see ThreadAdapter#getItemViewTypes(int) + * * + * @param position is a position of item in recyclerView. + * @return It returns int which is value of view type of item. + * @see ThreadAdapter#onCreateViewHolder(ViewGroup, int) + */ + @Override + public int getItemViewType(int position) { + return getItemViewTypes(position); + } + + private void setMessageList(List messageList) { + this.messageList.addAll(0, messageList); + notifyItemRangeInserted(0,messageList.size()); + + } + + + /** + * This method is used to inflate the view for item based on its viewtype. + * It helps to differentiate view for different type of messages. + * Based on view type it returns various ViewHolder + * Ex :- For MediaMessage it will return ImageMessageViewHolder, + * For TextMessage it will return TextMessageViewHolder,etc. + * + * @param parent is a object of ViewGroup. + * @param i is viewType based on it various view will be inflated by adapter for various type + * of messages. + * @return It return different ViewHolder for different viewType. + */ + @NonNull + @Override + public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) { + + View view; + switch (i) { + case DELETE_MESSAGE: + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.thread_message_item,parent,false); + view.setTag(DELETE_MESSAGE); + return new DeleteMessageViewHolder(view); + case TEXT_MESSAGE: + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.thread_message_item, parent, false); + view.setTag(TEXT_MESSAGE); + return new TextMessageViewHolder(view); + + case REPLY_TEXT_MESSAGE: + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.thread_message_item, parent, false); + view.setTag(REPLY_TEXT_MESSAGE); + return new TextMessageViewHolder(view); + + case LINK_MESSAGE: + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.thread_message_link_item,parent,false); + view.setTag(LINK_MESSAGE); + return new LinkMessageViewHolder(view); + + case AUDIO_MESSAGE: + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.thread_message_audio_layout,parent,false); + view.setTag(AUDIO_MESSAGE); + return new AudioMessageViewHolder(view); + + case IMAGE_MESSAGE: + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.thread_message_image_item, parent, false); + view.setTag(IMAGE_MESSAGE); + return new ImageMessageViewHolder(view); + + case VIDEO_MESSAGE: + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.thread_message_video_item,parent,false); + view.setTag(VIDEO_MESSAGE); + return new VideoMessageViewHolder(view); + + case FILE_MESSAGE: + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.thread_message_file_item, parent, false); + view.setTag(FILE_MESSAGE); + return new FileMessageViewHolder(view); + + case CUSTOM_MESSAGE: + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.thread_message_item, parent, false); + view.setTag(TEXT_MESSAGE); + return new CustomMessageViewHolder(view); + default: + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.thread_message_item, parent, false); + view.setTag(-1); + return new TextMessageViewHolder(view); + } + } + + + /** + * This method is used to bind the various ViewHolder content with their respective view types. + * Here different methods are being called for different view type and in each method different + * ViewHolder are been passed as parameter along with position of item. + * + * Ex :- For TextMessage setTextData((TextMessageViewHolder)viewHolder,i) is been called. + * where viewHolder is casted as TextMessageViewHolder and i is position of item. + * + * @see ThreadAdapter#setTextData(TextMessageViewHolder, int) + * @see ThreadAdapter#setImageData(ImageMessageViewHolder, int) + * @see ThreadAdapter#setFileData(FileMessageViewHolder, int) + * + * @param viewHolder is a object of RecyclerViewHolder. + * @param i is position of item in recyclerView. + */ + @Override + public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) { + BaseMessage baseMessage = messageList.get(i); + switch (viewHolder.getItemViewType()) { + + case DELETE_MESSAGE: + setDeleteData((DeleteMessageViewHolder)viewHolder,i); + break; + case TEXT_MESSAGE: + case REPLY_TEXT_MESSAGE: + setTextData((TextMessageViewHolder) viewHolder, i); + break; + case LINK_MESSAGE: + setLinkData((LinkMessageViewHolder) viewHolder,i); + break; + case IMAGE_MESSAGE: + setImageData((ImageMessageViewHolder) viewHolder, i); + break; + case AUDIO_MESSAGE: + setAudioData((AudioMessageViewHolder) viewHolder,i); + break; + case VIDEO_MESSAGE: + setVideoData((VideoMessageViewHolder) viewHolder,i); + break; + case FILE_MESSAGE: + setFileData((FileMessageViewHolder) viewHolder, i); + break; + case CUSTOM_MESSAGE: + setCustomData((CustomMessageViewHolder) viewHolder, i); + break; + + + } + } + + private void setAudioData(AudioMessageViewHolder viewHolder, int i) { + BaseMessage baseMessage = messageList.get(i); + if (baseMessage!=null&&baseMessage.getDeletedAt()==0) { + viewHolder.playBtn.setImageTintList(ColorStateList.valueOf(context.getResources().getColor(R.color.textColorWhite))); + setAvatar(viewHolder.ivUser, baseMessage.getSender().getAvatar(), baseMessage.getSender().getName()); + viewHolder.tvUser.setText(baseMessage.getSender().getName()); + + + showMessageTime(viewHolder,baseMessage); +// if (selectedItemList.contains(baseMessage.getId())) +// viewHolder.txtTime.setVisibility(View.VISIBLE); +// else +// viewHolder.txtTime.setVisibility(View.GONE); + + viewHolder.length.setText(Utils.getFileSize(((MediaMessage)baseMessage).getAttachment().getFileSize())); + viewHolder.playBtn.setImageResource(R.drawable.ic_play_arrow_black_24dp); + viewHolder.playBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { +// MediaUtils.openFile(((MediaMessage) baseMessage).getAttachment().getFileUrl(),context); + mediaPlayer.reset(); + if (messagePosition!=i) { + notifyItemChanged(messagePosition); + messagePosition = i; + } + try { + mediaPlayer.setDataSource(((MediaMessage)baseMessage).getAttachment().getFileUrl()); + mediaPlayer.prepare(); + mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { + @Override + public void onCompletion(MediaPlayer mp) { + viewHolder.playBtn.setImageResource(R.drawable.ic_play_arrow_black_24dp); + } + }); + } catch (Exception e) { + Log.e(TAG, "MediaPlayerError: "+e.getMessage()); + } + if (!mediaPlayer.isPlaying()) { + mediaPlayer.start(); + viewHolder.playBtn.setImageResource(R.drawable.ic_pause_24dp); + } else { + mediaPlayer.pause(); + viewHolder.playBtn.setImageResource(R.drawable.ic_play_arrow_black_24dp); + } + } + }); + viewHolder.rlMessageBubble.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + if (!isLongClickEnabled && !isTextMessageClick) { + isImageMessageClick = true; + setLongClickSelectedItem(baseMessage); + messageLongClick.setLongMessageClick(longselectedItemList); + notifyDataSetChanged(); + } + return true; + } + }); + } + } + + public void stopPlayingAudio() { + if (mediaPlayer!=null) + mediaPlayer.stop(); + } + /** + * This method is called whenever viewType of item is file. It is used to bind FileMessageViewHolder + * contents with MediaMessage at a given position. + * It shows FileName, FileType, FileSize. + * + * @param viewHolder is a object of FileMessageViewHolder. + * @param i is a position of item in recyclerView. + * @see MediaMessage + * @see BaseMessage + */ + private void setFileData(FileMessageViewHolder viewHolder, int i) { + BaseMessage baseMessage = messageList.get(i); + + if (baseMessage!=null&&baseMessage.getDeletedAt()==0) { + setAvatar(viewHolder.ivUser, baseMessage.getSender().getAvatar(), baseMessage.getSender().getName()); + viewHolder.tvUser.setText(baseMessage.getSender().getName()); + + viewHolder.fileName.setText(((MediaMessage) baseMessage).getAttachment().getFileName()); + viewHolder.fileExt.setText(((MediaMessage) baseMessage).getAttachment().getFileExtension()); + int fileSize = ((MediaMessage) baseMessage).getAttachment().getFileSize(); + + viewHolder.fileSize.setText(Utils.getFileSize(fileSize)); + + showMessageTime(viewHolder, baseMessage); + +// if (selectedItemList.contains(baseMessage.getId())) +// viewHolder.txtTime.setVisibility(View.VISIBLE); +// else +// viewHolder.txtTime.setVisibility(View.GONE); + + + viewHolder.rlMessageBubble.setOnClickListener(view -> { +// if (isLongClickEnabled && !isTextMessageClick) { +// setLongClickSelectedItem(baseMessage); +// } +// else { + setSelectedMessage(baseMessage.getId()); +// } + notifyDataSetChanged(); + }); + viewHolder.fileName.setOnClickListener(view -> MediaUtils.openFile(((MediaMessage) baseMessage).getAttachment().getFileUrl(),context)); + viewHolder.rlMessageBubble.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + if (!isLongClickEnabled && !isTextMessageClick) { + isImageMessageClick = true; + setLongClickSelectedItem(baseMessage); + messageLongClick.setLongMessageClick(longselectedItemList); + notifyDataSetChanged(); + } + return true; + } + }); + } + } + + + /** + * This method is called whenever viewType of item is media. It is used to bind ImageMessageViewHolder + * contents with MediaMessage at a given position. + * It loads image of MediaMessage using its url. + * + * @param viewHolder is a object of ImageMessageViewHolder. + * @param i is a position of item in recyclerView. + * @see MediaMessage + * @see BaseMessage + */ + private void setImageData(ImageMessageViewHolder viewHolder, int i) { + + + BaseMessage baseMessage = messageList.get(i); + + setAvatar(viewHolder.ivUser, baseMessage.getSender().getAvatar(), baseMessage.getSender().getName()); + viewHolder.tvUser.setText(baseMessage.getSender().getName()); + + boolean isImageNotSafe = Extensions.getImageModeration(context,baseMessage); + String smallUrl = Extensions.getThumbnailGeneration(context,baseMessage); + viewHolder.imageView.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_defaulf_image)); + if (smallUrl!=null) { + Glide.with(context).asBitmap().diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true).load(smallUrl).into(new SimpleTarget() { + @Override + public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition transition) { + if (isImageNotSafe) + viewHolder.imageView.setImageBitmap(Utils.blur(context,resource)); + else + viewHolder.imageView.setImageBitmap(resource); + } + }); + } else { + Glide.with(context).asBitmap().diskCacheStrategy(DiskCacheStrategy.NONE).skipMemoryCache(true).load(((MediaMessage)baseMessage).getAttachment().getFileUrl()).into(new SimpleTarget() { + @Override + public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition transition) { + if (isImageNotSafe) + viewHolder.imageView.setImageBitmap(Utils.blur(context,resource)); + else + viewHolder.imageView.setImageBitmap(resource); + } + }); + } + if (isImageNotSafe) { + viewHolder.sensitiveLayout.setVisibility(View.VISIBLE); + } else { + viewHolder.sensitiveLayout.setVisibility(View.GONE); + } + showMessageTime(viewHolder, baseMessage); +// if (selectedItemList.contains(baseMessage.getId())) +// viewHolder.txtTime.setVisibility(View.VISIBLE); +// else +// viewHolder.txtTime.setVisibility(View.GONE); + + + + viewHolder.rlMessageBubble.setOnClickListener(view -> { + if (isImageNotSafe) { + AlertDialog.Builder alert = new AlertDialog.Builder(context); + alert.setTitle("Unsafe Content"); + alert.setIcon(R.drawable.ic_hand); + alert.setMessage("Are you surely want to see this unsafe content"); + alert.setPositiveButton("Yes", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + MediaUtils.openFile(((MediaMessage) baseMessage).getAttachment().getFileUrl(), context); + } + }); + alert.setNegativeButton("No", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + alert.create().show(); + } else { + setSelectedMessage(baseMessage.getId()); + notifyDataSetChanged(); + MediaUtils.openFile(((MediaMessage) baseMessage).getAttachment().getFileUrl(), context); + } + + }); + viewHolder.rlMessageBubble.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + if (!isLongClickEnabled && !isTextMessageClick) { + isImageMessageClick = true; + setLongClickSelectedItem(baseMessage); + messageLongClick.setLongMessageClick(longselectedItemList); + notifyDataSetChanged(); + } + return true; + } + }); + } + + private void displayImage(BaseMessage baseMessage) { + Dialog imageDialog = new Dialog(context); + View messageVw = LayoutInflater.from(context).inflate(R.layout.image_dialog_view, null); + ZoomIv imageView = messageVw.findViewById(R.id.imageView); + Glide.with(context).asBitmap().load(((MediaMessage) baseMessage).getAttachment().getFileUrl()).into(new SimpleTarget() { + @Override + public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition transition) { + imageView.setImageBitmap(resource); + } + }); + imageDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + imageDialog.setContentView(messageVw); + imageDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); + imageDialog.show(); + } + + + private void setVideoData(VideoMessageViewHolder viewHolder, int i) { + + + BaseMessage baseMessage = messageList.get(i); + + setAvatar(viewHolder.ivUser, baseMessage.getSender().getAvatar(), baseMessage.getSender().getName()); + viewHolder.tvUser.setText(baseMessage.getSender().getName()); + + if (((MediaMessage)baseMessage).getAttachment()!=null) + Glide.with(context).load(((MediaMessage) baseMessage).getAttachment().getFileUrl()).into(viewHolder.imageView); + + showMessageTime(viewHolder, baseMessage); +// if (selectedItemList.contains(baseMessage.getId())) +// viewHolder.txtTime.setVisibility(View.VISIBLE); +// else +// viewHolder.txtTime.setVisibility(View.GONE); +// + + + viewHolder.rlMessageBubble.setOnClickListener(view -> { + setSelectedMessage(baseMessage.getId()); + notifyDataSetChanged(); + + }); + viewHolder.rlMessageBubble.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View v) { + if (!isLongClickEnabled && !isTextMessageClick) { + isImageMessageClick = true; + setLongClickSelectedItem(baseMessage); + messageLongClick.setLongMessageClick(longselectedItemList); + notifyDataSetChanged(); + } + return true; + } + }); + viewHolder.playBtn.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + MediaUtils.openFile(((MediaMessage)baseMessage).getAttachment().getFileUrl(),context); + } + }); + } + + + + + + private void setDeleteData(DeleteMessageViewHolder viewHolder, int i) { + + + BaseMessage baseMessage = messageList.get(i); + + setAvatar(viewHolder.ivUser, baseMessage.getSender().getAvatar(), baseMessage.getSender().getName()); + viewHolder.tvUser.setText(baseMessage.getSender().getName()); + + if (baseMessage.getDeletedAt()!=0) { + viewHolder.txtMessage.setText(R.string.message_deleted); + viewHolder.txtMessage.setTextColor(context.getResources().getColor(R.color.secondaryTextColor)); + viewHolder.txtMessage.setTypeface(null, Typeface.ITALIC); + } + showMessageTime(viewHolder, baseMessage); + +// if (selectedItemList.contains(baseMessage.getId())) +// viewHolder.txtTime.setVisibility(View.VISIBLE); +// else +// viewHolder.txtTime.setVisibility(View.GONE); +// + } + + + + + /** + * This method is used to show message time below message whenever we click on message. + * Since we have different ViewHolder, we have to pass txtTime of each viewHolder to + * setStatusIcon(RecyclerView.ViewHolder viewHolder,BaseMessage baseMessage) + * along with baseMessage. + * @see ThreadAdapter#setStatusIcon(TextView, BaseMessage) + * * + * @param viewHolder is object of ViewHolder. + * @param baseMessage is a object of BaseMessage. + * + * @see BaseMessage + */ + private void showMessageTime(RecyclerView.ViewHolder viewHolder, BaseMessage baseMessage) { + + if (viewHolder instanceof TextMessageViewHolder) { + setStatusIcon(((TextMessageViewHolder) viewHolder).txtTime, baseMessage); + } else if (viewHolder instanceof LinkMessageViewHolder) { + setStatusIcon(((LinkMessageViewHolder) viewHolder).txtTime, baseMessage); + } else if (viewHolder instanceof ImageMessageViewHolder) { + setStatusIcon(((ImageMessageViewHolder) viewHolder).txtTime, baseMessage); + } else if (viewHolder instanceof FileMessageViewHolder) { + setStatusIcon(((FileMessageViewHolder) viewHolder).txtTime, baseMessage); + } + + } + + /** + * This method is used set message time i.e sentAt, deliveredAt & readAt in txtTime. + * If sender of baseMessage is user then for user side messages it will show readAt, deliveredAt + * time along with respective icon. For reciever side message it will show only deliveredAt time + * + * @param txtTime is a object of TextView which will show time. + * @param baseMessage is a object of BaseMessage used to identify baseMessage sender. + * @see BaseMessage + */ + private void setStatusIcon(TextView txtTime, BaseMessage baseMessage) { + if (baseMessage.getSender().getUid().equals(loggedInUser.getUid())) { + if (baseMessage.getReadAt() != 0) { + txtTime.setText(Utils.getHeaderDate(baseMessage.getReadAt() * 1000)); +// txtTime.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_double_tick, 0); + txtTime.setCompoundDrawablePadding(10); + } else if (baseMessage.getDeliveredAt() != 0) { + txtTime.setText(Utils.getHeaderDate(baseMessage.getDeliveredAt() * 1000)); +// txtTime.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_done_all_black_24dp, 0); + txtTime.setCompoundDrawablePadding(10); + } else { + txtTime.setText(Utils.getHeaderDate(baseMessage.getSentAt() * 1000)); +// txtTime.setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_check_black_24dp, 0); + txtTime.setCompoundDrawablePadding(10); + } + } else { + txtTime.setText(Utils.getHeaderDate(baseMessage.getSentAt() * 1000)); + } + } + + /** + * This method is called whenever viewType of item is TextMessage. It is used to bind + * TextMessageViewHolder content with TextMessage at given position. + * It shows text of a message if deletedAt = 0 else it shows "message deleted" + * + * @param viewHolder is a object of TextMessageViewHolder. + * @param i is postion of item in recyclerView. + * @see TextMessage + * @see BaseMessage + */ + private void setTextData(TextMessageViewHolder viewHolder, int i) { + + BaseMessage baseMessage = messageList.get(i); + if (baseMessage!=null) { + if (!baseMessage.getSender().getUid().equals(loggedInUser.getUid())) { + boolean isSentimentNegative = Extensions.checkSentiment(baseMessage); + if (isSentimentNegative) { + viewHolder.txtMessage.setVisibility(View.GONE); + viewHolder.sentimentVw.setVisibility(View.VISIBLE); + } + else { + viewHolder.txtMessage.setVisibility(View.VISIBLE); + viewHolder.sentimentVw.setVisibility(View.GONE); + } + viewHolder.viewSentimentMessage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + AlertDialog.Builder sentimentAlert = new AlertDialog.Builder(context) + .setTitle(context.getResources().getString(R.string.sentiment_alert)) + .setMessage(context.getResources().getString(R.string.sentiment_alert_message)) + .setPositiveButton(context.getResources().getString(R.string.yes), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + viewHolder.txtMessage.setVisibility(View.VISIBLE); + viewHolder.sentimentVw.setVisibility(View.GONE); + } + }) + .setNegativeButton(context.getResources().getString(R.string.cancel), new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + } + }); + sentimentAlert.create().show(); + } + }); + } else { + viewHolder.txtMessage.setVisibility(View.VISIBLE); + viewHolder.sentimentVw.setVisibility(View.GONE); + } + setAvatar(viewHolder.ivUser, baseMessage.getSender().getAvatar(), baseMessage.getSender().getName()); + viewHolder.tvUser.setText(baseMessage.getSender().getName()); + + String txtMessage = ((TextMessage) baseMessage).getText().trim(); + viewHolder.txtMessage.setTextSize(16f); + int count = 0; + CharSequence processed = EmojiCompat.get().process(txtMessage, 0, + txtMessage.length() -1, Integer.MAX_VALUE, EmojiCompat.REPLACE_STRATEGY_ALL); + if (processed instanceof Spannable) { + Spannable spannable = (Spannable) processed; + count = spannable.getSpans(0, spannable.length() - 1, EmojiSpan.class).length; + if (Utils.removeEmojiAndSymbol(txtMessage).trim().length() == 0) { + if (count == 1) { + viewHolder.txtMessage.setTextSize((int) Utils.dpToPx(context, 32)); + } else if (count == 2) { + viewHolder.txtMessage.setTextSize((int) Utils.dpToPx(context, 24)); + } + } + } + + viewHolder.txtMessage.setText(txtMessage); + String profanityFilter = Extensions.checkProfanityMessage(baseMessage); + viewHolder.txtMessage.setText(profanityFilter); + viewHolder.txtMessage.setTypeface(fontUtils.getTypeFace(FontUtils.robotoRegular)); + + viewHolder.txtMessage.setTextColor(context.getResources().getColor(R.color.primaryTextColor)); + + showMessageTime(viewHolder, baseMessage); + if (messageList.get(messageList.size()-1).equals(baseMessage)) + { + selectedItemList.add(baseMessage.getId()); + } + + setColorFilter(baseMessage,viewHolder.cardView); + + viewHolder.rlMessageBubble.setOnClickListener(view -> { + if (isLongClickEnabled && !isImageMessageClick) { + setLongClickSelectedItem(baseMessage); + messageLongClick.setLongMessageClick(longselectedItemList); + } + else { + setSelectedMessage(baseMessage.getId()); + } + notifyDataSetChanged(); + + }); + + viewHolder.rlMessageBubble.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View view) { + if (!isImageMessageClick) { + isLongClickEnabled = true; + isTextMessageClick = true; + setLongClickSelectedItem(baseMessage); + messageLongClick.setLongMessageClick(longselectedItemList); + notifyDataSetChanged(); + } + return true; + } + }); + viewHolder.itemView.setTag(R.string.message, baseMessage); + } + } + + + private void setCustomData(CustomMessageViewHolder viewHolder, int i) { + + BaseMessage baseMessage = messageList.get(i); + if (baseMessage!=null) { + setAvatar(viewHolder.ivUser, baseMessage.getSender().getAvatar(), baseMessage.getSender().getName()); + viewHolder.tvUser.setText(baseMessage.getSender().getName()); + + viewHolder.txtMessage.setText(context.getResources().getString(R.string.custom_message)); + viewHolder.txtMessage.setTypeface(fontUtils.getTypeFace(FontUtils.robotoLight)); + viewHolder.txtMessage.setTextColor(context.getResources().getColor(R.color.primaryTextColor)); + + showMessageTime(viewHolder, baseMessage); + if (messageList.get(messageList.size()-1).equals(baseMessage)) + { + selectedItemList.add(baseMessage.getId()); + } + if (selectedItemList.contains(baseMessage.getId())) + viewHolder.txtTime.setVisibility(View.VISIBLE); + else + viewHolder.txtTime.setVisibility(View.GONE); + + viewHolder.rlMessageBubble.setOnClickListener(view -> { + setSelectedMessage(baseMessage.getId()); + notifyDataSetChanged(); + + }); + viewHolder.itemView.setTag(R.string.message, baseMessage); + } + } + + private void setColorFilter(BaseMessage baseMessage,View view){ + + if (!longselectedItemList.contains(baseMessage)) + { + view.getBackground().setColorFilter(context.getResources().getColor(R.color.message_bubble_grey), PorterDuff.Mode.SRC_ATOP); + } else { + view.getBackground().setColorFilter(context.getResources().getColor(R.color.secondaryTextColor), PorterDuff.Mode.SRC_ATOP); + } + + } + + + private void setLinkData(LinkMessageViewHolder viewHolder, int i) { + + BaseMessage baseMessage = messageList.get(i); + + String url = null; + + if (baseMessage!=null) { + + setAvatar(viewHolder.ivUser, baseMessage.getSender().getAvatar(), baseMessage.getSender().getName()); + viewHolder.tvUser.setText(baseMessage.getSender().getName()); + + if (baseMessage.getDeletedAt() == 0) { + HashMap extensionList = Extensions.extensionCheck(baseMessage); + if (extensionList!=null) { + if (extensionList.containsKey("linkPreview")) { + JSONObject linkPreviewJsonObject = extensionList.get("linkPreview"); + try { + String description = linkPreviewJsonObject.getString("description"); + String image = linkPreviewJsonObject.getString("image"); + String title = linkPreviewJsonObject.getString("title"); + url = linkPreviewJsonObject.getString("url"); + Log.e("setLinkData: ", baseMessage.toString() + "\n\n" + url + "\n" + description + "\n" + image); + viewHolder.linkTitle.setText(title); + viewHolder.linkSubtitle.setText(description); + Glide.with(context).load(Uri.parse(image)).timeout(1000).into(viewHolder.linkImg); + if (url.contains("youtu.be") || url.contains("youtube")) { + viewHolder.videoLink.setVisibility(View.VISIBLE); + viewHolder.linkVisit.setText(context.getResources().getString(R.string.view_on_youtube)); + } else { + viewHolder.videoLink.setVisibility(View.GONE); + viewHolder.linkVisit.setText(context.getResources().getString(R.string.visit)); + } + String messageStr = ((TextMessage) baseMessage).getText(); + if (((TextMessage) baseMessage).getText().equals(url) || ((TextMessage) baseMessage).getText().equals(url + "/")) { + viewHolder.message.setVisibility(View.GONE); + } else { + viewHolder.message.setVisibility(View.VISIBLE); + } + viewHolder.message.setText(messageStr); + } catch (Exception e) { + Log.e("setLinkData: ", e.getMessage()); + } + } + } + } + + showMessageTime(viewHolder, baseMessage); + String finalUrl = url; + viewHolder.linkVisit.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + + if (finalUrl != null) { + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(finalUrl)); + context.startActivity(intent); + } + } + }); +// if (selectedItemList.contains(baseMessage.getId())) +// viewHolder.txtTime.setVisibility(View.VISIBLE); +// else +// viewHolder.txtTime.setVisibility(View.GONE); +// if (i < selectedItems.length && selectedItems[i] == 0) { +// viewHolder.txtTime.setVisibility(View.GONE); +// } else +// viewHolder.txtTime.setVisibility(View.VISIBLE); + + viewHolder.rlMessageBubble.setOnClickListener(view -> { + if (isLongClickEnabled && !isImageMessageClick) { + setLongClickSelectedItem(baseMessage); + messageLongClick.setLongMessageClick(longselectedItemList); + } + else { + setSelectedMessage(baseMessage.getId()); + } + notifyDataSetChanged(); + + }); + viewHolder.rlMessageBubble.setOnLongClickListener(new View.OnLongClickListener() { + @Override + public boolean onLongClick(View view) { + if (!isImageMessageClick) { + isLongClickEnabled = true; + isTextMessageClick = true; + setLongClickSelectedItem(baseMessage); + messageLongClick.setLongMessageClick(longselectedItemList); + notifyDataSetChanged(); + } + return true; + } + }); + viewHolder.itemView.setTag(R.string.message, baseMessage); + } + } + + public void setSelectedMessage(Integer id) + { + if (selectedItemList.contains(id)) + selectedItemList.remove(id); + else + selectedItemList.add(id); + } + + public void setLongClickSelectedItem(BaseMessage baseMessage) { + + + if (longselectedItemList.contains(baseMessage)) + longselectedItemList.remove(baseMessage); + else + longselectedItemList.add(baseMessage); + } + /** + * This method is used to set avatar of groupMembers to show in groupMessages. If avatar of + * group member is not available then it calls setInitials(String name) to show + * first two letter of group member name. + * + * @param avatar is a object of Avatar + * @param avatarUrl is a String. It is url of avatar. + * @param name is a String. It is a name of groupMember. + * @see Avatar + * + */ + private void setAvatar(Avatar avatar, String avatarUrl, String name) { + + if (avatarUrl != null && !avatarUrl.isEmpty()) + Glide.with(context).load(avatarUrl).into(avatar); + else + avatar.setInitials(name); + + } + + + @Override + public int getItemCount() { + return messageList.size(); + } + +// @Override +// public long getHeaderId(int var1) { +// +// BaseMessage baseMessage = messageList.get(var1); +// return Long.parseLong(Utils.getDateId(baseMessage.getSentAt() * 1000)); +// } +// +// @Override +// public DateItemHolder onCreateHeaderViewHolder(ViewGroup var1) { +// View view = LayoutInflater.from(var1.getContext()).inflate(R.layout.cc_message_list_header, +// var1, false); +// +// return new DateItemHolder(view); +// } +// +// @Override +// public void onBindHeaderViewHolder(DateItemHolder var1, int var2, long var3) { +// BaseMessage baseMessage = messageList.get(var2); +// Date date = new Date(baseMessage.getSentAt() * 1000L); +// String formattedDate = Utils.getDate(date.getTime()); +// var1.txtMessageDate.setBackground(context.getResources().getDrawable(R.drawable.cc_rounded_date_button)); +// var1.txtMessageDate.setText(formattedDate); +// } + + /** + * This method is used to maintain different viewType based on message category and type and + * returns the different view types to adapter based on it. + * + * Ex :- For message with category CometChatConstants.CATEGORY_MESSAGE and type + * CometChatConstants.MESSAGE_TYPE_TEXT and message is sent by a Logged-in user, + * It will return RIGHT_TEXT_MESSAGE + * + * + * @param position is a position of item in recyclerView. + * @return It returns int which is value of view type of item. + * + * @see ThreadAdapter#onCreateViewHolder(ViewGroup, int) + * @see BaseMessage + * + */ + private int getItemViewTypes(int position) { + BaseMessage baseMessage = messageList.get(position); + HashMap extensionList = Extensions.extensionCheck(baseMessage); + if (baseMessage.getDeletedAt()==0) { + if (baseMessage.getCategory().equals(CometChatConstants.CATEGORY_MESSAGE)) { + switch (baseMessage.getType()) { + + case CometChatConstants.MESSAGE_TYPE_TEXT: + if (extensionList != null && extensionList.containsKey("linkPreview") && extensionList.get("linkPreview") != null) + return LINK_MESSAGE; + else if (baseMessage.getMetadata()!=null && baseMessage.getMetadata().has("reply")) + return REPLY_TEXT_MESSAGE; + else + return TEXT_MESSAGE; + case CometChatConstants.MESSAGE_TYPE_AUDIO: + return AUDIO_MESSAGE; + case CometChatConstants.MESSAGE_TYPE_IMAGE: + return IMAGE_MESSAGE; + case CometChatConstants.MESSAGE_TYPE_VIDEO: + return VIDEO_MESSAGE; + case CometChatConstants.MESSAGE_TYPE_FILE: + return FILE_MESSAGE; + default: + return -1; + } + } else { + if (baseMessage.getCategory().equals(CometChatConstants.CATEGORY_CUSTOM)){ + return CUSTOM_MESSAGE; + } + } + } + else + { + return DELETE_MESSAGE; + } + return -1; + + } + + /** + * This method is used to update message list of adapter. + * + * @param baseMessageList is list of baseMessages. + * + */ + public void updateList(List baseMessageList) { + setMessageList(baseMessageList); + } + + /** + * This method is used to set real time delivery receipt of particular message in messageList + * of adapter by updating message. + * + * @param messageReceipt is a object of MessageReceipt. + * @see MessageReceipt + */ + public void setDeliveryReceipts(MessageReceipt messageReceipt) { + + for (int i = messageList.size() - 1; i >= 0; i--) { + BaseMessage baseMessage = messageList.get(i); + if (baseMessage.getDeliveredAt() == 0) { + int index = messageList.indexOf(baseMessage); + messageList.get(index).setDeliveredAt(messageReceipt.getDeliveredAt()); + } + } + notifyDataSetChanged(); + } + + /** + * This method is used to set real time read receipt of particular message in messageList + * of adapter by updating message. + * + * @param messageReceipt is a object of MessageReceipt. + * @see MessageReceipt + */ + public void setReadReceipts(MessageReceipt messageReceipt) { + for (int i = messageList.size() - 1; i >= 0; i--) { + BaseMessage baseMessage = messageList.get(i); + if (baseMessage.getReadAt() == 0) { + int index = messageList.indexOf(baseMessage); + messageList.get(index).setReadAt(messageReceipt.getReadAt()); + } + } + + notifyDataSetChanged(); + } + + /** + * This method is used to add message in messageList when send by a user or when received in + * real time. + * + * @param baseMessage is a object of BaseMessage. It is new message which will added. + * @see BaseMessage + * + */ + public void addMessage(BaseMessage baseMessage) { +// if (!messageList.contains(baseMessage)) { + messageList.add(baseMessage); + selectedItemList.clear(); +// } + notifyItemInserted(messageList.size()-1); + } + + /** + * This method is used to update previous message with new message in messageList of adapter. + * + * @param baseMessage is a object of BaseMessage. It is new message which will be updated. + */ + public void setUpdatedMessage(BaseMessage baseMessage) { + + if (messageList.contains(baseMessage)) { + int index = messageList.indexOf(baseMessage); + messageList.remove(baseMessage); + messageList.add(index, baseMessage); + notifyItemChanged(index); + } + } + + public void resetList() { + messageList.clear(); + notifyDataSetChanged(); + } + + public void clearLongClickSelectedItem() { + isLongClickEnabled = false; + isTextMessageClick = false; + isImageMessageClick = false; + longselectedItemList.clear(); + notifyDataSetChanged(); + } + + public BaseMessage getLastMessage() { + if (messageList.size()>0) + { + Log.e(TAG, "getLastMessage: "+messageList.get(messageList.size()-1 )); + return messageList.get(messageList.size()-1); + } + else + return null; + } + + public int getPosition(BaseMessage baseMessage){ + return messageList.indexOf(baseMessage); + } + + class ImageMessageViewHolder extends RecyclerView.ViewHolder { + + private ImageView imageView; + private CardView cardView; + private ProgressBar progressBar; + private Avatar ivUser; + public TextView txtTime,tvUser; + private RelativeLayout rlMessageBubble; + + private RelativeLayout sensitiveLayout; + public ImageMessageViewHolder(@NonNull View view) { + super(view); + int type = (int) view.getTag(); + imageView = view.findViewById(R.id.go_img_message); + tvUser= view.findViewById(R.id.tv_user); + cardView = view.findViewById(R.id.cv_image_message_container); + progressBar = view.findViewById(R.id.img_progress_bar); + txtTime = view.findViewById(R.id.txt_time); + ivUser = view.findViewById(R.id.iv_user); + sensitiveLayout = view.findViewById(R.id.sensitive_layout); + rlMessageBubble = view.findViewById(R.id.rl_message); + } + } + + public class ActionMessageViewHolder extends RecyclerView.ViewHolder { + + private TextView textView; + + public ActionMessageViewHolder(@NonNull View view) { + super(view); + int type = (int) view.getTag(); + textView = view.findViewById(R.id.go_txt_message); + } + } + + class VideoMessageViewHolder extends RecyclerView.ViewHolder { + + private ImageView imageView; + private ImageView playBtn; + private CardView cardView; + private ProgressBar progressBar; + private Avatar ivUser; + public TextView txtTime,tvUser; + private RelativeLayout rlMessageBubble; + + public VideoMessageViewHolder(@NonNull View view) { + super(view); + int type = (int) view.getTag(); + imageView = view.findViewById(R.id.go_video_message); + playBtn = view.findViewById(R.id.playBtn); + tvUser= view.findViewById(R.id.tv_user); + cardView = view.findViewById(R.id.cv_image_message_container); + progressBar = view.findViewById(R.id.img_progress_bar); + txtTime = view.findViewById(R.id.txt_time); + ivUser = view.findViewById(R.id.iv_user); + rlMessageBubble = view.findViewById(R.id.rl_message); + } + } + + public class FileMessageViewHolder extends RecyclerView.ViewHolder { + + private TextView fileName; + private TextView fileExt; + public TextView txtTime; + private TextView fileSize; + private TextView tvUser; + private View view; + private Avatar ivUser; + private RelativeLayout rlMessageBubble; + + FileMessageViewHolder(@NonNull View itemView) { + super(itemView); + fileSize = itemView.findViewById(R.id.tvFileSize); + ivUser = itemView.findViewById(R.id.iv_user); + tvUser = itemView.findViewById(R.id.tv_user); + fileExt = itemView.findViewById(R.id.tvFileExtension); + txtTime = itemView.findViewById(R.id.txt_time); + fileName = itemView.findViewById(R.id.tvFileName); + rlMessageBubble = itemView.findViewById(R.id.rl_message); + this.view = itemView; + } + } + + public class DeleteMessageViewHolder extends RecyclerView.ViewHolder { + + private TextView txtMessage; + private RelativeLayout cardView; + private View view; + public TextView txtTime; + public TextView tvUser; + private ImageView imgStatus; + private int type; + private Avatar ivUser; + private RelativeLayout rlMessageBubble; + + DeleteMessageViewHolder(@NonNull View view) { + super(view); + type = (int) view.getTag(); + tvUser = view.findViewById(R.id.tv_user); + txtMessage = view.findViewById(R.id.go_txt_message); + cardView = view.findViewById(R.id.cv_message_container); + txtTime = view.findViewById(R.id.txt_time); + imgStatus = view.findViewById(R.id.img_pending); + ivUser = view.findViewById(R.id.iv_user); + rlMessageBubble = view.findViewById(R.id.rl_message); + this.view = view; + } + } + + public class TextMessageViewHolder extends RecyclerView.ViewHolder { + + private TextView txtMessage; + private RelativeLayout cardView; + private View view; + public TextView txtTime; + public TextView tvUser; + private ImageView imgStatus; + private int type; + private Avatar ivUser; + private RelativeLayout rlMessageBubble; + private RelativeLayout replyLayout; + private TextView replyUser; + private TextView replyMessage; + private RelativeLayout sentimentVw; + private TextView viewSentimentMessage; + + TextMessageViewHolder(@NonNull View view) { + super(view); + + type = (int) view.getTag(); + tvUser = view.findViewById(R.id.tv_user); + txtMessage = view.findViewById(R.id.go_txt_message); + cardView = view.findViewById(R.id.cv_message_container); + txtTime = view.findViewById(R.id.txt_time); + imgStatus = view.findViewById(R.id.img_pending); + ivUser = view.findViewById(R.id.iv_user); + rlMessageBubble = view.findViewById(R.id.rl_message); + replyLayout = view.findViewById(R.id.replyLayout); + replyUser = view.findViewById(R.id.reply_user); + replyMessage = view.findViewById(R.id.reply_message); + sentimentVw = view.findViewById(R.id.sentiment_layout); + viewSentimentMessage = view.findViewById(R.id.view_sentiment); + this.view = view; + + } + } + + public class CustomMessageViewHolder extends RecyclerView.ViewHolder { + + private TextView txtMessage; + private RelativeLayout cardView; + private View view; + public TextView txtTime; + public TextView tvUser; + private ImageView imgStatus; + private int type; + private Avatar ivUser; + private RelativeLayout rlMessageBubble; + + + CustomMessageViewHolder(@NonNull View view) { + super(view); + + type = (int) view.getTag(); + tvUser = view.findViewById(R.id.tv_user); + txtMessage = view.findViewById(R.id.go_txt_message); + cardView = view.findViewById(R.id.cv_message_container); + txtTime = view.findViewById(R.id.txt_time); + imgStatus = view.findViewById(R.id.img_pending); + ivUser = view.findViewById(R.id.iv_user); + rlMessageBubble = view.findViewById(R.id.rl_message); + this.view = view; + } + } + + public class AudioMessageViewHolder extends RecyclerView.ViewHolder { + + private TextView length; + private ImageView playBtn; + private int type; + private TextView tvUser; + private Avatar ivUser; + private RelativeLayout rlMessageBubble; + private TextView txtTime; + public AudioMessageViewHolder(@NonNull View itemView) { + super(itemView); + type = (int)itemView.getTag(); + length = itemView.findViewById(R.id.audiolength_tv); + playBtn = itemView.findViewById(R.id.playBtn); + rlMessageBubble = itemView.findViewById(R.id.cv_message_container); + tvUser = itemView.findViewById(R.id.tv_user); + ivUser = itemView.findViewById(R.id.iv_user); + txtTime = itemView.findViewById(R.id.txt_time); + } + } + public class LinkMessageViewHolder extends RecyclerView.ViewHolder { + + private TextView linkTitle; + private TextView linkVisit; + private TextView linkSubtitle; + private TextView message; + private ImageView videoLink; + private RelativeLayout cardView; + private View view; + public TextView txtTime; + private ImageView imgStatus; + private ImageView linkImg; + private int type; + private TextView tvUser; + private Avatar ivUser; + private RelativeLayout rlMessageBubble; + + LinkMessageViewHolder(@NonNull View view) { + super(view); + + type = (int) view.getTag(); + tvUser = view.findViewById(R.id.tv_user); + linkTitle = view.findViewById(R.id.link_title); + linkSubtitle = view.findViewById(R.id.link_subtitle); + linkVisit = view.findViewById(R.id.visitLink); + linkImg = view.findViewById(R.id.link_img); + message = view.findViewById(R.id.message); + videoLink = view.findViewById(R.id.videoLink); + cardView = view.findViewById(R.id.cv_message_container); + txtTime = view.findViewById(R.id.txt_time); + imgStatus = view.findViewById(R.id.img_pending); + ivUser = view.findViewById(R.id.iv_user); + rlMessageBubble = view.findViewById(R.id.rl_message); + this.view = view; + } + } + + public class DateItemHolder extends RecyclerView.ViewHolder { + + TextView txtMessageDate; + + DateItemHolder(@NonNull View itemView) { + super(itemView); + txtMessageDate = itemView.findViewById(R.id.txt_message_date); + } + } + + public interface OnMessageLongClick + { + void setLongMessageClick(List baseMessage); + } +} + + + diff --git a/uikit/src/main/java/com/cometchat/pro/uikit/CometChatConversationList.java b/uikit/src/main/java/com/cometchat/pro/uikit/CometChatConversationList.java index 1fa975c4..7c6c07bf 100644 --- a/uikit/src/main/java/com/cometchat/pro/uikit/CometChatConversationList.java +++ b/uikit/src/main/java/com/cometchat/pro/uikit/CometChatConversationList.java @@ -73,7 +73,6 @@ public CometChatConversationList(@NonNull Context context, @Nullable AttributeSe private void setViewModel(){ if (conversationViewModel==null) conversationViewModel=new ConversationViewModel(context,this); - } /** diff --git a/uikit/src/main/java/com/cometchat/pro/uikit/CometChatGroupList.java b/uikit/src/main/java/com/cometchat/pro/uikit/CometChatGroupList.java index 38e14b23..3318f86a 100644 --- a/uikit/src/main/java/com/cometchat/pro/uikit/CometChatGroupList.java +++ b/uikit/src/main/java/com/cometchat/pro/uikit/CometChatGroupList.java @@ -77,11 +77,11 @@ private void setViewModel(){ * This method helps updating the group in CometChatGroupList * * @param group object to be updated in the list - * + * @param position is int value which indicates position of group in list. */ - public void update(Group group){ + public void update(Group group,int position){ if (groupListViewModel!=null){ - groupListViewModel.update(group); + groupListViewModel.update(group,position); } } /** diff --git a/uikit/src/main/java/com/cometchat/pro/uikit/ComposeBox.java b/uikit/src/main/java/com/cometchat/pro/uikit/ComposeBox.java index 8f18b0c8..959f8e67 100644 --- a/uikit/src/main/java/com/cometchat/pro/uikit/ComposeBox.java +++ b/uikit/src/main/java/com/cometchat/pro/uikit/ComposeBox.java @@ -62,7 +62,7 @@ public class ComposeBox extends RelativeLayout implements View.OnClickListener { private Chronometer recordTime; - private EditText etComposeBox; + public EditText etComposeBox; private RelativeLayout composeBox; @@ -278,28 +278,16 @@ public void onClick(View view) { } if(view.getId()==R.id.ivArrow) { if (isOpen) { - ivArrow.setRotation(0); - isOpen = false; - Animation leftAnim = AnimationUtils.loadAnimation(getContext(), R.anim.animate_left_slide); - rlActionContainer.startAnimation(leftAnim); - rlActionContainer.setVisibility(GONE); + closeActionContainer(); } else { - ivArrow.setRotation(45f); - isOpen = true; - Animation rightAnimate = AnimationUtils.loadAnimation(getContext(), R.anim.animate_right_slide); - rlActionContainer.startAnimation(rightAnimate); - rlActionContainer.setVisibility(View.VISIBLE); + openActionContainer(); } } if (view.getId()==R.id.ivMic) { if (Utils.hasPermissions(context, new String[]{Manifest.permission.RECORD_AUDIO,Manifest.permission.WRITE_EXTERNAL_STORAGE})) { if (isOpen) { - ivArrow.setRotation(0); - isOpen = false; - Animation leftAnim = AnimationUtils.loadAnimation(getContext(), R.anim.animate_left_slide); - rlActionContainer.startAnimation(leftAnim); - rlActionContainer.setVisibility(GONE); + closeActionContainer(); } if (!isRecording) { startRecord(); @@ -332,6 +320,22 @@ public void onClick(View view) { } } + public void openActionContainer() { + ivArrow.setRotation(45f); + isOpen = true; + Animation rightAnimate = AnimationUtils.loadAnimation(getContext(), R.anim.animate_right_slide); + rlActionContainer.startAnimation(rightAnimate); + rlActionContainer.setVisibility(View.VISIBLE); + } + + public void closeActionContainer() { + ivArrow.setRotation(0); + isOpen = false; + Animation leftAnim = AnimationUtils.loadAnimation(getContext(), R.anim.animate_left_slide); + rlActionContainer.startAnimation(leftAnim); + rlActionContainer.setVisibility(GONE); + } + public void startRecord() { etComposeBox.setVisibility(GONE); recordTime.setBase(SystemClock.elapsedRealtime()); diff --git a/uikit/src/main/java/com/cometchat/pro/uikit/SharedMedia/SharedFilesFragment.java b/uikit/src/main/java/com/cometchat/pro/uikit/SharedMedia/SharedFilesFragment.java index 5408f300..058087e2 100644 --- a/uikit/src/main/java/com/cometchat/pro/uikit/SharedMedia/SharedFilesFragment.java +++ b/uikit/src/main/java/com/cometchat/pro/uikit/SharedMedia/SharedFilesFragment.java @@ -56,13 +56,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c Id = getArguments().getString("Id"); type = getArguments().getString("type"); fetchMessage(); - rvFiles.addOnItemTouchListener(new RecyclerTouchListener(getContext(), rvFiles, new ClickListener() { - @Override - public void onClick(View var1, int var2) { - BaseMessage message = (BaseMessage)var1.getTag(R.string.baseMessage); - MediaUtils.openFile(((MediaMessage)message).getAttachment().getFileUrl(),getContext()); - } - })); + rvFiles.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { diff --git a/uikit/src/main/java/com/cometchat/pro/uikit/SharedMedia/SharedImagesFragment.java b/uikit/src/main/java/com/cometchat/pro/uikit/SharedMedia/SharedImagesFragment.java index 946ed335..51b0948e 100644 --- a/uikit/src/main/java/com/cometchat/pro/uikit/SharedMedia/SharedImagesFragment.java +++ b/uikit/src/main/java/com/cometchat/pro/uikit/SharedMedia/SharedImagesFragment.java @@ -65,25 +65,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c Id = this.getArguments().getString("Id"); type = this.getArguments().getString("type"); fetchMessage(); - rvFiles.addOnItemTouchListener(new RecyclerTouchListener(getContext(), rvFiles, new ClickListener() { - @Override - public void onClick(View var1, int var2) { - BaseMessage message = (BaseMessage)var1.getTag(R.string.baseMessage); - Dialog imageDialog = new Dialog(getContext()); - View messageVw = LayoutInflater.from(getContext()).inflate(R.layout.image_dialog_view, null); - ZoomIv imageView = messageVw.findViewById(R.id.imageView); - Glide.with(getContext()).asBitmap().load(((MediaMessage) message).getAttachment().getFileUrl()).into(new SimpleTarget() { - @Override - public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition transition) { - imageView.setImageBitmap(resource); - } - }); - imageDialog.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); - imageDialog.setContentView(messageVw); - imageDialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); - imageDialog.show(); - } - })); + rvFiles.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { diff --git a/uikit/src/main/java/com/cometchat/pro/uikit/SharedMedia/SharedVideosFragment.java b/uikit/src/main/java/com/cometchat/pro/uikit/SharedMedia/SharedVideosFragment.java index 760e29c5..f8aed679 100644 --- a/uikit/src/main/java/com/cometchat/pro/uikit/SharedMedia/SharedVideosFragment.java +++ b/uikit/src/main/java/com/cometchat/pro/uikit/SharedMedia/SharedVideosFragment.java @@ -48,13 +48,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c type = getArguments().getString("type"); fetchMessage(); - rvFiles.addOnItemTouchListener(new RecyclerTouchListener(getContext(), rvFiles, new ClickListener() { - @Override - public void onClick(View var1, int var2) { - BaseMessage message = (BaseMessage)var1.getTag(R.string.baseMessage); - MediaUtils.openFile(((MediaMessage)message).getAttachment().getFileUrl(),getContext()); - } - })); + rvFiles.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { diff --git a/uikit/src/main/java/constant/StringContract.java b/uikit/src/main/java/constant/StringContract.java index d5477f9e..d734cb73 100644 --- a/uikit/src/main/java/constant/StringContract.java +++ b/uikit/src/main/java/constant/StringContract.java @@ -4,6 +4,9 @@ public class StringContract { + public static class AppInfo { + public static String API_KEY = ""; + } public static class IntentStrings { public static final String IMAGE_TYPE = "image/*"; @@ -65,6 +68,21 @@ public static class IntentStrings { public static final String GROUP_PASSWORD = "group_password" ; public static final String GROUP_TYPE = "group_type" ; + + public static final String TEXTMESSAGE = "text_message"; + + public static final String SENTAT = "sent_at"; + + public static final String MESSAGE_TYPE = "message_type" ; + + public static final String PARENT_ID = "parent_id"; + + public static final String REPLY_COUNT = "reply_count"; + + public static final String CONVERSATION_NAME = "conversation_name"; + + + public static final String INTENT_MEDIA_MESSAGE = "intent_media_message" ; } public static class Tab { @@ -92,5 +110,4 @@ public static class RequestCode{ public static final int RECORD = 003; } - } diff --git a/uikit/src/main/java/listeners/MessageActionCloseListener.java b/uikit/src/main/java/listeners/MessageActionCloseListener.java new file mode 100644 index 00000000..c5b46304 --- /dev/null +++ b/uikit/src/main/java/listeners/MessageActionCloseListener.java @@ -0,0 +1,8 @@ +package listeners; + +import android.content.DialogInterface; + +public interface MessageActionCloseListener +{ + public void handleDialogClose(DialogInterface dialog); +} diff --git a/uikit/src/main/java/listeners/OnMessageLongClick.java b/uikit/src/main/java/listeners/OnMessageLongClick.java new file mode 100644 index 00000000..c05d02e2 --- /dev/null +++ b/uikit/src/main/java/listeners/OnMessageLongClick.java @@ -0,0 +1,10 @@ +package listeners; + +import com.cometchat.pro.models.BaseMessage; + +import java.util.List; + +public interface OnMessageLongClick +{ + void setLongMessageClick(List baseMessage); +} diff --git a/uikit/src/main/java/screen/CometChatConversationListScreen.java b/uikit/src/main/java/screen/CometChatConversationListScreen.java index 897f4191..9f564c72 100644 --- a/uikit/src/main/java/screen/CometChatConversationListScreen.java +++ b/uikit/src/main/java/screen/CometChatConversationListScreen.java @@ -77,6 +77,8 @@ public class CometChatConversationListScreen extends Fragment implements TextWat private View view; + private List conversationList = new ArrayList<>(); + public CometChatConversationListScreen() { // Required empty public constructor } @@ -158,7 +160,8 @@ private void makeConversationList() { conversationsRequest.fetchNext(new CometChat.CallbackListener>() { @Override public void onSuccess(List conversations) { - if (conversations.size() != 0) { + conversationList.addAll(conversations); + if (conversationList.size() != 0) { stopHideShimmer(); noConversationView.setVisibility(View.GONE); rvConversationList.setConversationList(conversations); @@ -340,7 +343,7 @@ public void onResume() { Log.d(TAG, "onResume: "); conversationsRequest = null; searchEdit.addTextChangedListener(this); - rvConversationList.clearList(); +// rvConversationList.clearList(); makeConversationList(); addConversationListener(); } diff --git a/uikit/src/main/java/screen/CometChatForwardMessageScreenActivity.java b/uikit/src/main/java/screen/CometChatForwardMessageScreenActivity.java index 2be02b47..d332b5b7 100644 --- a/uikit/src/main/java/screen/CometChatForwardMessageScreenActivity.java +++ b/uikit/src/main/java/screen/CometChatForwardMessageScreenActivity.java @@ -3,6 +3,7 @@ import android.content.Context; import android.content.Intent; import android.graphics.drawable.Drawable; +import android.net.Uri; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; @@ -54,6 +55,7 @@ import listeners.OnItemClickListener; import screen.unified.CometChatUnified; import utils.FontUtils; +import utils.MediaUtils; import utils.Utils; /** @@ -106,10 +108,41 @@ protected void onCreate(Bundle savedInstanceState) { init(); } + + void handleSendText(Intent intent) { + String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT); + if (sharedText != null) { + messageType = CometChatConstants.MESSAGE_TYPE_TEXT; + textMessage = sharedText; + } + } + + void handleSendImage(Intent intent) { + Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM); + if (imageUri != null) { + messageType = StringContract.IntentStrings.INTENT_MEDIA_MESSAGE; + mediaMessageUrl = imageUri.toString(); + Log.e(TAG, "handleSendImage: "+mediaMessageUrl); + } + } /** * This method is used to handle parameter passed to this class. */ private void handleIntent() { + + // Get intent, action and MIME type + Intent intent = getIntent(); + String action = intent.getAction(); + String type = intent.getType(); + + if (Intent.ACTION_SEND.equals(action) && type != null) { + if ("text/plain".equals(type)) { + handleSendText(intent); // Handle text being sent + } else if (type.startsWith("image/")) { + handleSendImage(intent); // Handle single image being sent + } + } + if (getIntent().hasExtra(StringContract.IntentStrings.TYPE)) { messageType = getIntent().getStringExtra(StringContract.IntentStrings.TYPE); } @@ -271,7 +304,7 @@ public void onClick(View view) { } }).start(); - } else if (messageType!=null) { + } else if (messageType!=null && !messageType.equals(StringContract.IntentStrings.INTENT_MEDIA_MESSAGE)) { new Thread(() -> { for (int i = 0; i <= userList.size() - 1; i++) { Conversation conversation = new ArrayList<>(userList.values()).get(i); @@ -304,6 +337,40 @@ public void onClick(View view) { } } + }).start(); + } else { + new Thread(() -> { + for (int i = 0; i <= userList.size() - 1; i++) { + Conversation conversation = new ArrayList<>(userList.values()).get(i); + MediaMessage message; + String uid; + String type; + Log.e(TAG, "run: " + conversation.getConversationId()); + if (conversation.getConversationType().equals(CometChatConstants.CONVERSATION_TYPE_USER)) { + uid = ((User) conversation.getConversationWith()).getUid(); + type = CometChatConstants.RECEIVER_TYPE_USER; + } else { + uid = ((Group) conversation.getConversationWith()).getGuid(); + type = CometChatConstants.RECEIVER_TYPE_GROUP; + } + File file = MediaUtils.getRealPath(CometChatForwardMessageScreenActivity.this,Uri.parse(mediaMessageUrl)); + message = new MediaMessage(uid,file,CometChatConstants.MESSAGE_TYPE_IMAGE, type); + try { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("path",mediaMessageUrl); + message.setMetadata(jsonObject); + } catch (Exception e) { + Log.e(TAG, "onError: "+e.getMessage()); + } + sendMediaMessage(message); + if (i == userList.size() - 1) { + Intent intent = new Intent(CometChatForwardMessageScreenActivity.this, CometChatUnified.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + finish(); + } + } + }).start(); } } diff --git a/uikit/src/main/java/screen/CometChatGroupDetailScreenActivity.java b/uikit/src/main/java/screen/CometChatGroupDetailScreenActivity.java index c85aae3b..f9b6a9ec 100644 --- a/uikit/src/main/java/screen/CometChatGroupDetailScreenActivity.java +++ b/uikit/src/main/java/screen/CometChatGroupDetailScreenActivity.java @@ -76,6 +76,8 @@ public class CometChatGroupDetailScreenActivity extends AppCompatActivity { private TextView tvGroupName; + private TextView tvGroupDesc; + private TextView tvAdminCount; private TextView tvModeratorCount; @@ -156,6 +158,7 @@ private void initComponent() { divider2 = findViewById(R.id.tv_seperator_1); groupIcon = findViewById(R.id.iv_group); tvGroupName = findViewById(R.id.tv_group_name); + tvGroupDesc = findViewById(R.id.group_description); tvGroupName.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { @@ -440,6 +443,7 @@ private void handleIntent() { } if (getIntent().hasExtra(StringContract.IntentStrings.GROUP_DESC)) { gDesc = getIntent().getStringExtra(StringContract.IntentStrings.GROUP_DESC); + tvGroupDesc.setText(gDesc); } if (getIntent().hasExtra(StringContract.IntentStrings.GROUP_PASSWORD)) { gPassword = getIntent().getStringExtra(StringContract.IntentStrings.GROUP_PASSWORD); @@ -565,8 +569,8 @@ private void banMember() { public void onSuccess(String s) { Log.e(TAG, "onSuccess: " + s); tvMemberCount.setText((groupMemberCount-1)+" Members"); - int count = Integer.parseInt(tvBanMemberCount.getText().toString()); - tvBanMemberCount.setText(String.valueOf(++count)); +// int count = Integer.parseInt(tvBanMemberCount.getText().toString()); +// tvBanMemberCount.setText(String.valueOf(++count)); groupMemberUids.remove(groupMember.getUid()); groupMemberAdapter.removeGroupMember(groupMember); } @@ -609,8 +613,8 @@ public void onSuccess(List groupMembers) { } s[j] = groupMembers.get(j).getName(); } - tvAdminCount.setText(adminCount+""); - tvModeratorCount.setText(moderatorCount+""); +// tvAdminCount.setText(adminCount+""); +// tvModeratorCount.setText(moderatorCount+""); if (groupMemberAdapter == null) { groupMemberAdapter = new GroupMemberAdapter(CometChatGroupDetailScreenActivity.this, groupMembers, ownerId); rvMemberList.setAdapter(groupMemberAdapter); @@ -636,24 +640,24 @@ public void onError(CometChatException e) { }); } - private void getBannedMemberCount() { - banMemberRequest = new BannedGroupMembersRequest.BannedGroupMembersRequestBuilder(guid).setLimit(100).build(); - banMemberRequest.fetchNext(new CometChat.CallbackListener>() { - @Override - public void onSuccess(List groupMembers) { - if (groupMembers.size()>=99) { - tvBanMemberCount.setText("99+"); - } else { - tvBanMemberCount.setText(groupMembers.size()+""); - } - } - - @Override - public void onError(CometChatException e) { - Log.e(TAG, "onError: "+e.getMessage()+"\n"+e.getCode()); - } - }); - } +// private void getBannedMemberCount() { +// banMemberRequest = new BannedGroupMembersRequest.BannedGroupMembersRequestBuilder(guid).setLimit(100).build(); +// banMemberRequest.fetchNext(new CometChat.CallbackListener>() { +// @Override +// public void onSuccess(List groupMembers) { +// if (groupMembers.size()>=99) { +// tvBanMemberCount.setText("99+"); +// } else { +// tvBanMemberCount.setText(groupMembers.size()+""); +// } +// } +// +// @Override +// public void onError(CometChatException e) { +// Log.e(TAG, "onError: "+e.getMessage()+"\n"+e.getCode()); +// } +// }); +// } /** * This method is used to leave the loggedIn User from respective group. @@ -719,8 +723,8 @@ public void onMemberAddedToGroup(Action action, User addedby, User userAdded, Gr @Override public void onGroupMemberBanned(Action action, User bannedUser, User bannedBy, Group bannedFrom) { if (bannedFrom.getGuid().equals(guid)) { - int count = Integer.parseInt(tvBanMemberCount.getText().toString()); - tvBanMemberCount.setText(String.valueOf(++count)); +// int count = Integer.parseInt(tvBanMemberCount.getText().toString()); +// tvBanMemberCount.setText(String.valueOf(++count)); updateGroupMember(bannedUser, true, false, action); } } @@ -728,8 +732,8 @@ public void onGroupMemberBanned(Action action, User bannedUser, User bannedBy, G @Override public void onGroupMemberUnbanned(Action action, User unbannedUser, User unbannedBy, Group unbannedFrom) { if (unbannedFrom.getGuid().equals(guid)) { - int count = Integer.parseInt(tvBanMemberCount.getText().toString()); - tvBanMemberCount.setText(String.valueOf(--count)); +// int count = Integer.parseInt(tvBanMemberCount.getText().toString()); +// tvBanMemberCount.setText(String.valueOf(--count)); } } }); @@ -762,17 +766,17 @@ private void updateGroupMember(User user, boolean isRemoved, boolean isScopeUpda if(action.getNewScope()!=null) { if (action.getNewScope().equals(CometChatConstants.SCOPE_ADMIN)) { adminCount = adminCount - 1; - tvAdminCount.setText(String.valueOf(adminCount)); +// tvAdminCount.setText(String.valueOf(adminCount)); } else if (action.getNewScope().equals(CometChatConstants.SCOPE_MODERATOR)) { moderatorCount = moderatorCount - 1; - tvModeratorCount.setText(String.valueOf(moderatorCount)); +// tvModeratorCount.setText(String.valueOf(moderatorCount)); } } } else if (!isRemoved) { groupMemberAdapter.updateMember(UserToGroupMember(user, true, action.getNewScope())); if (action.getNewScope().equals(CometChatConstants.SCOPE_ADMIN)) { adminCount = adminCount + 1; - tvAdminCount.setText(String.valueOf(adminCount)); +// tvAdminCount.setText(String.valueOf(adminCount)); if (user.getUid().equals(loggedInUser.getUid())) { rlAddMemberView.setVisibility(View.VISIBLE); loggedInUserScope = CometChatConstants.SCOPE_ADMIN; @@ -780,17 +784,17 @@ private void updateGroupMember(User user, boolean isRemoved, boolean isScopeUpda } } else if (action.getNewScope().equals(CometChatConstants.SCOPE_MODERATOR)) { moderatorCount = moderatorCount + 1; - tvModeratorCount.setText(String.valueOf(moderatorCount)); +// tvModeratorCount.setText(String.valueOf(moderatorCount)); if (user.getUid().equals(loggedInUser.getUid())) { rlBanMembers.setVisibility(View.VISIBLE); loggedInUserScope = CometChatConstants.SCOPE_MODERATOR; } } else if (action.getOldScope().equals(CometChatConstants.SCOPE_ADMIN)) { adminCount = adminCount - 1; - tvAdminCount.setText(String.valueOf(adminCount)); +// tvAdminCount.setText(String.valueOf(adminCount)); } else if (action.getOldScope().equals(CometChatConstants.SCOPE_MODERATOR)) { moderatorCount = moderatorCount -1; - tvModeratorCount.setText(String.valueOf(moderatorCount)); +// tvModeratorCount.setText(String.valueOf(moderatorCount)); } } } @@ -883,6 +887,7 @@ public void afterTextChanged(Editable s) { @Override public void onClick(View v) { Group group = new Group(); + group.setDescription(groupDesc.getText().toString().trim()); if(groupName.getText().toString().isEmpty()) { groupName.setError(getString(R.string.fill_this_field)); } else if (groupTypeSp.getSelectedItemPosition()==2) { @@ -969,6 +974,7 @@ public void onSuccess(Group group) { groupMemberCount = group.getMembersCount(); groupType = group.getGroupType(); gDesc = group.getDescription(); + tvGroupDesc.setText(gDesc); tvMemberCount.setText(groupMemberCount+" Members"); } @@ -989,7 +995,7 @@ protected void onResume() { groupMemberAdapter = null; } - getBannedMemberCount(); +// getBannedMemberCount(); getGroupMembers(); addGroupListener(); } diff --git a/uikit/src/main/java/screen/CometChatGroupListScreen.java b/uikit/src/main/java/screen/CometChatGroupListScreen.java index 77962ceb..06156494 100644 --- a/uikit/src/main/java/screen/CometChatGroupListScreen.java +++ b/uikit/src/main/java/screen/CometChatGroupListScreen.java @@ -262,6 +262,5 @@ public void onResume() { groupsRequest=null; groupListAdapter=null; fetchGroup(); - } } diff --git a/uikit/src/main/java/screen/CometChatUserInfoScreen.java b/uikit/src/main/java/screen/CometChatUserInfoScreen.java index 68211235..7e442774 100644 --- a/uikit/src/main/java/screen/CometChatUserInfoScreen.java +++ b/uikit/src/main/java/screen/CometChatUserInfoScreen.java @@ -151,9 +151,7 @@ public void onClick(View v) { } private void updateUser(User user) { - PreferenceUtil preferenceUtil = PreferenceUtil.getInstance(getContext()); - String apikey = preferenceUtil.getString("apikey"); - CometChat.updateUser(user, apikey, new CometChat.CallbackListener() { + CometChat.updateUser(user, StringContract.AppInfo.API_KEY, new CometChat.CallbackListener() { @Override public void onSuccess(User user) { if (getContext()!=null) diff --git a/uikit/src/main/java/screen/MessageActionFragment.java b/uikit/src/main/java/screen/MessageActionFragment.java new file mode 100644 index 00000000..ee9b2529 --- /dev/null +++ b/uikit/src/main/java/screen/MessageActionFragment.java @@ -0,0 +1,217 @@ +package screen; + +import android.app.Activity; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.view.ViewTreeObserver; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; + +import com.cometchat.pro.uikit.R; +import com.google.android.material.bottomsheet.BottomSheetBehavior; +import com.google.android.material.bottomsheet.BottomSheetDialog; +import com.google.android.material.bottomsheet.BottomSheetDialogFragment; + +import screen.messagelist.CometChatMessageListActivity; +import screen.threadconversation.CometChatThreadMessageActivity; + +public class MessageActionFragment extends BottomSheetDialogFragment { + + private TextView threadMessage; + private TextView editMessage; + private TextView replyMessage; + private TextView forwardMessage; + private TextView deleteMessage; + private TextView copyMessage; + private TextView shareMessage; + + private boolean isShareVisible; + private boolean isThreadVisible; + private boolean isCopyVisible; + private boolean isEditVisible; + private boolean isDeleteVisible; + private boolean isForwardVisible; + private boolean isReplyVisible; + + private MessageActionListener messageActionListener; + + private String type; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + fetchArguments(); + } + + private void fetchArguments() { + if (getArguments()!=null) { + isCopyVisible = getArguments().getBoolean("copyVisible"); + isThreadVisible = getArguments().getBoolean("threadVisible"); + isEditVisible = getArguments().getBoolean("editVisible"); + isDeleteVisible = getArguments().getBoolean("deleteVisible"); + isReplyVisible = getArguments().getBoolean("replyVisible"); + isForwardVisible = getArguments().getBoolean("forwardVisible"); + isShareVisible = getArguments().getBoolean("shareVisible"); + type = getArguments().getString("type"); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + View view = inflater.inflate(R.layout.fragment_message_actions, container, false); + view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + BottomSheetDialog dialog = (BottomSheetDialog) getDialog(); + // androidx should use: com.google.android.material.R.id.design_bottom_sheet + FrameLayout bottomSheet = (FrameLayout) + dialog.findViewById(com.google.android.material.R.id.design_bottom_sheet); + BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet); + behavior.setState(BottomSheetBehavior.STATE_EXPANDED); + behavior.setPeekHeight(0); + } + }); + threadMessage = view.findViewById(R.id.start_thread); + editMessage = view.findViewById(R.id.edit_message); + replyMessage = view.findViewById(R.id.reply_message); + forwardMessage = view.findViewById(R.id.forward_message); + deleteMessage = view.findViewById(R.id.delete_message); + copyMessage = view.findViewById(R.id.copy_message); + shareMessage = view.findViewById(R.id.share_message); + + if (isThreadVisible) + threadMessage.setVisibility(View.VISIBLE); + else + threadMessage.setVisibility(View.GONE); + if (isCopyVisible) + copyMessage.setVisibility(View.VISIBLE); + else + copyMessage.setVisibility(View.GONE); + if (isEditVisible) + editMessage.setVisibility(View.VISIBLE); + else + editMessage.setVisibility(View.GONE); + if (isDeleteVisible) + deleteMessage.setVisibility(View.VISIBLE); + else + deleteMessage.setVisibility(View.GONE); + if (isReplyVisible) + replyMessage.setVisibility(View.VISIBLE); + else + replyMessage.setVisibility(View.GONE); + if (isForwardVisible) + forwardMessage.setVisibility(View.VISIBLE); + else + forwardMessage.setVisibility(View.GONE); + if (isShareVisible) + shareMessage.setVisibility(View.VISIBLE); + else + shareMessage.setVisibility(View.GONE); + + if (type!=null && type.equals(CometChatThreadMessageActivity.class.getName())) { + threadMessage.setVisibility(View.GONE); + } + + threadMessage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (messageActionListener!=null) + messageActionListener.onThreadMessageClick(); + dismiss(); + } + }); + copyMessage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (messageActionListener!=null) + messageActionListener.onCopyMessageClick(); + dismiss(); + } + }); + editMessage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (messageActionListener!=null) + messageActionListener.onEditMessageClick(); + dismiss(); + } + }); + deleteMessage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (messageActionListener!=null) + messageActionListener.onDeleteMessageClick(); + dismiss(); + } + }); + replyMessage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (messageActionListener!=null) + messageActionListener.onReplyMessageClick(); + dismiss(); + } + }); + forwardMessage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (messageActionListener!=null) + messageActionListener.onForwardMessageClick(); + dismiss(); + } + }); + shareMessage.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + if (messageActionListener!=null) + messageActionListener.onShareMessageClick(); + dismiss(); + } + }); + + return view; + } + + + public void setMessageActionListener(MessageActionListener messageActionListener) { + this.messageActionListener = messageActionListener; + + } + + public interface MessageActionListener { + void onThreadMessageClick(); + void onEditMessageClick(); + void onReplyMessageClick(); + void onForwardMessageClick(); + void onDeleteMessageClick(); + void onCopyMessageClick(); + void onShareMessageClick(); + } + + @Override + public void onDismiss(@NonNull DialogInterface dialog) { + Activity activity = getActivity(); + if (activity!=null) + if (type!=null && type== CometChatMessageListActivity.class.getName()) + ((CometChatMessageListActivity)activity).handleDialogClose(dialog); + else + ((CometChatThreadMessageActivity)activity).handleDialogClose(dialog); + } + + @Override + public void onCancel(@NonNull DialogInterface dialog) { + Activity activity = getActivity(); + if (activity!=null) + if (type!=null && type==CometChatMessageListActivity.class.getName()) + ((CometChatMessageListActivity)activity).handleDialogClose(dialog); + else + ((CometChatThreadMessageActivity)activity).handleDialogClose(dialog); + } +} \ No newline at end of file diff --git a/uikit/src/main/java/screen/groupmemberlist/CometChatGroupMemberListScreen.java b/uikit/src/main/java/screen/groupmemberlist/CometChatGroupMemberListScreen.java index c8aed923..47befcdf 100644 --- a/uikit/src/main/java/screen/groupmemberlist/CometChatGroupMemberListScreen.java +++ b/uikit/src/main/java/screen/groupmemberlist/CometChatGroupMemberListScreen.java @@ -214,7 +214,8 @@ private void updateAsModeratorScope(GroupMember groupMember) { public void onSuccess(String s) { Log.d(TAG, "onSuccess: "+s); groupMemberListAdapter.removeGroupMember(groupMember); - Snackbar.make(rvUserList,String.format(getResources().getString(R.string.user_is_moderator),groupMember.getName()), Snackbar.LENGTH_LONG).show(); + if (rvUserList!=null) + Snackbar.make(rvUserList,String.format(getResources().getString(R.string.user_is_moderator),groupMember.getName()), Snackbar.LENGTH_LONG).show(); } @Override diff --git a/uikit/src/main/java/screen/messagelist/CometChatMessageListActivity.java b/uikit/src/main/java/screen/messagelist/CometChatMessageListActivity.java index 41bba647..3bc81b31 100644 --- a/uikit/src/main/java/screen/messagelist/CometChatMessageListActivity.java +++ b/uikit/src/main/java/screen/messagelist/CometChatMessageListActivity.java @@ -1,5 +1,6 @@ package screen.messagelist; +import android.content.DialogInterface; import android.content.Intent; import android.os.Bundle; import android.util.Log; @@ -23,6 +24,8 @@ import adapter.MessageAdapter; import constant.StringContract; +import listeners.MessageActionCloseListener; +import listeners.OnMessageLongClick; import screen.CometChatUserDetailScreenActivity; import utils.Utils; @@ -116,11 +119,6 @@ public void setLongMessageClick(List baseMessage) { ((OnMessageLongClick)fragment).setLongMessageClick(baseMessage); } - public interface OnMessageLongClick - { - void setLongMessageClick(List baseMessagesList); - } - @Override protected void onResume() { super.onResume(); @@ -131,4 +129,7 @@ protected void onPause() { super.onPause(); } + public void handleDialogClose(DialogInterface dialog) { + ((MessageActionCloseListener)fragment).handleDialogClose(dialog); + } } diff --git a/uikit/src/main/java/screen/messagelist/CometChatMessageScreen.java b/uikit/src/main/java/screen/messagelist/CometChatMessageScreen.java index 8b89ca21..776781e2 100644 --- a/uikit/src/main/java/screen/messagelist/CometChatMessageScreen.java +++ b/uikit/src/main/java/screen/messagelist/CometChatMessageScreen.java @@ -1,24 +1,26 @@ package screen.messagelist; import android.Manifest; -import android.app.Activity; import android.content.ClipData; import android.content.ClipboardManager; import android.content.ContentResolver; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; import android.content.res.ColorStateList; +import android.graphics.Bitmap; import android.media.AudioManager; import android.media.MediaPlayer; import android.media.MediaRecorder; +import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; +import android.provider.MediaStore; import android.text.Editable; -import android.text.TextWatcher; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -26,14 +28,10 @@ import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.widget.Chronometer; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; -import android.widget.SeekBar; import android.widget.TextView; import android.widget.Toast; @@ -41,10 +39,16 @@ import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; +import androidx.core.app.ShareCompat; +import androidx.core.content.FileProvider; +import androidx.core.text.HtmlCompat; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.target.SimpleTarget; +import com.bumptech.glide.request.transition.Transition; import com.cometchat.pro.constants.CometChatConstants; import com.cometchat.pro.core.CometChat; import com.cometchat.pro.core.GroupMembersRequest; @@ -67,11 +71,11 @@ import com.google.android.material.button.MaterialButton; import com.google.android.material.snackbar.Snackbar; +import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.File; -import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -81,12 +85,16 @@ import adapter.MessageAdapter; import constant.StringContract; import listeners.ComposeActionListener; +import listeners.MessageActionCloseListener; import listeners.OnItemClickListener; +import listeners.OnMessageLongClick; import listeners.StickyHeaderDecoration; import screen.CometChatForwardMessageScreenActivity; import screen.CometChatGroupDetailScreenActivity; import screen.CometChatUserDetailScreenActivity; -import utils.AudioVisualizer.AudioRecordView; +import screen.MessageActionFragment; +import screen.threadconversation.CometChatThreadMessageActivity; +import utils.Extensions; import utils.FontUtils; import utils.MediaUtils; import utils.KeyBoardUtils; @@ -111,12 +119,15 @@ */ -public class CometChatMessageScreen extends Fragment implements View.OnClickListener, CometChatMessageListActivity.OnMessageLongClick { +public class CometChatMessageScreen extends Fragment implements View.OnClickListener, + OnMessageLongClick, MessageActionCloseListener { private static final String TAG = "CometChatMessageScreen"; private static final int LIMIT = 30; + private RelativeLayout bottomLayout; + private String name = ""; private String status = ""; @@ -125,12 +136,6 @@ public class CometChatMessageScreen extends Fragment implements View.OnClickList private ComposeBox composeBox; - private MediaRecorder mediaRecorder; - - private MediaPlayer mediaPlayer; - - private String audioFileNameWithPath; - private RecyclerView rvChatListView; //Used to display list of messages. private MessageAdapter messageAdapter; @@ -172,23 +177,21 @@ public class CometChatMessageScreen extends Fragment implements View.OnClickList private String loggedInUserScope; - private RelativeLayout rlMessageAction; - - private ImageView ivCloseMessageAction; + private RelativeLayout editMessageLayout; - private ImageView ivCopyMessageAction; + private TextView tvMessageTitle; - private TextView tvEditMessage; + private TextView tvMessageSubTitle; - private TextView tvDeleteMessage; + private RelativeLayout replyMessageLayout; - private TextView tvForwardMessage; + private TextView replyTitle; - private RelativeLayout editMessageLayout; + private TextView replyMessage; - private TextView tvMessageTitle; + private ImageView replyMedia; - private TextView tvMessageSubTitle; + private ImageView replyClose; private BaseMessage baseMessage; @@ -198,6 +201,8 @@ public class CometChatMessageScreen extends Fragment implements View.OnClickList private boolean isEdit; + private boolean isReply; + private String groupOwnerId; private int memberCount; @@ -283,6 +288,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa private void initViewComponent(View view) { setHasOptionsMenu(true); + bottomLayout = view.findViewById(R.id.bottom_layout); composeBox = view.findViewById(R.id.message_box); messageShimmer = view.findViewById(R.id.shimmer_layout); composeBox = view.findViewById(R.id.message_box); @@ -290,22 +296,20 @@ private void initViewComponent(View view) { setComposeBoxListener(); rvSmartReply = view.findViewById(R.id.rv_smartReply); - rlMessageAction = view.findViewById(R.id.message_actions); - ivCloseMessageAction = view.findViewById(R.id.iv_close_message_action); - ivCloseMessageAction.setOnClickListener(this); - ivCopyMessageAction = view.findViewById(R.id.iv_copy_message_action); - ivCopyMessageAction.setOnClickListener(this); - tvEditMessage = view.findViewById(R.id.edit_message); - tvEditMessage.setOnClickListener(this); - tvDeleteMessage = view.findViewById(R.id.delete_message); - tvDeleteMessage.setOnClickListener(this); - tvForwardMessage = view.findViewById(R.id.forward_message); - tvForwardMessage.setOnClickListener(this); + editMessageLayout = view.findViewById(R.id.editMessageLayout); tvMessageTitle = view.findViewById(R.id.tv_message_layout_title); tvMessageSubTitle = view.findViewById(R.id.tv_message_layout_subtitle); ImageView ivMessageClose = view.findViewById(R.id.iv_message_close); ivMessageClose.setOnClickListener(this); + + replyMessageLayout = view.findViewById(R.id.replyMessageLayout); + replyTitle = view.findViewById(R.id.tv_reply_layout_title); + replyMessage = view.findViewById(R.id.tv_reply_layout_subtitle); + replyMedia = view.findViewById(R.id.iv_reply_media); + replyClose = view.findViewById(R.id.iv_reply_close); + replyClose.setOnClickListener(this); + rvChatListView = view.findViewById(R.id.rv_message_list); MaterialButton unblockUserBtn = view.findViewById(R.id.btn_unblock_user); unblockUserBtn.setOnClickListener(this); @@ -321,24 +325,25 @@ private void initViewComponent(View view) { tvName.setText(name); setAvatar(); -// barVisualizer = view.findViewById(R.id.barVisualizer); rvChatListView.setLayoutManager(linearLayoutManager); ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar); ((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true); if (Utils.isDarkMode(context)) { + bottomLayout.setBackgroundColor(getResources().getColor(R.color.darkModeBackground)); toolbar.setBackgroundColor(getResources().getColor(R.color.grey)); editMessageLayout.setBackground(getResources().getDrawable(R.drawable.left_border_dark)); + replyMessageLayout.setBackground(getResources().getDrawable(R.drawable.left_border_dark)); composeBox.setBackgroundColor(getResources().getColor(R.color.darkModeBackground)); rvChatListView.setBackgroundColor(getResources().getColor(R.color.darkModeBackground)); - rlMessageAction.setBackgroundColor(getResources().getColor(R.color.darkModeBackground)); tvName.setTextColor(getResources().getColor(R.color.textColorWhite)); } else { + bottomLayout.setBackgroundTintList(ColorStateList.valueOf(getResources().getColor(R.color.textColorWhite))); toolbar.setBackgroundColor(getResources().getColor(R.color.textColorWhite)); editMessageLayout.setBackground(getResources().getDrawable(R.drawable.left_border)); + replyMessageLayout.setBackground(getResources().getDrawable(R.drawable.left_border)); composeBox.setBackgroundColor(getResources().getColor(R.color.textColorWhite)); rvChatListView.setBackgroundColor(getResources().getColor(R.color.textColorWhite)); - rlMessageAction.setBackgroundColor(getResources().getColor(R.color.textColorWhite)); tvName.setTextColor(getResources().getColor(R.color.primaryTextColor)); } @@ -380,7 +385,6 @@ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { } }); - rvSmartReply.setItemClickListener(new OnItemClickListener() { @Override public void OnItemClick(String var, int position) { @@ -497,6 +501,9 @@ public void onSendActionClicked(EditText editText) { if (isEdit) { editMessage(baseMessage, message); editMessageLayout.setVisibility(GONE); + } else if(isReply){ + replyMessage(baseMessage,message); + replyMessageLayout.setVisibility(GONE); } else if (!message.isEmpty()) sendMessage(message); } @@ -654,9 +661,9 @@ private void fetchMessage() { if (messagesRequest == null) { if (type != null) { if (type.equals(CometChatConstants.RECEIVER_TYPE_USER)) - messagesRequest = new MessagesRequest.MessagesRequestBuilder().setLimit(LIMIT).setUID(Id).build(); + messagesRequest = new MessagesRequest.MessagesRequestBuilder().setLimit(LIMIT).hideReplies(true).setUID(Id).build(); else - messagesRequest = new MessagesRequest.MessagesRequestBuilder().setLimit(LIMIT).setGUID(Id).hideMessagesFromBlockedUsers(true).build(); + messagesRequest = new MessagesRequest.MessagesRequestBuilder().setLimit(LIMIT).hideReplies(true).setGUID(Id).hideMessagesFromBlockedUsers(true).build(); } } messagesRequest.fetchPrevious(new CometChat.CallbackListener>() { @@ -705,6 +712,7 @@ private List filterBaseMessages(List baseMessages) { tempList.add(baseMessage); } } + else { tempList.add(baseMessage); } @@ -714,7 +722,7 @@ private List filterBaseMessages(List baseMessages) { private void getSmartReplyList(BaseMessage baseMessage) { - HashMap extensionList = Utils.extensionCheck(baseMessage); + HashMap extensionList = Extensions.extensionCheck(baseMessage); if (extensionList != null && extensionList.containsKey("smartReply")) { rvSmartReply.setVisibility(View.VISIBLE); JSONObject replyObject = extensionList.get("smartReply"); @@ -746,7 +754,7 @@ private void setSmartReplyAdapter(List replyList) { */ private void initMessageAdapter(List messageList) { if (messageAdapter == null) { - messageAdapter = new MessageAdapter(getActivity(), messageList, type); + messageAdapter = new MessageAdapter(getActivity(), messageList, CometChatMessageScreen.class.getName()); rvChatListView.setAdapter(messageAdapter); stickyHeaderDecoration = new StickyHeaderDecoration(messageAdapter); rvChatListView.addItemDecoration(stickyHeaderDecoration, 0); @@ -1078,6 +1086,62 @@ public void onError(CometChatException e) { } + /** + * This method is used to send reply message by link previous message with new message. + * @param baseMessage is a linked message + * @param message is a String. It will be new message sent as reply. + */ + private void replyMessage(BaseMessage baseMessage, String message) { + isReply = false; + try { + TextMessage textMessage; + if (type.equalsIgnoreCase(CometChatConstants.RECEIVER_TYPE_USER)) + textMessage = new TextMessage(Id, message, CometChatConstants.RECEIVER_TYPE_USER); + else + textMessage = new TextMessage(Id, message, CometChatConstants.RECEIVER_TYPE_GROUP); + JSONObject jsonObject = new JSONObject(); + JSONObject replyObject = new JSONObject(); + if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + replyObject.put("type",CometChatConstants.MESSAGE_TYPE_TEXT); + replyObject.put("message", ((TextMessage) baseMessage).getText()); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_IMAGE)) { + replyObject.put("type",CometChatConstants.MESSAGE_TYPE_IMAGE); + replyObject.put("message", "image"); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + replyObject.put("type",CometChatConstants.MESSAGE_TYPE_VIDEO); + replyObject.put("message", "video"); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + replyObject.put("type",CometChatConstants.MESSAGE_TYPE_FILE); + replyObject.put("message", "file"); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + replyObject.put("type", CometChatConstants.MESSAGE_TYPE_AUDIO); + replyObject.put("message", "audio"); + } + replyObject.put("name",baseMessage.getSender().getName()); + replyObject.put("avatar",baseMessage.getSender().getAvatar()); + jsonObject.put("reply",replyObject); + textMessage.setMetadata(jsonObject); + sendTypingIndicator(true); + CometChat.sendMessage(textMessage, new CometChat.CallbackListener() { + @Override + public void onSuccess(TextMessage textMessage) { + if (messageAdapter != null) { + MediaUtils.playSendSound(context,R.raw.outgoing_message); + messageAdapter.addMessage(textMessage); + scrollToBottom(); + } + } + + @Override + public void onError(CometChatException e) { + Log.e(TAG, "onError: "+e.getMessage()); + } + }); + }catch (Exception e) { + Log.e(TAG, "replyMessage: "+e.getMessage()); + } + } + private void scrollToBottom() { if (messageAdapter != null && messageAdapter.getItemCount() > 0) { rvChatListView.scrollToPosition(messageAdapter.getItemCount() - 1); @@ -1170,6 +1234,7 @@ private void addUserListener() { public void onUserOnline(User user) { Log.d(TAG, "onUserOnline: " + user.toString()); if (user.getUid().equals(Id)) { + status = CometChatConstants.USER_STATUS_ONLINE; tvStatus.setText(user.getStatus()); tvStatus.setTextColor(getResources().getColor(R.color.colorPrimary)); } @@ -1184,6 +1249,7 @@ public void onUserOffline(User user) { else tvStatus.setTextColor(getResources().getColor(android.R.color.black)); tvStatus.setText(user.getStatus()); + status = CometChatConstants.USER_STATUS_OFFLINE; } } }); @@ -1281,8 +1347,10 @@ private void setMessageReciept(MessageReceipt messageReceipt) { private void setTypingIndicator(TypingIndicator typingIndicator,boolean isShow) { if (typingIndicator.getReceiverType().equalsIgnoreCase(CometChatConstants.RECEIVER_TYPE_USER)) { Log.e(TAG, "onTypingStarted: " + typingIndicator); - if (Id != null && Id.equalsIgnoreCase(typingIndicator.getSender().getUid())) - typingIndicator(typingIndicator, isShow); + if (Id != null && Id.equalsIgnoreCase(typingIndicator.getSender().getUid())) { + if (typingIndicator.getMetadata() == null) + typingIndicator(typingIndicator, isShow); + } } else { if (Id != null && Id.equalsIgnoreCase(typingIndicator.getReceiverId())) typingIndicator(typingIndicator, isShow); @@ -1403,7 +1471,6 @@ private void removeGroupListener() { @Override public void onResume() { - onCloseAction(); super.onResume(); Log.d(TAG, "onResume: "); rvChatListView.removeItemDecoration(stickyHeaderDecoration); @@ -1426,18 +1493,6 @@ public void onResume() { } } - public void onCloseAction() { - if (messageAdapter != null) - messageAdapter.clearLongClickSelectedItem(); - composeBox.setVisibility(View.VISIBLE); - rlMessageAction.setVisibility(GONE); - userAvatar.setVisibility(View.VISIBLE); - ivCloseMessageAction.setVisibility(GONE); - ivCopyMessageAction.setVisibility(GONE); - if (getActivity() != null && ((AppCompatActivity) getActivity()).getSupportActionBar() != null) - ((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true); - } - @Override public void onAttach(Context context) { super.onAttach(context); @@ -1454,82 +1509,24 @@ public void onClick(View view) { int id = view.getId(); - if (id == R.id.delete_message) { - deleteMessage(baseMessage); - if (messageAdapter != null) { - messageAdapter.clearLongClickSelectedItem(); - messageAdapter.notifyDataSetChanged(); - } - onCloseAction(); - } - else if (id == R.id.forward_message) { - Intent intent = new Intent(getContext(), CometChatForwardMessageScreenActivity.class); - if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)){ - intent.putExtra(CometChatConstants.MESSAGE_TYPE_TEXT, ((TextMessage) baseMessage).getText()); - intent.putExtra(StringContract.IntentStrings.TYPE, CometChatConstants.MESSAGE_TYPE_TEXT); - } else if(baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_IMAGE) || - baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_AUDIO) || - baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_VIDEO) || - baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_FILE)) { - intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME, ((MediaMessage)baseMessage).getAttachment().getFileName()); - intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL, ((MediaMessage)baseMessage).getAttachment().getFileUrl()); - intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_MIME_TYPE, ((MediaMessage)baseMessage).getAttachment().getFileMimeType()); - intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION, ((MediaMessage)baseMessage).getAttachment().getFileExtension()); - intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE, ((MediaMessage)baseMessage).getAttachment().getFileSize()); - intent.putExtra(StringContract.IntentStrings.TYPE,baseMessage.getType()); - } - startActivity(intent); - } - else if (id == R.id.edit_message) { - if (baseMessage!=null&&baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { - isEdit = true; - tvMessageTitle.setText(getResources().getString(R.string.edit_message)); - tvMessageSubTitle.setText(((TextMessage) baseMessage).getText()); - composeBox.ivMic.setVisibility(GONE); - composeBox.ivSend.setVisibility(View.VISIBLE); - editMessageLayout.setVisibility(View.VISIBLE); - if (messageAdapter != null) { - messageAdapter.setSelectedMessage(baseMessage.getId()); - messageAdapter.notifyDataSetChanged(); - } - } - onCloseAction(); - } - else if (id == R.id.iv_copy_message_action) { - String message = ""; - for (BaseMessage bMessage : baseMessages) { - if (bMessage.getDeletedAt() == 0 && bMessage instanceof TextMessage) { - message = message + "[" + Utils.getLastMessageDate(bMessage.getSentAt()) + "] " + bMessage.getSender().getName() + ": " + ((TextMessage) bMessage).getText(); - } - } - Log.e(TAG, "onCopy: " + message); - ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); - ClipData clipData = ClipData.newPlainText("MessageAdapter", message); - clipboardManager.setPrimaryClip(clipData); - Toast.makeText(context, getResources().getString(R.string.text_copied_clipboard), Toast.LENGTH_LONG).show(); - if (messageAdapter != null) { - messageAdapter.clearLongClickSelectedItem(); - messageAdapter.notifyDataSetChanged(); - } - onCloseAction(); - } - else if (id == R.id.iv_close_message_action) { + if (id == R.id.iv_message_close) { if (messageAdapter != null) { messageAdapter.clearLongClickSelectedItem(); messageAdapter.notifyDataSetChanged(); } - onCloseAction(); + isEdit = false; + baseMessage = null; + editMessageLayout.setVisibility(GONE); } - else if (id == R.id.iv_message_close) { - if (messageAdapter != null) { + else if (id == R.id.iv_reply_close) { + if (messageAdapter!=null) { messageAdapter.clearLongClickSelectedItem(); messageAdapter.notifyDataSetChanged(); } - isEdit = false; + isReply = false; baseMessage = null; - editMessageLayout.setVisibility(GONE); + replyMessageLayout.setVisibility(GONE); } - else if (id == R.id.btn_unblock_user) { unblockUser(); } @@ -1560,9 +1557,94 @@ else if (id == R.id.chatList_toolbar) { } } + private void startForwardMessageActivity() { + Intent intent = new Intent(getContext(), CometChatForwardMessageScreenActivity.class); + if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)){ + intent.putExtra(CometChatConstants.MESSAGE_TYPE_TEXT, ((TextMessage) baseMessage).getText()); + intent.putExtra(StringContract.IntentStrings.TYPE, CometChatConstants.MESSAGE_TYPE_TEXT); + } else if(baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_IMAGE) || + baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_AUDIO) || + baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_VIDEO) || + baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME, ((MediaMessage)baseMessage).getAttachment().getFileName()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL, ((MediaMessage)baseMessage).getAttachment().getFileUrl()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_MIME_TYPE, ((MediaMessage)baseMessage).getAttachment().getFileMimeType()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION, ((MediaMessage)baseMessage).getAttachment().getFileExtension()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE, ((MediaMessage)baseMessage).getAttachment().getFileSize()); + intent.putExtra(StringContract.IntentStrings.TYPE,baseMessage.getType()); + } + startActivity(intent); + } + + private void shareMessage() { + if (baseMessage!=null && baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + Intent shareIntent = new Intent(); + shareIntent.setAction(Intent.ACTION_SEND); + shareIntent.putExtra(Intent.EXTRA_TITLE,getResources().getString(R.string.app_name)); + shareIntent.putExtra(Intent.EXTRA_TEXT, ((TextMessage)baseMessage).getText()); + shareIntent.setType("text/plain"); + Intent intent = Intent.createChooser(shareIntent, getResources().getString(R.string.share_message)); + startActivity(intent); + } else if (baseMessage!=null && baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_IMAGE)) { + String mediaName = ((MediaMessage)baseMessage).getAttachment().getFileName(); + Glide.with(context).asBitmap().load(((MediaMessage)baseMessage).getAttachment().getFileUrl()).into(new SimpleTarget() { + @Override + public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition transition) { + String path = MediaStore.Images.Media.insertImage(context.getContentResolver(), resource, mediaName, null); + Intent shareIntent = new Intent(); + shareIntent.setAction(Intent.ACTION_SEND); + shareIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(path)); + shareIntent.setType(((MediaMessage)baseMessage).getAttachment().getFileMimeType()); + Intent intent = Intent.createChooser(shareIntent, getResources().getString(R.string.share_message)); + startActivity(intent); + } + }); + } + } + private void startThreadActivity() { + Intent intent = new Intent(getContext(), CometChatThreadMessageActivity.class); + intent.putExtra(StringContract.IntentStrings.CONVERSATION_NAME,name); + intent.putExtra(StringContract.IntentStrings.NAME,baseMessage.getSender().getName()); + intent.putExtra(StringContract.IntentStrings.UID,baseMessage.getSender().getName()); + intent.putExtra(StringContract.IntentStrings.AVATAR,baseMessage.getSender().getAvatar()); + intent.putExtra(StringContract.IntentStrings.PARENT_ID,baseMessage.getId()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE,baseMessage.getType()); + intent.putExtra(StringContract.IntentStrings.REPLY_COUNT,baseMessage.getReplyCount()); + intent.putExtra(StringContract.IntentStrings.SENTAT,baseMessage.getSentAt()); + if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) + intent.putExtra(StringContract.IntentStrings.TEXTMESSAGE,((TextMessage)baseMessage).getText()); + else { + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME,((MediaMessage)baseMessage).getAttachment().getFileName()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION,((MediaMessage)baseMessage).getAttachment().getFileExtension()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL,((MediaMessage)baseMessage).getAttachment().getFileUrl()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE,((MediaMessage)baseMessage).getAttachment().getFileSize()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_MIME_TYPE,((MediaMessage)baseMessage).getAttachment().getFileMimeType()); + } + intent.putExtra(StringContract.IntentStrings.TYPE,type); + if (type.equals(CometChatConstants.CONVERSATION_TYPE_GROUP)) { + intent.putExtra(StringContract.IntentStrings.GUID,Id); + } + else { + intent.putExtra(StringContract.IntentStrings.UID,Id); + } + startActivity(intent); + } + @Override public void setLongMessageClick(List baseMessagesList) { Log.e(TAG, "setLongMessageClick: " + baseMessagesList); + isReply = false; + isEdit = false; + MessageActionFragment messageActionFragment = new MessageActionFragment(); + replyMessageLayout.setVisibility(GONE); + editMessageLayout.setVisibility(GONE); + boolean shareVisible = true; + boolean copyVisible = true; + boolean threadVisible = true; + boolean replyVisible = true; + boolean editVisible = true; + boolean deleteVisible = true; + boolean forwardVisible = true; List textMessageList = new ArrayList<>(); List mediaMessageList = new ArrayList<>(); for (BaseMessage baseMessage : baseMessagesList) { @@ -1577,38 +1659,25 @@ public void setLongMessageClick(List baseMessagesList) { if (basemessage != null && basemessage.getSender() != null) { if (!(basemessage instanceof Action) && basemessage.getDeletedAt() == 0) { baseMessage = basemessage; - ((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(false); - ivCloseMessageAction.setVisibility(View.VISIBLE); - ivCopyMessageAction.setVisibility(View.VISIBLE); - userAvatar.setVisibility(GONE); + if (basemessage.getReplyCount()>0) + threadVisible = false; + else + threadVisible = true; if (basemessage.getSender().getUid().equals(CometChat.getLoggedInUser().getUid())) { - tvDeleteMessage.setVisibility(View.VISIBLE); - tvEditMessage.setVisibility(View.VISIBLE); - tvEditMessage.setText(getResources().getString(R.string.edit)); - tvForwardMessage.setVisibility(View.VISIBLE); - rlMessageAction.setVisibility(View.VISIBLE); + deleteVisible = true; + editVisible = true; + forwardVisible = true; } else { - tvForwardMessage.setVisibility(View.VISIBLE); + editVisible = false; + forwardVisible = true; if (loggedInUserScope!=null && (loggedInUserScope.equals(CometChatConstants.SCOPE_ADMIN) || loggedInUserScope.equals(CometChatConstants.SCOPE_MODERATOR))) { - tvDeleteMessage.setVisibility(View.VISIBLE); - tvEditMessage.setVisibility(View.VISIBLE); + deleteVisible = true; } else { - tvDeleteMessage.setVisibility(GONE); - tvEditMessage.setVisibility(GONE); + deleteVisible = false; } - rlMessageAction.setVisibility(View.VISIBLE); } } } - } else if (textMessageList.size() == 0) { - onCloseAction(); - if (messageAdapter != null) - messageAdapter.clearLongClickSelectedItem(); - } else { - ivCopyMessageAction.setVisibility(View.VISIBLE); - tvEditMessage.setVisibility(GONE); - tvDeleteMessage.setVisibility(GONE); - tvForwardMessage.setVisibility(GONE); } if (mediaMessageList.size() == 1) { @@ -1616,29 +1685,146 @@ public void setLongMessageClick(List baseMessagesList) { if (basemessage != null && basemessage.getSender() != null) { if (!(basemessage instanceof Action) && basemessage.getDeletedAt() == 0) { baseMessage = basemessage; - ((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(false); - ivCloseMessageAction.setVisibility(View.VISIBLE); - ivCopyMessageAction.setVisibility(GONE); - userAvatar.setVisibility(GONE); + if (basemessage.getReplyCount()>0) + threadVisible = false; + else + threadVisible = true; + copyVisible = false; if (basemessage.getSender().getUid().equals(CometChat.getLoggedInUser().getUid())) { - tvDeleteMessage.setVisibility(View.VISIBLE); - tvEditMessage.setVisibility(GONE); - tvForwardMessage.setVisibility(View.VISIBLE); - rlMessageAction.setVisibility(View.VISIBLE); + deleteVisible = true; + editVisible = false; + forwardVisible = true; } else { if (loggedInUserScope!=null && (loggedInUserScope.equals(CometChatConstants.SCOPE_ADMIN) || loggedInUserScope.equals(CometChatConstants.SCOPE_MODERATOR))){ - tvDeleteMessage.setVisibility(View.VISIBLE); + deleteVisible = true; } else { - tvDeleteMessage.setVisibility(GONE); + deleteVisible = false; } - tvForwardMessage.setVisibility(View.VISIBLE); - tvEditMessage.setVisibility(GONE); - rlMessageAction.setVisibility(View.VISIBLE); - ivCloseMessageAction.setVisibility(View.VISIBLE); + forwardVisible = true; + editVisible = false; } } } } baseMessages = baseMessagesList; + Bundle bundle = new Bundle(); + bundle.putBoolean("copyVisible",copyVisible); + bundle.putBoolean("threadVisible",threadVisible); + bundle.putBoolean("shareVisible",shareVisible); + bundle.putBoolean("editVisible",editVisible); + bundle.putBoolean("deleteVisible",deleteVisible); + bundle.putBoolean("replyVisible",replyVisible); + bundle.putBoolean("forwardVisible",forwardVisible); + bundle.putString("type", CometChatMessageListActivity.class.getName()); + messageActionFragment.setArguments(bundle); + messageActionFragment.show(getFragmentManager(),messageActionFragment.getTag()); + messageActionFragment.setMessageActionListener(new MessageActionFragment.MessageActionListener() { + @Override + public void onThreadMessageClick() { + startThreadActivity(); + } + + @Override + public void onEditMessageClick() { + if (baseMessage!=null&&baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + isEdit = true; + isReply = false; + tvMessageTitle.setText(getResources().getString(R.string.edit_message)); + tvMessageSubTitle.setText(((TextMessage) baseMessage).getText()); + composeBox.ivMic.setVisibility(GONE); + composeBox.ivSend.setVisibility(View.VISIBLE); + editMessageLayout.setVisibility(View.VISIBLE); + composeBox.etComposeBox.setText(((TextMessage) baseMessage).getText()); + if (messageAdapter != null) { + messageAdapter.setSelectedMessage(baseMessage.getId()); + messageAdapter.notifyDataSetChanged(); + } + } + } + + @Override + public void onReplyMessageClick() { + replyMessage(); + } + + @Override + public void onForwardMessageClick() { + startForwardMessageActivity(); + } + + @Override + public void onDeleteMessageClick() { + deleteMessage(baseMessage); + if (messageAdapter != null) { + messageAdapter.clearLongClickSelectedItem(); + messageAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onCopyMessageClick() { + String message = ""; + for (BaseMessage bMessage : baseMessages) { + if (bMessage.getDeletedAt() == 0 && bMessage instanceof TextMessage) { + message = message + "[" + Utils.getLastMessageDate(bMessage.getSentAt()) + "] " + bMessage.getSender().getName() + ": " + ((TextMessage) bMessage).getText(); + } + } + Log.e(TAG, "onCopy: " + message); + ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clipData = ClipData.newPlainText("MessageAdapter", message); + clipboardManager.setPrimaryClip(clipData); + Toast.makeText(context, getResources().getString(R.string.text_copied_clipboard), Toast.LENGTH_LONG).show(); + if (messageAdapter != null) { + messageAdapter.clearLongClickSelectedItem(); + messageAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onShareMessageClick() { shareMessage(); } + }); + } + + + private void replyMessage() { + if (baseMessage != null) { + isReply = true; + replyTitle.setText(baseMessage.getSender().getName()); + replyMedia.setVisibility(View.VISIBLE); + if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + replyMessage.setText(((TextMessage) baseMessage).getText()); + replyMedia.setVisibility(GONE); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_IMAGE)) { + replyMessage.setText(getResources().getString(R.string.shared_a_image)); + Glide.with(context).load(((MediaMessage) baseMessage).getAttachment().getFileUrl()).into(replyMedia); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + String messageStr = String.format(getResources().getString(R.string.shared_a_audio), + Utils.getFileSize(((MediaMessage) baseMessage).getAttachment().getFileSize())); + replyMessage.setText(messageStr); + replyMessage.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_library_music_24dp, 0, 0, 0); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + replyMessage.setText(getResources().getString(R.string.shared_a_video)); + Glide.with(context).load(((MediaMessage) baseMessage).getAttachment().getFileUrl()).into(replyMedia); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + String messageStr = String.format(getResources().getString(R.string.shared_a_file), + Utils.getFileSize(((MediaMessage) baseMessage).getAttachment().getFileSize())); + replyMessage.setText(messageStr); + replyMessage.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_insert_drive_file_black_24dp, 0, 0, 0); + } + composeBox.ivMic.setVisibility(GONE); + composeBox.ivSend.setVisibility(View.VISIBLE); + replyMessageLayout.setVisibility(View.VISIBLE); + if (messageAdapter != null) { + messageAdapter.setSelectedMessage(baseMessage.getId()); + messageAdapter.notifyDataSetChanged(); + } + } + } + + @Override + public void handleDialogClose(DialogInterface dialog) { + if (messageAdapter!=null) + messageAdapter.clearLongClickSelectedItem(); + dialog.dismiss(); } } diff --git a/uikit/src/main/java/screen/threadconversation/CometChatThreadMessageActivity.java b/uikit/src/main/java/screen/threadconversation/CometChatThreadMessageActivity.java new file mode 100644 index 00000000..7cffc45d --- /dev/null +++ b/uikit/src/main/java/screen/threadconversation/CometChatThreadMessageActivity.java @@ -0,0 +1,204 @@ +package screen.threadconversation; + +import android.content.DialogInterface; +import android.content.Intent; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; + +import com.cometchat.pro.constants.CometChatConstants; +import com.cometchat.pro.models.BaseMessage; +import com.cometchat.pro.uikit.R; + +import java.util.List; + +import adapter.MessageAdapter; +import adapter.ThreadAdapter; +import constant.StringContract; +import listeners.MessageActionCloseListener; +import listeners.OnMessageLongClick; + +/** + +* Purpose - CometChatMessageListActivity.class is a Activity used to display messages using CometChatMessageScreen.class. It takes + parameter like TYPE to differentiate between User MessageScreen & Group MessageScreen. + + It passes parameters like UID (userID) ,AVATAR (userAvatar) ,NAME (userName) ,STATUS (userStatus) to CometChatMessageScreen.class + if TYPE is CometChatConstant.RECEIVER_TYPE_USER + + It passes parameters like GUID (groupID) ,AVATAR (groupIcon) ,NAME (groupName) ,GROUP_OWNER (groupOwner) to CometChatMessageScreen.class + if TYPE is CometChatConstant.RECEIVER_TYPE_GROUP + + @see CometChatConstants + @see CometChatThreadMessageScreen + + +*/ + +public class CometChatThreadMessageActivity extends AppCompatActivity implements ThreadAdapter.OnMessageLongClick { + + private static final String TAG = "CometChatMessageListAct"; + + private OnMessageLongClick messageLongClick; + + Fragment fragment = new CometChatThreadMessageScreen(); + + private String avatar; + + private String name; + + private String uid; + + private String messageType; + + private String message; + + private String messagefileName; + + private String mediaUrl; + + private String mediaExtension; + + private int messageId; + + private int mediaSize; + + private String mediaMime; + + private String type; + + private String Id; + + private long sentAt; + + private int replyCount; + + private String conversationName; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_cometchat_message_list); + + if (getIntent()!=null) { + Bundle bundle = new Bundle(); + + if (getIntent().hasExtra(StringContract.IntentStrings.CONVERSATION_NAME)) + conversationName = getIntent().getStringExtra(StringContract.IntentStrings.CONVERSATION_NAME); + if (getIntent().hasExtra(StringContract.IntentStrings.PARENT_ID)) + messageId = getIntent().getIntExtra(StringContract.IntentStrings.PARENT_ID,0); + if (getIntent().hasExtra(StringContract.IntentStrings.REPLY_COUNT)) + replyCount = getIntent().getIntExtra(StringContract.IntentStrings.REPLY_COUNT,0); + if (getIntent().hasExtra(StringContract.IntentStrings.AVATAR)) + avatar = getIntent().getStringExtra(StringContract.IntentStrings.AVATAR); + if (getIntent().hasExtra(StringContract.IntentStrings.NAME)) + name = getIntent().getStringExtra(StringContract.IntentStrings.NAME); + if (getIntent().hasExtra(StringContract.IntentStrings.MESSAGE_TYPE)) + messageType = getIntent().getStringExtra(StringContract.IntentStrings.MESSAGE_TYPE); + if (getIntent().hasExtra(StringContract.IntentStrings.UID)) + uid = getIntent().getStringExtra(StringContract.IntentStrings.UID); + if (getIntent().hasExtra(StringContract.IntentStrings.SENTAT)) + sentAt = getIntent().getLongExtra(StringContract.IntentStrings.SENTAT,0); + if (getIntent().hasExtra(StringContract.IntentStrings.TEXTMESSAGE)) + message = getIntent().getStringExtra(StringContract.IntentStrings.TEXTMESSAGE); + if (getIntent().hasExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME)) + messagefileName = getIntent().getStringExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME); + if (getIntent().hasExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE)) + mediaSize = getIntent().getIntExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE,0); + if (getIntent().hasExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL)) + mediaUrl = getIntent().getStringExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL); + if (getIntent().hasExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION)) + mediaExtension = getIntent().getStringExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION); + if (getIntent().hasExtra(StringContract.IntentStrings.TYPE)) + type = getIntent().getStringExtra(StringContract.IntentStrings.TYPE); + if (getIntent().hasExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_MIME_TYPE)) + mediaMime = getIntent().getStringExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_MIME_TYPE); + + if (type.equals(CometChatConstants.RECEIVER_TYPE_GROUP)) { + if (getIntent().hasExtra(StringContract.IntentStrings.GUID)) + Id = getIntent().getStringExtra(StringContract.IntentStrings.GUID); + } else{ + if (getIntent().hasExtra(StringContract.IntentStrings.UID)) + Id = getIntent().getStringExtra(StringContract.IntentStrings.UID); + } + bundle.putString(StringContract.IntentStrings.ID,Id); + bundle.putString(StringContract.IntentStrings.CONVERSATION_NAME,conversationName); + bundle.putString(StringContract.IntentStrings.TYPE,type); + bundle.putString(StringContract.IntentStrings.AVATAR, avatar); + bundle.putString(StringContract.IntentStrings.NAME, name); + bundle.putInt(StringContract.IntentStrings.PARENT_ID,messageId); + bundle.putInt(StringContract.IntentStrings.REPLY_COUNT,replyCount); + bundle.putString(StringContract.IntentStrings.MESSAGE_TYPE,messageType); + bundle.putString(StringContract.IntentStrings.UID, uid); + bundle.putLong(StringContract.IntentStrings.SENTAT, sentAt); + + if (messageType.equals(CometChatConstants.MESSAGE_TYPE_TEXT)) + bundle.putString(StringContract.IntentStrings.TEXTMESSAGE,message); + else { + bundle.putString(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL,mediaUrl); + bundle.putString(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME,messagefileName); + bundle.putString(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION,mediaExtension); + bundle.putInt(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE,mediaSize); + bundle.putString(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_MIME_TYPE,mediaMime); + } + + fragment.setArguments(bundle); + getSupportFragmentManager().beginTransaction().replace(R.id.ChatFragment, fragment).commit(); + } + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode,resultCode,data); + Log.d(TAG, "onActivityResult: "); + + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + Log.d(TAG, "onRequestPermissionsResult: "); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + return super.onCreateOptionsMenu(menu); + } + + @Override + public void onBackPressed() { + super.onBackPressed(); + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + return super.onOptionsItemSelected(item); + } + + @Override + public void setLongMessageClick(List baseMessage) { + if (fragment!=null) + ((OnMessageLongClick)fragment).setLongMessageClick(baseMessage); + } + + + @Override + protected void onResume() { + super.onResume(); + } + + @Override + protected void onPause() { + super.onPause(); + } + + public void handleDialogClose(DialogInterface dialog) { + ((MessageActionCloseListener)fragment).handleDialogClose(dialog); + } +} diff --git a/uikit/src/main/java/screen/threadconversation/CometChatThreadMessageScreen.java b/uikit/src/main/java/screen/threadconversation/CometChatThreadMessageScreen.java new file mode 100644 index 00000000..0819a406 --- /dev/null +++ b/uikit/src/main/java/screen/threadconversation/CometChatThreadMessageScreen.java @@ -0,0 +1,1831 @@ +package screen.threadconversation; + +import android.Manifest; +import android.content.ClipData; +import android.content.ClipboardManager; +import android.content.ContentResolver; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.content.res.ColorStateList; +import android.media.MediaPlayer; +import android.media.MediaRecorder; +import android.net.Uri; +import android.os.Build; +import android.os.Bundle; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.MediaController; +import android.widget.RelativeLayout; +import android.widget.TextView; +import android.widget.Toast; +import android.widget.VideoView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.Toolbar; +import androidx.core.widget.NestedScrollView; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.cometchat.pro.constants.CometChatConstants; +import com.cometchat.pro.core.CometChat; +import com.cometchat.pro.core.MessagesRequest; +import com.cometchat.pro.exceptions.CometChatException; +import com.cometchat.pro.models.Action; +import com.cometchat.pro.models.Attachment; +import com.cometchat.pro.models.BaseMessage; +import com.cometchat.pro.models.Group; +import com.cometchat.pro.models.MediaMessage; +import com.cometchat.pro.models.MessageReceipt; +import com.cometchat.pro.models.TextMessage; +import com.cometchat.pro.models.TypingIndicator; +import com.cometchat.pro.models.User; +import com.cometchat.pro.uikit.Avatar; +import com.cometchat.pro.uikit.ComposeBox; +import com.cometchat.pro.uikit.R; +import com.cometchat.pro.uikit.SmartReplyList; +import com.facebook.shimmer.ShimmerFrameLayout; +import com.google.android.material.button.MaterialButton; +import com.google.android.material.snackbar.Snackbar; + +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; + +import adapter.ThreadAdapter; +import constant.StringContract; +import listeners.ComposeActionListener; +import listeners.MessageActionCloseListener; +import listeners.OnItemClickListener; +import listeners.OnMessageLongClick; +import listeners.StickyHeaderDecoration; +import screen.CometChatForwardMessageScreenActivity; +import screen.CometChatGroupDetailScreenActivity; +import screen.CometChatUserDetailScreenActivity; +import screen.MessageActionFragment; +import utils.Extensions; +import utils.FontUtils; +import utils.KeyBoardUtils; +import utils.MediaUtils; +import utils.Utils; + +import static android.view.View.FOCUS_DOWN; +import static android.view.View.GONE; +import static android.view.View.VISIBLE; + +/** + * Purpose - CometChatMessageScreen class is a fragment used to display list of messages and perform certain action on click of message. + * It also provide search bar to perform search operation on the list of messages. User can send text,images,video and file as messages + * to each other and in groups. User can also perform actions like edit message,delete message and forward messages to other user and groups. + * + * @see CometChat + * @see User + * @see Group + * @see TextMessage + * @see MediaMessage + *

+ * Created on - 20th December 2019 + *

+ * Modified on - 16th January 2020 + */ + + +public class CometChatThreadMessageScreen extends Fragment implements View.OnClickListener, + OnMessageLongClick, MessageActionCloseListener { + + private static final String TAG = "CometChatThreadScreen"; + + private static final int LIMIT = 30; + + private RelativeLayout bottomLayout; + + private String name = ""; + + private String conversationName = ""; + + private MessagesRequest messagesRequest; //Used to fetch messages. + + private ComposeBox composeBox; + + private MediaRecorder mediaRecorder; + + private MediaPlayer mediaPlayer; + + private String audioFileNameWithPath; + + private RecyclerView rvChatListView; //Used to display list of messages. + + private ThreadAdapter messageAdapter; + + private LinearLayoutManager linearLayoutManager; + + private SmartReplyList rvSmartReply; + + private ShimmerFrameLayout messageShimmer; + + /** + * Avatar is a UI Kit Component which is used to display user and group avatars. + */ + private TextView tvName; + + private TextView tvTypingIndicator; + + private Avatar senderAvatar; + + private TextView senderName; + + private TextView tvSentAt; + + private String Id; + + private Context context; + + private LinearLayout blockUserLayout; + + private TextView blockedUserName; + + private StickyHeaderDecoration stickyHeaderDecoration; + + private String avatarUrl; + + private Toolbar toolbar; + + private boolean isBlockedByMe; + + private String loggedInUserScope; + + private RelativeLayout editMessageLayout; + + private TextView tvMessageTitle; + + private TextView tvMessageSubTitle; + + private RelativeLayout replyMessageLayout; + + private TextView replyTitle; + + private TextView replyMessage; + + private ImageView replyMedia; + + private ImageView replyClose; + + private BaseMessage baseMessage; + + private List baseMessages = new ArrayList<>(); + + private List messageList = new ArrayList<>(); + + private boolean isEdit; + + private boolean isReply; + + private Timer timer = new Timer(); + + private Timer typingTimer = new Timer(); + + private View view; + + private boolean isNoMoreMessages; + + private FontUtils fontUtils; + + private User loggedInUser = CometChat.getLoggedInUser(); + + String[] CAMERA_PERMISSION = {Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE}; + + private boolean isInProgress; + + private boolean isSmartReplyClicked; + + private RelativeLayout onGoingCallView; + + private TextView onGoingCallTxt; + + private ImageView onGoingCallClose; + + public int count = 0; + + private long messageSentAt; + + private String messageType; + + private String message; + + private String messageFileName; + + private int messageSize; + + private String messageMimeType; + + private String messageExtension; + + private int parentId; + + private String type; + + private String groupOwnerId; + + private TextView textMessage; + + private ImageView imageMessage; + + private VideoView videoMessage; + + private RelativeLayout fileMessage; + + private TextView fileName; + + private TextView fileSize; + + private TextView fileExtension; + + private TextView sentAt; + + private int replyCount; + + private TextView tvReplyCount; + + private NestedScrollView nestedScrollView; + + private LinearLayout noReplyMessages; + + private ImageView ivForwardMessage; + + private boolean isParent = true; + + private ImageView ivMoreOption; + + public CometChatThreadMessageScreen() { + // Required empty public constructor + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + handleArguments(); + if (getActivity() != null) + fontUtils = FontUtils.getInstance(getActivity()); + } + + /** + * This method is used to handle arguments passed to this fragment. + */ + private void handleArguments() { + if (getArguments() != null) { + parentId = getArguments().getInt(StringContract.IntentStrings.PARENT_ID,0); + replyCount = getArguments().getInt(StringContract.IntentStrings.REPLY_COUNT,0); + type = getArguments().getString(StringContract.IntentStrings.TYPE); + Id = getArguments().getString(StringContract.IntentStrings.ID); + avatarUrl = getArguments().getString(StringContract.IntentStrings.AVATAR); + name = getArguments().getString(StringContract.IntentStrings.NAME); + conversationName = getArguments().getString(StringContract.IntentStrings.CONVERSATION_NAME); + messageType = getArguments().getString(StringContract.IntentStrings.MESSAGE_TYPE); + messageSentAt = getArguments().getLong(StringContract.IntentStrings.SENTAT); + if (messageType.equals(CometChatConstants.MESSAGE_TYPE_TEXT)){ + message = getArguments().getString(StringContract.IntentStrings.TEXTMESSAGE); + } else { + message = getArguments().getString(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL); + messageFileName = getArguments().getString(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME); + messageExtension = getArguments().getString(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION); + messageSize = getArguments().getInt(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE,0); + messageMimeType = getArguments().getString(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_MIME_TYPE); + } + } + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + // Inflate the layout for this fragment + view = inflater.inflate(R.layout.fragment_thread_message, container, false); + initViewComponent(view); + return view; + } + + + /** + * This is a main method which is used to initialize the view for this fragment. + * + * @param view + */ + private void initViewComponent(View view) { + + setHasOptionsMenu(true); + nestedScrollView = view.findViewById(R.id.nested_scrollview); + noReplyMessages = view.findViewById(R.id.no_reply_layout); + ivMoreOption = view.findViewById(R.id.ic_more_option); + ivMoreOption.setOnClickListener(this); + ivForwardMessage = view.findViewById(R.id.ic_forward_option); + ivForwardMessage.setOnClickListener(this); + textMessage = view.findViewById(R.id.tv_textMessage); + textMessage.setText(message); + imageMessage = view.findViewById(R.id.iv_imageMessage); + videoMessage = view.findViewById(R.id.vv_videoMessage); + fileMessage = view.findViewById(R.id.rl_fileMessage); + fileName = view.findViewById(R.id.tvFileName); + fileSize = view.findViewById(R.id.tvFileSize); + fileExtension = view.findViewById(R.id.tvFileExtension); + + Glide.with(context).load(message).into(imageMessage); + + MediaController mediacontroller = new MediaController(getContext()); + mediacontroller.setAnchorView(videoMessage); + videoMessage.setMediaController(mediacontroller); + videoMessage.setVideoURI(Uri.parse(message)); + + if (messageFileName!=null) + fileName.setText(messageFileName); + if (messageExtension!=null) + fileExtension.setText(messageExtension); + + fileSize.setText(Utils.getFileSize(messageSize)); + + if (messageType.equals(CometChatConstants.MESSAGE_TYPE_IMAGE)) { + textMessage.setVisibility(GONE); + imageMessage.setVisibility(View.VISIBLE); + videoMessage.setVisibility(GONE); + fileMessage.setVisibility(GONE); + } else if (messageType.equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + videoMessage.setVisibility(VISIBLE); + imageMessage.setVisibility(GONE); + textMessage.setVisibility(GONE); + fileMessage.setVisibility(GONE); + } + else if (messageType.equals(CometChatConstants.MESSAGE_TYPE_FILE) || + messageType.equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + fileMessage.setVisibility(VISIBLE); + imageMessage.setVisibility(GONE); + videoMessage.setVisibility(GONE); + textMessage.setVisibility(GONE); + } else if (messageType.equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + videoMessage.setVisibility(GONE); + fileMessage.setVisibility(GONE); + imageMessage.setVisibility(GONE); + textMessage.setVisibility(View.VISIBLE); + } + bottomLayout = view.findViewById(R.id.bottom_layout); + composeBox = view.findViewById(R.id.message_box); + messageShimmer = view.findViewById(R.id.shimmer_layout); + composeBox = view.findViewById(R.id.message_box); + + setComposeBoxListener(); + + rvSmartReply = view.findViewById(R.id.rv_smartReply); + + editMessageLayout = view.findViewById(R.id.editMessageLayout); + tvMessageTitle = view.findViewById(R.id.tv_message_layout_title); + tvMessageSubTitle = view.findViewById(R.id.tv_message_layout_subtitle); + ImageView ivMessageClose = view.findViewById(R.id.iv_message_close); + ivMessageClose.setOnClickListener(this); + + replyMessageLayout = view.findViewById(R.id.replyMessageLayout); + replyTitle = view.findViewById(R.id.tv_reply_layout_title); + replyMessage = view.findViewById(R.id.tv_reply_layout_subtitle); + replyMedia = view.findViewById(R.id.iv_reply_media); + replyClose = view.findViewById(R.id.iv_reply_close); + replyClose.setOnClickListener(this); + + senderAvatar = view.findViewById(R.id.av_sender); + setAvatar(); + senderName = view.findViewById(R.id.tv_sender_name); + senderName.setText(name); + sentAt = view.findViewById(R.id.tv_message_time); + sentAt.setText(String.format(getString(R.string.sentAtTxt),Utils.getMessageDate(messageSentAt))); + tvReplyCount = view.findViewById(R.id.thread_reply_count); + rvChatListView = view.findViewById(R.id.rv_message_list); + if (replyCount>0) { + tvReplyCount.setText(replyCount + " Replies"); + noReplyMessages.setVisibility(GONE); + } + else { + noReplyMessages.setVisibility(VISIBLE); + } + + MaterialButton unblockUserBtn = view.findViewById(R.id.btn_unblock_user); + unblockUserBtn.setOnClickListener(this); + blockedUserName = view.findViewById(R.id.tv_blocked_user_name); + blockUserLayout = view.findViewById(R.id.blocked_user_layout); + tvName = view.findViewById(R.id.tv_name); + tvTypingIndicator = view.findViewById(R.id.tv_typing); + toolbar = view.findViewById(R.id.chatList_toolbar); + toolbar.setOnClickListener(this); + linearLayoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false); + tvName.setTypeface(fontUtils.getTypeFace(FontUtils.robotoMedium)); + tvName.setText(String.format(getString(R.string.thread_in_name),conversationName)); + setAvatar(); + rvChatListView.setLayoutManager(linearLayoutManager); + + ((AppCompatActivity) getActivity()).setSupportActionBar(toolbar); + ((AppCompatActivity) getActivity()).getSupportActionBar().setDisplayHomeAsUpEnabled(true); + if (Utils.isDarkMode(context)) { + ivMoreOption.setImageTintList(ColorStateList.valueOf(getResources().getColor(R.color.textColorWhite))); + ivForwardMessage.setImageTintList(ColorStateList.valueOf(getResources().getColor(R.color.textColorWhite))); + bottomLayout.setBackgroundColor(getResources().getColor(R.color.darkModeBackground)); + toolbar.setBackgroundColor(getResources().getColor(R.color.grey)); + editMessageLayout.setBackground(getResources().getDrawable(R.drawable.left_border_dark)); + replyMessageLayout.setBackground(getResources().getDrawable(R.drawable.left_border_dark)); + composeBox.setBackgroundColor(getResources().getColor(R.color.darkModeBackground)); + rvChatListView.setBackgroundColor(getResources().getColor(R.color.darkModeBackground)); + tvName.setTextColor(getResources().getColor(R.color.textColorWhite)); + } else { + ivMoreOption.setImageTintList(ColorStateList.valueOf(getResources().getColor(R.color.primaryTextColor))); + ivForwardMessage.setImageTintList(ColorStateList.valueOf(getResources().getColor(R.color.primaryTextColor))); + bottomLayout.setBackgroundTintList(ColorStateList.valueOf(getResources().getColor(R.color.textColorWhite))); + toolbar.setBackgroundColor(getResources().getColor(R.color.textColorWhite)); + editMessageLayout.setBackground(getResources().getDrawable(R.drawable.left_border)); + replyMessageLayout.setBackground(getResources().getDrawable(R.drawable.left_border)); + composeBox.setBackgroundColor(getResources().getColor(R.color.textColorWhite)); + rvChatListView.setBackgroundColor(getResources().getColor(R.color.textColorWhite)); + tvName.setTextColor(getResources().getColor(R.color.primaryTextColor)); + } + composeBox.etComposeBox.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + + } + + @Override + public void afterTextChanged(Editable s) { + if (s.length()>0) { + composeBox.ivMic.setVisibility(GONE); + composeBox.ivSend.setVisibility(View.VISIBLE); + } else { + composeBox.ivMic.setVisibility(View.VISIBLE); + composeBox.ivSend.setVisibility(GONE);; + } + } + }); + KeyBoardUtils.setKeyboardVisibilityListener(getActivity(),nestedScrollView, keyboardVisible -> { + if (keyboardVisible) { + scrollToBottom(); + composeBox.ivMic.setVisibility(GONE); + composeBox.ivSend.setVisibility(View.VISIBLE); + } else { + if (isEdit) { + composeBox.ivMic.setVisibility(GONE); + composeBox.ivSend.setVisibility(View.VISIBLE); + }else { + composeBox.ivMic.setVisibility(View.VISIBLE); + composeBox.ivSend.setVisibility(GONE);; + } + } + }); + + + // Uses to fetch next list of messages if rvChatListView (RecyclerView) is scrolled in downward direction. + rvChatListView.addOnScrollListener(new RecyclerView.OnScrollListener() { + @Override + public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) { + + //for toolbar elevation animation i.e stateListAnimator + toolbar.setSelected(rvChatListView.canScrollVertically(-1)); + } + + @Override + public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { + + if (!isNoMoreMessages && !isInProgress) { + if (linearLayoutManager.findFirstVisibleItemPosition() == 10 || !rvChatListView.canScrollVertically(-1)) { + isInProgress = true; + fetchMessage(); + } + } + } + + }); + rvSmartReply.setItemClickListener(new OnItemClickListener() { + @Override + public void OnItemClick(String var, int position) { + if (!isSmartReplyClicked) { + isSmartReplyClicked = true; + rvSmartReply.setVisibility(GONE); + sendMessage(var); + } + } + }); + + //Check Ongoing Call + onGoingCallView = view.findViewById(R.id.ongoing_call_view); + onGoingCallClose = view.findViewById(R.id.close_ongoing_view); + onGoingCallTxt = view.findViewById(R.id.ongoing_call); + checkOnGoingCall(); + } + + private void checkOnGoingCall() { + if(CometChat.getActiveCall()!=null && CometChat.getActiveCall().getCallStatus().equals(CometChatConstants.CALL_STATUS_ONGOING) && CometChat.getActiveCall().getSessionId()!=null) { + if(onGoingCallView!=null) + onGoingCallView.setVisibility(View.VISIBLE); + if(onGoingCallTxt!=null) { + onGoingCallTxt.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onGoingCallView.setVisibility(View.GONE); + Utils.joinOnGoingCall(getContext()); + } + }); + } + if(onGoingCallClose!=null) { + onGoingCallClose.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onGoingCallView.setVisibility(GONE); + } + }); + } + } else if (CometChat.getActiveCall()!=null){ + if (onGoingCallView!=null) + onGoingCallView.setVisibility(GONE); + Log.e(TAG, "checkOnGoingCall: "+CometChat.getActiveCall().toString()); + } + } + + private void setComposeBoxListener() { + + composeBox.setComposeBoxListener(new ComposeActionListener() { + @Override + public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) { + + } + + @Override + public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) { + if (charSequence.length()>0) { + sendTypingIndicator(false); + } else { + sendTypingIndicator(true); + } + } + + @Override + public void afterTextChanged(Editable editable) { + if (typingTimer == null) { + typingTimer = new Timer(); + } + endTypingTimer(); + } + + @Override + public void onAudioActionClicked(ImageView audioIcon) { + if (Utils.hasPermissions(getContext(),Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + startActivityForResult(MediaUtils.openAudio(getActivity()),StringContract.RequestCode.AUDIO); + } else { + requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},StringContract.RequestCode.AUDIO); + } + } + + @Override + public void onCameraActionClicked(ImageView cameraIcon) { + if (Utils.hasPermissions(getContext(), CAMERA_PERMISSION)) { + startActivityForResult(MediaUtils.openCamera(getContext()), StringContract.RequestCode.CAMERA); + } else { + requestPermissions(CAMERA_PERMISSION, StringContract.RequestCode.CAMERA); + } + } + + + @Override + public void onGalleryActionClicked(ImageView galleryIcon) { + if (Utils.hasPermissions(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + startActivityForResult(MediaUtils.openGallery(getActivity()), StringContract.RequestCode.GALLERY); + } else { + requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, StringContract.RequestCode.GALLERY); + } + } + + @Override + public void onFileActionClicked(ImageView fileIcon) { + if (Utils.hasPermissions(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) { + startActivityForResult(MediaUtils.getFileIntent(StringContract.IntentStrings.EXTRA_MIME_DOC), StringContract.RequestCode.FILE); + } else { + requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, StringContract.RequestCode.FILE); + } + } + + @Override + public void onSendActionClicked(EditText editText) { + String message = editText.getText().toString().trim(); + editText.setText(""); + editText.setHint(getString(R.string.message)); + if (isEdit) { + if (isParent) + editThread(message); + else { + editMessage(baseMessage, message); + } + editMessageLayout.setVisibility(GONE); + } else if(isReply){ + replyMessage(baseMessage,message); + replyMessageLayout.setVisibility(GONE); + } else if (!message.isEmpty()) + sendMessage(message); + } + + @Override + public void onVoiceNoteComplete(String string) { + if (string != null) { + File audioFile = new File(string); + sendMediaMessage(audioFile, CometChatConstants.MESSAGE_TYPE_AUDIO); + } + } + }); + } + + private void editThread(String editMessage) { + isEdit = false; + + TextMessage textmessage; + if (type.equalsIgnoreCase(CometChatConstants.RECEIVER_TYPE_USER)) + textmessage = new TextMessage(Id, editMessage, CometChatConstants.RECEIVER_TYPE_USER); + else + textmessage = new TextMessage(Id, editMessage, CometChatConstants.RECEIVER_TYPE_GROUP); + sendTypingIndicator(true); + textmessage.setId(parentId); + CometChat.editMessage(textmessage, new CometChat.CallbackListener() { + @Override + public void onSuccess(BaseMessage baseMessage) { + textMessage.setText(((TextMessage)baseMessage).getText()); + message = ((TextMessage) baseMessage).getText(); + } + + @Override + public void onError(CometChatException e) { + Log.d(TAG, "onError: " + e.getMessage()); + } + }); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + + Log.d(TAG, "onRequestPermissionsResult: "); + switch (requestCode) { + + case StringContract.RequestCode.CAMERA: + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED && grantResults[1] == PackageManager.PERMISSION_GRANTED) + + startActivityForResult(MediaUtils.openCamera(getActivity()), StringContract.RequestCode.CAMERA); + else + showSnackBar(view.findViewById(R.id.message_box), getResources().getString(R.string.grant_camera_permission)); + break; + case StringContract.RequestCode.GALLERY: + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) + startActivityForResult(MediaUtils.openGallery(getActivity()), StringContract.RequestCode.GALLERY); + else + showSnackBar(view.findViewById(R.id.message_box), getResources().getString(R.string.grant_storage_permission)); + break; + case StringContract.RequestCode.FILE: + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) + startActivityForResult(MediaUtils.getFileIntent(StringContract.IntentStrings.EXTRA_MIME_DOC), StringContract.RequestCode.FILE); + else + showSnackBar(view.findViewById(R.id.message_box), getResources().getString(R.string.grant_storage_permission)); + break; + } + } + + private void showSnackBar(View view, String message) { + Snackbar.make(view, message, Snackbar.LENGTH_SHORT).show(); + } + + @Override + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + } + + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + + if (item.getItemId() == android.R.id.home) { + if (getActivity() != null) { + getActivity().onBackPressed(); + } + + return true; + } + return super.onOptionsItemSelected(item); + } + + /** + * Incase if user is blocked already, then this method is used to unblock the user . + * + * @see CometChat#unblockUsers(List, CometChat.CallbackListener) + */ + private void unblockUser() { + ArrayList uids = new ArrayList<>(); + uids.add(Id); + CometChat.unblockUsers(uids, new CometChat.CallbackListener>() { + @Override + public void onSuccess(HashMap stringStringHashMap) { + Snackbar.make(rvChatListView,String.format(getResources().getString(R.string.user_unblocked),name),Snackbar.LENGTH_LONG).show(); + blockUserLayout.setVisibility(GONE); + isBlockedByMe = false; + messagesRequest=null; + } + + @Override + public void onError(CometChatException e) { + Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_LONG).show(); + } + }); + } + + /** + * This method is used to fetch message of users & groups. For user it fetches previous 100 messages at + * a time and for groups it fetches previous 30 messages. You can change limit of messages by modifying + * number in setLimit() + * This method also mark last message as read using markMessageAsRead() present in this class. + * So all the above messages get marked as read. + * + * @see MessagesRequest#fetchPrevious(CometChat.CallbackListener) + */ + private void fetchMessage() { + + if (messagesRequest == null) { + messagesRequest = new MessagesRequest.MessagesRequestBuilder().setLimit(LIMIT).setParentMessageId(parentId).hideMessagesFromBlockedUsers(true).build(); + } + messagesRequest.fetchPrevious(new CometChat.CallbackListener>() { + + @Override + public void onSuccess(List baseMessages) { + isInProgress = false; + List filteredMessageList = filterBaseMessages(baseMessages); + initMessageAdapter(filteredMessageList); + if (baseMessages.size() != 0) { + stopHideShimmer(); + BaseMessage baseMessage = baseMessages.get(baseMessages.size() - 1); + markMessageAsRead(baseMessage); + } + + if (baseMessages.size() == 0) { + stopHideShimmer(); + isNoMoreMessages = true; + } + } + + @Override + public void onError(CometChatException e) { + Log.d(TAG, "onError: " + e.getMessage()); + } + }); + } + + private void stopHideShimmer() { + messageShimmer.stopShimmer(); + messageShimmer.setVisibility(GONE); + } + + + private List filterBaseMessages(List baseMessages) { + List tempList = new ArrayList<>(); + for(BaseMessage baseMessage : baseMessages) + { + Log.e(TAG, "filterBaseMessages: "+baseMessage.getSentAt()); + if (baseMessage.getCategory().equals(CometChatConstants.CATEGORY_ACTION)) { + Action action = ((Action)baseMessage); + if (action.getAction().equals(CometChatConstants.ActionKeys.ACTION_MESSAGE_DELETED) || + action.getAction().equals(CometChatConstants.ActionKeys.ACTION_MESSAGE_EDITED)) { + } + else { + tempList.add(baseMessage); + } + } + else { + tempList.add(baseMessage); + } + } + return tempList; + } + + private void getSmartReplyList(BaseMessage baseMessage) { + + HashMap extensionList = Extensions.extensionCheck(baseMessage); + if (extensionList != null && extensionList.containsKey("smartReply")) { + rvSmartReply.setVisibility(View.VISIBLE); + JSONObject replyObject = extensionList.get("smartReply"); + List replyList = new ArrayList<>(); + try { + replyList.add(replyObject.getString("reply_positive")); + replyList.add(replyObject.getString("reply_neutral")); + replyList.add(replyObject.getString("reply_negative")); + } catch (Exception e) { + Log.e(TAG, "onSuccess: " + e.getMessage()); + } + setSmartReplyAdapter(replyList); + } else { + rvSmartReply.setVisibility(GONE); + } + } + + private void setSmartReplyAdapter(List replyList) { + rvSmartReply.setSmartReplyList(replyList); + scrollToBottom(); + } + + + /** + * This method is used to initialize the message adapter if it is empty else it helps + * to update the messagelist in adapter. + * + * @param messageList is a list of messages which will be added. + */ + private void initMessageAdapter(List messageList) { + if (messageAdapter == null) { + messageAdapter = new ThreadAdapter(getActivity(), messageList, type); + rvChatListView.setAdapter(messageAdapter); + messageAdapter.notifyDataSetChanged(); + } else { + messageAdapter.updateList(messageList); + + } + if (!isBlockedByMe && rvSmartReply.getAdapter().getItemCount()==0&&rvSmartReply.getVisibility() == GONE) { + BaseMessage lastMessage = messageAdapter.getLastMessage(); + checkSmartReply(lastMessage); + } + } + + /** + * This method is used to send typing indicator to other users and groups. + * + * @param isEnd is boolean which is used to differentiate between startTyping & endTyping Indicators. + * @see CometChat#startTyping(TypingIndicator) + * @see CometChat#endTyping(TypingIndicator) + */ + private void sendTypingIndicator(boolean isEnd) { + if (isEnd) { + if (type.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + CometChat.endTyping(new TypingIndicator(Id, CometChatConstants.RECEIVER_TYPE_USER)); + } else { + CometChat.endTyping(new TypingIndicator(Id, CometChatConstants.RECEIVER_TYPE_GROUP)); + } + } else { + if (type.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + CometChat.startTyping(new TypingIndicator(Id, CometChatConstants.RECEIVER_TYPE_USER)); + } else { + CometChat.startTyping(new TypingIndicator(Id, CometChatConstants.RECEIVER_TYPE_GROUP)); + } + } + } + + private void endTypingTimer() { + if (typingTimer!=null) { + typingTimer.schedule(new TimerTask() { + @Override + public void run() { + sendTypingIndicator(true); + } + }, 2000); + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + super.onActivityResult(requestCode, resultCode, data); + Log.d(TAG, "onActivityResult: "); + + switch (requestCode) { + case StringContract.RequestCode.AUDIO: + if (data!=null) { + File file = MediaUtils.getRealPath(getContext(),data.getData()); + ContentResolver cr = getActivity().getContentResolver(); + sendMediaMessage(file,CometChatConstants.MESSAGE_TYPE_AUDIO); + } + break; + case StringContract.RequestCode.GALLERY: + if (data != null) { + + File file = MediaUtils.getRealPath(getContext(), data.getData()); + ContentResolver cr = getActivity().getContentResolver(); + String mimeType = cr.getType(data.getData()); + if (mimeType!=null && mimeType.contains("image")) { + if (file.exists()) + sendMediaMessage(file, CometChatConstants.MESSAGE_TYPE_IMAGE); + else + Snackbar.make(rvChatListView, R.string.file_not_exist, Snackbar.LENGTH_LONG).show(); + } + else { + if (file.exists()) + sendMediaMessage(file, CometChatConstants.MESSAGE_TYPE_VIDEO); + else + Snackbar.make(rvChatListView, R.string.file_not_exist, Snackbar.LENGTH_LONG).show(); + } + } + + break; + case StringContract.RequestCode.CAMERA: + File file; + if (Build.VERSION.SDK_INT >= 29) { + file = MediaUtils.getRealPath(getContext(), MediaUtils.uri); + } else { + file = new File(MediaUtils.pictureImagePath); + } + if (file.exists()) + sendMediaMessage(file, CometChatConstants.MESSAGE_TYPE_IMAGE); + else + Snackbar.make(rvChatListView,R.string.file_not_exist,Snackbar.LENGTH_LONG).show(); + + break; + case StringContract.RequestCode.FILE: + if (data != null) + sendMediaMessage(MediaUtils.getRealPath(getActivity(), data.getData()), CometChatConstants.MESSAGE_TYPE_FILE); + break; + case StringContract.RequestCode.BLOCK_USER: + name = data.getStringExtra(""); + break; + } + + } + + + /** + * This method is used to send media messages to other users and group. + * + * @param file is an object of File which is been sent within the message. + * @param filetype is a string which indicate a type of file been sent within the message. + * @see CometChat#sendMediaMessage(MediaMessage, CometChat.CallbackListener) + * @see MediaMessage + */ + private void sendMediaMessage(File file, String filetype) { + MediaMessage mediaMessage; + + if (type.equalsIgnoreCase(CometChatConstants.RECEIVER_TYPE_USER)) + mediaMessage = new MediaMessage(Id, file, filetype, CometChatConstants.RECEIVER_TYPE_USER); + else + mediaMessage = new MediaMessage(Id, file, filetype, CometChatConstants.RECEIVER_TYPE_GROUP); + + JSONObject jsonObject = new JSONObject(); + try { + jsonObject.put("path", file.getAbsolutePath()); + } catch (JSONException e) { + e.printStackTrace(); + } + mediaMessage.setMetadata(jsonObject); + mediaMessage.setParentMessageId(parentId); + CometChat.sendMediaMessage(mediaMessage, new CometChat.CallbackListener() { + @Override + public void onSuccess(MediaMessage mediaMessage) { + noReplyMessages.setVisibility(GONE); + Log.d(TAG, "sendMediaMessage onSuccess: " + mediaMessage.toString()); + if (messageAdapter != null) { + setReply(); + messageAdapter.addMessage(mediaMessage); + scrollToBottom(); + } + } + + @Override + public void onError(CometChatException e) { + if (getActivity() != null) { + Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show(); + } + } + }); + } + + /** + * This method is used to get details of reciever. + * + * @see CometChat#getUser(String, CometChat.CallbackListener) + */ + private void getUser() { + + CometChat.getUser(Id, new CometChat.CallbackListener() { + @Override + public void onSuccess(User user) { + + if (getActivity() != null) { + if (user.isBlockedByMe()) { + isBlockedByMe = true; + rvSmartReply.setVisibility(GONE); + toolbar.setSelected(false); + blockedUserName.setText("You've blocked " + user.getName()); + blockUserLayout.setVisibility(View.VISIBLE); + } else { + isBlockedByMe = false; + blockUserLayout.setVisibility(GONE); + } + tvName.setText(String.format(getString(R.string.thread_in_name),user.getName())); + Log.d(TAG, "onSuccess: " + user.toString()); + } + + } + + @Override + public void onError(CometChatException e) { + Toast.makeText(context, e.getMessage(), Toast.LENGTH_SHORT).show(); + } + }); + } + + private void setAvatar() { + if (avatarUrl != null && !avatarUrl.isEmpty()) + senderAvatar.setAvatar(avatarUrl); + else { + senderAvatar.setInitials(name); + } + } + + /** + * This method is used to get Group Details. + * + * @see CometChat#getGroup(String, CometChat.CallbackListener) + */ + private void getGroup() { + + CometChat.getGroup(Id, new CometChat.CallbackListener() { + @Override + public void onSuccess(Group group) { + if (getActivity() != null) { + loggedInUserScope = group.getScope(); + groupOwnerId = group.getOwner(); + + tvName.setText(String.format(getString(R.string.thread_in_name),group.getName())); + } + + } + + @Override + public void onError(CometChatException e) { + + } + }); + } + + /** + * This method is used to send Text Message to other users and groups. + * + * @param message is a String which is been sent as message. + * @see TextMessage + * @see CometChat#sendMessage(TextMessage, CometChat.CallbackListener) + */ + private void sendMessage(String message) { + TextMessage textMessage; + if (type.equalsIgnoreCase(CometChatConstants.RECEIVER_TYPE_USER)) + textMessage = new TextMessage(Id, message, CometChatConstants.RECEIVER_TYPE_USER); + else + textMessage = new TextMessage(Id, message, CometChatConstants.RECEIVER_TYPE_GROUP); + + textMessage.setParentMessageId(parentId); + sendTypingIndicator(true); + + CometChat.sendMessage(textMessage, new CometChat.CallbackListener() { + @Override + public void onSuccess(TextMessage textMessage) { + noReplyMessages.setVisibility(GONE); + isSmartReplyClicked=false; + if (messageAdapter != null) { + setReply(); + MediaUtils.playSendSound(context,R.raw.outgoing_message); + messageAdapter.addMessage(textMessage); + scrollToBottom(); + } + } + + @Override + public void onError(CometChatException e) { + Log.d(TAG, "onError: " + e.getMessage()); + } + }); + + } + + /** + * This method is used to delete the message. + * + * @param baseMessage is an object of BaseMessage which is being used to delete the message. + * @see BaseMessage + * @see CometChat#deleteMessage(int, CometChat.CallbackListener) + */ + private void deleteMessage(BaseMessage baseMessage) { + CometChat.deleteMessage(baseMessage.getId(), new CometChat.CallbackListener() { + @Override + public void onSuccess(BaseMessage baseMessage) { + if (messageAdapter != null) + messageAdapter.setUpdatedMessage(baseMessage); + } + + @Override + public void onError(CometChatException e) { + Log.d(TAG, "onError: " + e.getMessage()); + } + }); + } + + /** + * This method is used to edit the message. This methods takes old message and change text of old + * message with new message i.e String and update it. + * + * @param baseMessage is an object of BaseMessage, It is a old message which is going to be edited. + * @param message is String, It is a new message which will be replaced with text of old message. + * @see TextMessage + * @see BaseMessage + * @see CometChat#editMessage(BaseMessage, CometChat.CallbackListener) + */ + private void editMessage(BaseMessage baseMessage, String message) { + + isEdit = false; + isParent = true; + TextMessage textMessage; + if (baseMessage.getReceiverType().equalsIgnoreCase(CometChatConstants.RECEIVER_TYPE_USER)) + textMessage = new TextMessage(baseMessage.getReceiverUid(), message, CometChatConstants.RECEIVER_TYPE_USER); + else + textMessage = new TextMessage(baseMessage.getReceiverUid(), message, CometChatConstants.RECEIVER_TYPE_GROUP); + sendTypingIndicator(true); + textMessage.setId(baseMessage.getId()); + CometChat.editMessage(textMessage, new CometChat.CallbackListener() { + @Override + public void onSuccess(BaseMessage message) { + if (messageAdapter != null) { + Log.e(TAG, "onSuccess: " + message.toString()); + messageAdapter.setUpdatedMessage(message); + } + } + + @Override + public void onError(CometChatException e) { + Log.d(TAG, "onError: " + e.getMessage()); + } + }); + + } + + /** + * This method is used to send reply message by link previous message with new message. + * @param baseMessage is a linked message + * @param message is a String. It will be new message sent as reply. + */ + private void replyMessage(BaseMessage baseMessage, String message) { + isReply = false; + try { + TextMessage textMessage; + if (type.equalsIgnoreCase(CometChatConstants.RECEIVER_TYPE_USER)) + textMessage = new TextMessage(Id, message, CometChatConstants.RECEIVER_TYPE_USER); + else + textMessage = new TextMessage(Id, message, CometChatConstants.RECEIVER_TYPE_GROUP); + JSONObject jsonObject = new JSONObject(); + JSONObject replyObject = new JSONObject(); + if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + replyObject.put("type",CometChatConstants.MESSAGE_TYPE_TEXT); + replyObject.put("message", ((TextMessage) baseMessage).getText()); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_IMAGE)) { + replyObject.put("type",CometChatConstants.MESSAGE_TYPE_IMAGE); + replyObject.put("message", "image"); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + replyObject.put("type",CometChatConstants.MESSAGE_TYPE_VIDEO); + replyObject.put("message", "video"); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + replyObject.put("type",CometChatConstants.MESSAGE_TYPE_FILE); + replyObject.put("message", "file"); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + replyObject.put("type", CometChatConstants.MESSAGE_TYPE_AUDIO); + replyObject.put("message", "audio"); + } + replyObject.put("name",baseMessage.getSender().getName()); + replyObject.put("avatar",baseMessage.getSender().getAvatar()); + jsonObject.put("reply",replyObject); + textMessage.setParentMessageId(parentId); + textMessage.setMetadata(jsonObject); + sendTypingIndicator(true); + CometChat.sendMessage(textMessage, new CometChat.CallbackListener() { + @Override + public void onSuccess(TextMessage textMessage) { + if (messageAdapter != null) { + MediaUtils.playSendSound(context,R.raw.outgoing_message); + messageAdapter.addMessage(textMessage); + scrollToBottom(); + } + } + + @Override + public void onError(CometChatException e) { + Log.e(TAG, "onError: "+e.getMessage()); + } + }); + }catch (Exception e) { + Log.e(TAG, "replyMessage: "+e.getMessage()); + } + } + + private void scrollToBottom() { + if (messageAdapter != null && messageAdapter.getItemCount() > 0) { + rvChatListView.scrollToPosition(messageAdapter.getItemCount() - 1); + final int scrollViewHeight = nestedScrollView.getHeight(); + if (scrollViewHeight > 0) { + final View lastView = nestedScrollView.getChildAt(nestedScrollView.getChildCount() - 1); + final int lastViewBottom = lastView.getBottom() + nestedScrollView.getPaddingBottom(); + final int deltaScrollY = lastViewBottom - scrollViewHeight - nestedScrollView.getScrollY(); + /* If you want to see the scroll animation, call this. */ + nestedScrollView.smoothScrollBy(0, deltaScrollY); + } + } + } + + /** + * This method is used to mark users & group message as read. + * + * @param baseMessage is object of BaseMessage.class. It is message which is been marked as read. + */ + private void markMessageAsRead(BaseMessage baseMessage) { + if (type.equals(CometChatConstants.RECEIVER_TYPE_USER)) + CometChat.markAsRead(baseMessage.getId(), baseMessage.getSender().getUid(), baseMessage.getReceiverType()); + else + CometChat.markAsRead(baseMessage.getId(), baseMessage.getReceiverUid(), baseMessage.getReceiverType()); + } + + + /** + * This method is used to add message listener to recieve real time messages between users & + * groups. It also give real time events for typing indicators, edit message, delete message, + * message being read & delivered. + * + * @see CometChat#addMessageListener(String, CometChat.MessageListener) + */ + private void addMessageListener() { + + CometChat.addMessageListener(TAG, new CometChat.MessageListener() { + @Override + public void onTextMessageReceived(TextMessage message) { + Log.d(TAG, "onTextMessageReceived: " + message.toString()); + onMessageReceived(message); + } + + @Override + public void onMediaMessageReceived(MediaMessage message) { + Log.d(TAG, "onMediaMessageReceived: " + message.toString()); + onMessageReceived(message); + } + + @Override + public void onTypingStarted(TypingIndicator typingIndicator) { + Log.e(TAG, "onTypingStarted: " + typingIndicator); + setTypingIndicator(typingIndicator,true); + } + + @Override + public void onTypingEnded(TypingIndicator typingIndicator) { + Log.d(TAG, "onTypingEnded: " + typingIndicator.toString()); + setTypingIndicator(typingIndicator,false); + } + + @Override + public void onMessagesDelivered(MessageReceipt messageReceipt) { + Log.d(TAG, "onMessagesDelivered: " + messageReceipt.toString()); + setMessageReciept(messageReceipt); + + } + + @Override + public void onMessagesRead(MessageReceipt messageReceipt) { + Log.e(TAG, "onMessagesRead: " + messageReceipt.toString()); + setMessageReciept(messageReceipt); + } + + @Override + public void onMessageEdited(BaseMessage message) { + Log.d(TAG, "onMessageEdited: " + message.toString()); + updateMessage(message); + } + + @Override + public void onMessageDeleted(BaseMessage message) { + Log.d(TAG, "onMessageDeleted: "); + updateMessage(message); + } + }); + } + + private void setMessageReciept(MessageReceipt messageReceipt) { + if (messageAdapter != null) { + if (messageReceipt.getReceivertype().equals(CometChatConstants.RECEIVER_TYPE_USER)) { + if (Id!=null && messageReceipt.getSender().getUid().equals(Id)) { + if (messageReceipt.getReceiptType().equals(MessageReceipt.RECEIPT_TYPE_DELIVERED)) + messageAdapter.setDeliveryReceipts(messageReceipt); + else + messageAdapter.setReadReceipts(messageReceipt); + } + } + } + } + + private void setTypingIndicator(TypingIndicator typingIndicator,boolean isShow) { + if (typingIndicator.getReceiverType().equalsIgnoreCase(CometChatConstants.RECEIVER_TYPE_USER)) { + Log.e(TAG, "onTypingStarted: " + typingIndicator); + if (Id != null && Id.equalsIgnoreCase(typingIndicator.getSender().getUid())) { + if (typingIndicator.getMetadata() == null) + typingIndicator(typingIndicator, isShow); + } + } else { + if (Id != null && Id.equalsIgnoreCase(typingIndicator.getReceiverId())) + typingIndicator(typingIndicator, isShow); + } + } + + private void onMessageReceived(BaseMessage message) { + MediaUtils.playSendSound(context,R.raw.incoming_message); + if (message.getReceiverType().equals(CometChatConstants.RECEIVER_TYPE_USER)) { + if (Id != null && Id.equalsIgnoreCase(message.getSender().getUid())) { + if (message.getParentMessageId()==parentId) + setMessage(message); + } else if(Id != null && Id.equalsIgnoreCase(message.getReceiverUid()) && message.getSender().getUid().equalsIgnoreCase(loggedInUser.getUid())) { + if (message.getParentMessageId()==parentId) + setMessage(message); + } + } else { + if (Id != null && Id.equalsIgnoreCase(message.getReceiverUid())) { + if (message.getParentMessageId()==parentId) + setMessage(message); + } + } + } + + /** + * This method is used to update edited message by calling setEditMessage() of adapter + * + * @param message is an object of BaseMessage and it will replace with old message. + * @see BaseMessage + */ + private void updateMessage(BaseMessage message) { + messageAdapter.setUpdatedMessage(message); + } + + + /** + * This method is used to mark message as read before adding them to list. This method helps to + * add real time message in list. + * + * @param message is an object of BaseMessage, It is recieved from message listener. + * @see BaseMessage + */ + private void setMessage(BaseMessage message) { + setReply(); + if (messageAdapter != null) { + messageAdapter.addMessage(message); + checkSmartReply(message); + markMessageAsRead(message); + if ((messageAdapter.getItemCount() - 1) - ((LinearLayoutManager) rvChatListView.getLayoutManager()).findLastVisibleItemPosition() < 5) + scrollToBottom(); + } else { + messageList.add(message); + initMessageAdapter(messageList); + } + } + + private void setReply() { + replyCount = replyCount+1; + if (replyCount==1) + tvReplyCount.setText(replyCount+" Reply"); + else + tvReplyCount.setText(replyCount+" Replies"); + } + + private void checkSmartReply(BaseMessage lastMessage) { + if (lastMessage != null && !lastMessage.getSender().getUid().equals(loggedInUser.getUid())) { + if (lastMessage.getMetadata() != null) { + getSmartReplyList(lastMessage); + } + } + } + + /** + * This method is used to display typing status to user. + * + * @param show is boolean, If it is true then is Typing will be shown to user + * If it is false then it will show user status i.e online or offline. + */ + private void typingIndicator(TypingIndicator typingIndicator, boolean show) { + if (messageAdapter != null) { + if (show) { + if (typingIndicator.getReceiverType().equals(CometChatConstants.RECEIVER_TYPE_USER)) + tvTypingIndicator.setText("is Typing..."); + else + tvTypingIndicator.setText(typingIndicator.getSender().getName() + " is Typing..."); + } else { + tvTypingIndicator.setVisibility(GONE); + } + + } + } + + /** + * This method is used to remove message listener + * + * @see CometChat#removeMessageListener(String) + */ + private void removeMessageListener() { + CometChat.removeMessageListener(TAG); + } + + /** + * This method is used to remove user presence listener + * + * @see CometChat#removeUserListener(String) + */ + private void removeUserListener() { + CometChat.removeUserListener(TAG); + } + + + @Override + public void onPause() { + Log.d(TAG, "onPause: "); + super.onPause(); + if (messageAdapter!=null) + messageAdapter.stopPlayingAudio(); + removeMessageListener(); + sendTypingIndicator(true); + } + + @Override + public void onResume() { + super.onResume(); + Log.d(TAG, "onResume: "); + messageAdapter = null; + messagesRequest = null; + checkOnGoingCall(); + fetchMessage(); + isNoMoreMessages = false; + addMessageListener(); + + if (type != null) { + if (type.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + new Thread(this::getUser).start(); + } else { + new Thread(this::getGroup).start(); + } + } + } + + + + @Override + public void onAttach(Context context) { + super.onAttach(context); + this.context = context; + } + + @Override + public void onDetach() { + super.onDetach(); + } + + @Override + public void onClick(View view) { + + int id = view.getId(); + if (id == R.id.iv_close_message_action) { + if (messageAdapter != null) { + messageAdapter.clearLongClickSelectedItem(); + messageAdapter.notifyDataSetChanged(); + } + } + else if (id == R.id.ic_more_option) { + MessageActionFragment messageActionFragment = new MessageActionFragment(); + Bundle bundle = new Bundle(); + if (messageType.equals(CometChatConstants.MESSAGE_TYPE_TEXT)) + bundle.putBoolean("copyVisible",true); + else + bundle.putBoolean("copyVisible",false); + + bundle.putBoolean("forwardVisible",true); + if (name.equals(loggedInUser.getName()) && messageType.equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + bundle.putBoolean("editVisible",true); + } else { + bundle.putBoolean("editVisible",false); + } + bundle.putString("type", CometChatThreadMessageActivity.class.getName()); + messageActionFragment.setArguments(bundle); + showBottomSheet(messageActionFragment); + } + else if (id == R.id.ic_forward_option) { + isParent = true; + startForwardThreadActivity(); + } + else if (id == R.id.iv_message_close) { + if (messageAdapter != null) { + messageAdapter.clearLongClickSelectedItem(); + messageAdapter.notifyDataSetChanged(); + } + isEdit = false; + baseMessage = null; + editMessageLayout.setVisibility(GONE); + } + else if (id == R.id.iv_reply_close) { + if (messageAdapter!=null) { + messageAdapter.clearLongClickSelectedItem(); + messageAdapter.notifyDataSetChanged(); + } + isReply = false; + baseMessage = null; + replyMessageLayout.setVisibility(GONE); + } + + else if (id == R.id.btn_unblock_user) { + unblockUser(); + } + else if (id == R.id.chatList_toolbar) { + if (type.equals(CometChatConstants.RECEIVER_TYPE_USER)) { + Intent intent = new Intent(getContext(), CometChatUserDetailScreenActivity.class); + intent.putExtra(StringContract.IntentStrings.UID, Id); + intent.putExtra(StringContract.IntentStrings.NAME, conversationName); + intent.putExtra(StringContract.IntentStrings.AVATAR, avatarUrl); + intent.putExtra(StringContract.IntentStrings.IS_BLOCKED_BY_ME, isBlockedByMe); + intent.putExtra(StringContract.IntentStrings.TYPE, type); + startActivity(intent); + } else { + Intent intent = new Intent(getContext(), CometChatGroupDetailScreenActivity.class); + intent.putExtra(StringContract.IntentStrings.GUID, Id); + intent.putExtra(StringContract.IntentStrings.NAME, conversationName); + intent.putExtra(StringContract.IntentStrings.AVATAR, avatarUrl); + intent.putExtra(StringContract.IntentStrings.TYPE, type); + intent.putExtra(StringContract.IntentStrings.MEMBER_SCOPE, loggedInUserScope); + intent.putExtra(StringContract.IntentStrings.GROUP_OWNER, groupOwnerId); + startActivity(intent); + } + } + } + + @Override + public void setLongMessageClick(List baseMessagesList) { + Log.e(TAG, "setLongMessageClick: " + baseMessagesList); + isReply = false; + isEdit = false; + isParent = false; + MessageActionFragment messageActionFragment = new MessageActionFragment(); + replyMessageLayout.setVisibility(GONE); + editMessageLayout.setVisibility(GONE); + boolean copyVisible = true; + boolean threadVisible = true; + boolean replyVisible = false; + boolean editVisible = true; + boolean deleteVisible = true; + boolean forwardVisible = true; + List textMessageList = new ArrayList<>(); + List mediaMessageList = new ArrayList<>(); + for (BaseMessage baseMessage : baseMessagesList) { + if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + textMessageList.add(baseMessage); + } else { + mediaMessageList.add(baseMessage); + } + } + if (textMessageList.size() == 1) { + BaseMessage basemessage = textMessageList.get(0); + if (basemessage != null && basemessage.getSender() != null) { + if (!(basemessage instanceof Action) && basemessage.getDeletedAt() == 0) { + baseMessage = basemessage; + threadVisible = false; + if (basemessage.getSender().getUid().equals(CometChat.getLoggedInUser().getUid())) { + deleteVisible = true; + editVisible = true; + forwardVisible = true; + } else { + editVisible = false; + forwardVisible = true; + if (loggedInUserScope!=null && (loggedInUserScope.equals(CometChatConstants.SCOPE_ADMIN) || loggedInUserScope.equals(CometChatConstants.SCOPE_MODERATOR))) { + deleteVisible = true; + } else { + deleteVisible = false; + } + } + } + } + } + + if (mediaMessageList.size() == 1) { + BaseMessage basemessage = mediaMessageList.get(0); + if (basemessage != null && basemessage.getSender() != null) { + if (!(basemessage instanceof Action) && basemessage.getDeletedAt() == 0) { + baseMessage = basemessage; + copyVisible = false; + threadVisible = false; + if (basemessage.getSender().getUid().equals(CometChat.getLoggedInUser().getUid())) { + deleteVisible = true; + editVisible = false; + forwardVisible = true; + } else { + if (loggedInUserScope!=null && (loggedInUserScope.equals(CometChatConstants.SCOPE_ADMIN) || loggedInUserScope.equals(CometChatConstants.SCOPE_MODERATOR))){ + deleteVisible = true; + } else { + deleteVisible = false; + } + forwardVisible = true; + editVisible = false; + } + } + } + } + baseMessages = baseMessagesList; + Bundle bundle = new Bundle(); + bundle.putBoolean("copyVisible",copyVisible); + bundle.putBoolean("threadVisible",threadVisible); + bundle.putBoolean("editVisible",editVisible); + bundle.putBoolean("deleteVisible",deleteVisible); + bundle.putBoolean("replyVisible",replyVisible); + bundle.putBoolean("forwardVisible",forwardVisible); + bundle.putString("type", CometChatThreadMessageActivity.class.getName()); + messageActionFragment.setArguments(bundle); + showBottomSheet(messageActionFragment); + } + + private void showBottomSheet(MessageActionFragment messageActionFragment) { + messageActionFragment.show(getFragmentManager(),messageActionFragment.getTag()); + messageActionFragment.setMessageActionListener(new MessageActionFragment.MessageActionListener() { + @Override + public void onThreadMessageClick() { + + } + + @Override + public void onEditMessageClick() { + if (isParent) + editParentMessage(); + else + editThreadMessage(); + } + + @Override + public void onReplyMessageClick() { + replyMessage(); + } + + @Override + public void onForwardMessageClick() { + if (isParent) + startForwardThreadActivity(); + else + startForwardMessageActivity(); + } + + @Override + public void onDeleteMessageClick() { + deleteMessage(baseMessage); + if (messageAdapter != null) { + messageAdapter.clearLongClickSelectedItem(); + messageAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onCopyMessageClick() { + String copyMessage = ""; + if (isParent) { + copyMessage = message; + } + for (BaseMessage bMessage : baseMessages) { + if (bMessage.getDeletedAt() == 0 && bMessage instanceof TextMessage) { + copyMessage = copyMessage + "[" + Utils.getLastMessageDate(bMessage.getSentAt()) + "] " + bMessage.getSender().getName() + ": " + ((TextMessage) bMessage).getText(); + } + } + Log.e(TAG, "onCopy: " + message); + ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE); + ClipData clipData = ClipData.newPlainText("ThreadMessageAdapter", copyMessage); + clipboardManager.setPrimaryClip(clipData); + Toast.makeText(context, getResources().getString(R.string.text_copied_clipboard), Toast.LENGTH_LONG).show(); + isParent = true; + if (messageAdapter != null) { + messageAdapter.clearLongClickSelectedItem(); + messageAdapter.notifyDataSetChanged(); + } + } + + @Override + public void onShareMessageClick() { + + } + }); + } + + private void editParentMessage() { + if (message!=null&&messageType.equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + isEdit = true; + isReply = false; + tvMessageTitle.setText(getResources().getString(R.string.edit_message)); + tvMessageSubTitle.setText(message); + composeBox.ivMic.setVisibility(GONE); + composeBox.ivSend.setVisibility(View.VISIBLE); + editMessageLayout.setVisibility(View.VISIBLE); + composeBox.etComposeBox.setText(message); + } + } + + private void editThreadMessage() { + if (baseMessage!=null&&baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + isEdit = true; + isReply = false; + tvMessageTitle.setText(getResources().getString(R.string.edit_message)); + tvMessageSubTitle.setText(((TextMessage) baseMessage).getText()); + composeBox.ivMic.setVisibility(GONE); + composeBox.ivSend.setVisibility(View.VISIBLE); + editMessageLayout.setVisibility(View.VISIBLE); + composeBox.etComposeBox.setText(((TextMessage) baseMessage).getText()); + if (messageAdapter != null) { + messageAdapter.setSelectedMessage(baseMessage.getId()); + messageAdapter.notifyDataSetChanged(); + } + } + } + + private void startForwardThreadActivity() { + Intent intent = new Intent(getContext(), CometChatForwardMessageScreenActivity.class); + intent.putExtra(StringContract.IntentStrings.TYPE,messageType); + if (messageType.equals(CometChatConstants.MESSAGE_TYPE_TEXT)){ + intent.putExtra(CometChatConstants.MESSAGE_TYPE_TEXT, message); + intent.putExtra(StringContract.IntentStrings.TYPE, CometChatConstants.MESSAGE_TYPE_TEXT); + } else if(messageType.equals(CometChatConstants.MESSAGE_TYPE_IMAGE) || + messageType.equals(CometChatConstants.MESSAGE_TYPE_AUDIO) || + messageType.equals(CometChatConstants.MESSAGE_TYPE_VIDEO) || + messageType.equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME, message); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL, message); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_MIME_TYPE, messageMimeType); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION, messageExtension); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE, messageSize); + } + startActivity(intent); + } + + private void startForwardMessageActivity() { + Intent intent = new Intent(getContext(), CometChatForwardMessageScreenActivity.class); + if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)){ + intent.putExtra(CometChatConstants.MESSAGE_TYPE_TEXT, ((TextMessage) baseMessage).getText()); + intent.putExtra(StringContract.IntentStrings.TYPE, CometChatConstants.MESSAGE_TYPE_TEXT); + } else if(baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_IMAGE) || + baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_AUDIO) || + baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_VIDEO) || + baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_NAME, ((MediaMessage)baseMessage).getAttachment().getFileName()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_URL, ((MediaMessage)baseMessage).getAttachment().getFileUrl()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_MIME_TYPE, ((MediaMessage)baseMessage).getAttachment().getFileMimeType()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_EXTENSION, ((MediaMessage)baseMessage).getAttachment().getFileExtension()); + intent.putExtra(StringContract.IntentStrings.MESSAGE_TYPE_IMAGE_SIZE, ((MediaMessage)baseMessage).getAttachment().getFileSize()); + intent.putExtra(StringContract.IntentStrings.TYPE,baseMessage.getType()); + } + startActivity(intent); + } + + + private void replyMessage() { + if (baseMessage != null) { + isReply = true; + replyTitle.setText(baseMessage.getSender().getName()); + replyMedia.setVisibility(View.VISIBLE); + if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_TEXT)) { + replyMessage.setText(((TextMessage) baseMessage).getText()); + replyMedia.setVisibility(GONE); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_IMAGE)) { + replyMessage.setText(getResources().getString(R.string.shared_a_image)); + Glide.with(context).load(((MediaMessage) baseMessage).getAttachment().getFileUrl()).into(replyMedia); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_AUDIO)) { + String messageStr = String.format(getResources().getString(R.string.shared_a_audio), + Utils.getFileSize(((MediaMessage) baseMessage).getAttachment().getFileSize())); + replyMessage.setText(messageStr); + replyMessage.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_library_music_24dp, 0, 0, 0); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_VIDEO)) { + replyMessage.setText(getResources().getString(R.string.shared_a_video)); + Glide.with(context).load(((MediaMessage) baseMessage).getAttachment().getFileUrl()).into(replyMedia); + } else if (baseMessage.getType().equals(CometChatConstants.MESSAGE_TYPE_FILE)) { + String messageStr = String.format(getResources().getString(R.string.shared_a_file), + Utils.getFileSize(((MediaMessage) baseMessage).getAttachment().getFileSize())); + replyMessage.setText(messageStr); + replyMessage.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_insert_drive_file_black_24dp, 0, 0, 0); + } + composeBox.ivMic.setVisibility(GONE); + composeBox.ivSend.setVisibility(View.VISIBLE); + replyMessageLayout.setVisibility(View.VISIBLE); + if (messageAdapter != null) { + messageAdapter.setSelectedMessage(baseMessage.getId()); + messageAdapter.notifyDataSetChanged(); + } + } + } + + @Override + public void handleDialogClose(DialogInterface dialog) { + if (messageAdapter!=null) + messageAdapter.clearLongClickSelectedItem(); + } +} diff --git a/uikit/src/main/java/screen/unified/CometChatUnified.java b/uikit/src/main/java/screen/unified/CometChatUnified.java index 2083ad3c..c83b519c 100644 --- a/uikit/src/main/java/screen/unified/CometChatUnified.java +++ b/uikit/src/main/java/screen/unified/CometChatUnified.java @@ -86,6 +86,8 @@ public class CometChatUnified extends AppCompatActivity implements private Group group; + private Fragment active = new CometChatConversationListScreen(); + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -156,9 +158,11 @@ public void OnItemClick(User user, int position) { */ private void initViewComponent() { - if (!Utils.hasPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO,Manifest.permission.WRITE_EXTERNAL_STORAGE})) { + if (!Utils.hasPermissions(this, new String[]{Manifest.permission.RECORD_AUDIO, + Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE})) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO,Manifest.permission.WRITE_EXTERNAL_STORAGE}, + requestPermissions(new String[]{Manifest.permission.RECORD_AUDIO, + Manifest.permission.CAMERA,Manifest.permission.WRITE_EXTERNAL_STORAGE}, StringContract.RequestCode.RECORD); } } @@ -169,8 +173,6 @@ private void initViewComponent() { badgeDrawable.setVisible(false); loadFragment(new CometChatConversationListScreen()); - - } /** @@ -228,6 +230,7 @@ public void getUnreadConversationCount() { @Override public void onSuccess(HashMap> stringHashMapHashMap) { Log.e(TAG, "onSuccess: " + stringHashMapHashMap); + unreadCount.clear(); unreadCount.addAll(stringHashMapHashMap.get("user").keySet()); //Add users whose messages are unread. unreadCount.addAll(stringHashMapHashMap.get("group").keySet()); //Add groups whose messages are unread. @@ -355,6 +358,7 @@ private void startGroupIntent(Group group) { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { int itemId = item.getItemId(); + Fragment fragment = null; if (itemId == R.id.menu_users) { fragment = new CometChatUserListScreen(); } else if (itemId == R.id.menu_group) { diff --git a/uikit/src/main/java/utils/Extensions.java b/uikit/src/main/java/utils/Extensions.java new file mode 100644 index 00000000..26f3e984 --- /dev/null +++ b/uikit/src/main/java/utils/Extensions.java @@ -0,0 +1,156 @@ +package utils; + +import android.content.Context; +import android.util.Log; +import android.widget.Toast; + +import com.cometchat.pro.models.BaseMessage; +import com.cometchat.pro.models.TextMessage; + +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +public class Extensions { + + private static final String TAG = "Extensions"; + public static boolean getImageModeration(Context context, BaseMessage baseMessage) { + boolean result = false; + try { + HashMap extensionList = extensionCheck(baseMessage); + if (extensionList != null && extensionList.containsKey("imageModeration")) { + JSONObject imageModeration = extensionList.get("imageModeration"); + String confidence = imageModeration.getString("confidence"); + if (Integer.parseInt(confidence) > 50) { + result = true; + } else { + result = false; + } + } + }catch (Exception e) { + Toast.makeText(context,"Error:"+e.getMessage(),Toast.LENGTH_LONG).show(); + } + return result; + } + + public static String getThumbnailGeneration(Context context, BaseMessage baseMessage) { + String resultUrl = null; + try { + HashMap extensionList = extensionCheck(baseMessage); + if (extensionList != null && extensionList.containsKey("thumbnailGeneration")) { + JSONObject thumbnailGeneration = extensionList.get("thumbnailGeneration"); + resultUrl = thumbnailGeneration.getString("url_small"); + } + }catch (Exception e) { + Toast.makeText(context,"Error:"+e.getMessage(),Toast.LENGTH_LONG).show(); + } + return resultUrl; + } + + + public static List getSmartReplyList(BaseMessage baseMessage){ + + HashMap extensionList = extensionCheck(baseMessage); + if (extensionList != null && extensionList.containsKey("smartReply")) { + JSONObject replyObject = extensionList.get("smartReply"); + List replyList = new ArrayList<>(); + try { + replyList.add(replyObject.getString("reply_positive")); + replyList.add(replyObject.getString("reply_neutral")); + replyList.add(replyObject.getString("reply_negative")); + } catch (Exception e) { + Log.e(TAG, "onSuccess: " + e.getMessage()); + } + return replyList; + } + return null; + } + + + public static HashMap extensionCheck(BaseMessage baseMessage) + { + JSONObject metadata = baseMessage.getMetadata(); + HashMap extensionMap = new HashMap<>(); + try { + if (metadata != null) { + JSONObject injectedObject = metadata.getJSONObject("@injected"); + if (injectedObject != null && injectedObject.has("extensions")) { + JSONObject extensionsObject = injectedObject.getJSONObject("extensions"); + if (extensionsObject != null && extensionsObject.has("link-preview")) { + JSONObject linkPreviewObject = extensionsObject.getJSONObject("link-preview"); + JSONArray linkPreview = linkPreviewObject.getJSONArray("links"); + if (linkPreview.length() > 0) { + extensionMap.put("linkPreview",linkPreview.getJSONObject(0)); + } + + } + if (extensionsObject !=null && extensionsObject.has("smart-reply")) { + extensionMap.put("smartReply",extensionsObject.getJSONObject("smart-reply")); + } + if (extensionsObject!=null && extensionsObject.has("message-translation")) { + extensionMap.put("messageTranslation",extensionsObject.getJSONObject("message-translation")); + } + if (extensionsObject!=null && extensionsObject.has("profanity-filter")) { + extensionMap.put("profanityFilter",extensionsObject.getJSONObject("profanity-filter")); + } + if (extensionsObject!=null && extensionsObject.has("image-moderation")) { + extensionMap.put("imageModeration",extensionsObject.getJSONObject("image-moderation")); + } + if (extensionsObject!=null && extensionsObject.has("sentiment-analysis")) { + extensionMap.put("sentimentAnalysis",extensionsObject.getJSONObject("sentiment-analysis")); + } + } + return extensionMap; + } + else + return null; + } catch (Exception e) { + Log.e(TAG, "isLinkPreview: "+e.getMessage() ); + } + return null; + } + + public static boolean checkSentiment(BaseMessage baseMessage) { + boolean result = false; + HashMap extensionList = extensionCheck(baseMessage); + try { + if (extensionList.containsKey("sentimentAnalysis")) { + JSONObject sentimentAnalysis = extensionList.get("sentimentAnalysis"); + String str = sentimentAnalysis.getString("sentiment"); + if (str.equals("negative")) + result = true; + else + result = false; + } + }catch (Exception e) { + Log.e(TAG, "checkSentiment: "+e.getMessage()); + } + return result; + } + + public static String checkProfanityMessage(BaseMessage baseMessage) { + String result = ((TextMessage)baseMessage).getText(); + HashMap extensionList = Extensions.extensionCheck(baseMessage); + if (extensionList!=null) { + try { + if (extensionList.containsKey("profanityFilter")) { + JSONObject profanityFilter = extensionList.get("profanityFilter"); + String profanity = profanityFilter.getString("profanity"); + String cleanMessage = profanityFilter.getString("message_clean"); + if (profanity.equals("no")) + result = ((TextMessage)baseMessage).getText(); + else + result = cleanMessage; + } else { + result = ((TextMessage)baseMessage).getText().trim(); + } + }catch (Exception e) { + Log.e(TAG, "checkProfanityMessage:Error: "+e.getMessage() ); + } + } + return result; + } +} diff --git a/uikit/src/main/java/utils/Utils.java b/uikit/src/main/java/utils/Utils.java index 24cd6eb1..5eec9358 100644 --- a/uikit/src/main/java/utils/Utils.java +++ b/uikit/src/main/java/utils/Utils.java @@ -33,6 +33,10 @@ import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.databinding.BindingAdapter; +import androidx.renderscript.Allocation; +import androidx.renderscript.Element; +import androidx.renderscript.RenderScript; +import androidx.renderscript.ScriptIntrinsicBlur; import com.cometchat.pro.constants.CometChatConstants; import com.cometchat.pro.core.Call; @@ -58,6 +62,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.text.SimpleDateFormat; @@ -68,6 +73,8 @@ import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import constant.StringContract; import kotlin.ranges.RangesKt; @@ -77,6 +84,22 @@ public class Utils { private static final String TAG = "Utils"; + public static String removeEmojiAndSymbol(String content) { + String utf8tweet = ""; + try { + byte[] utf8Bytes = content.getBytes("UTF-8"); + utf8tweet = new String(utf8Bytes, "UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + Pattern unicodeOutliers = Pattern.compile( + "[\ud83c\udc00-\ud83c\udfff]|[\ud83d\udc00-\ud83d\udfff]|[\u2600-\u27ff]", + Pattern.UNICODE_CASE | + Pattern.CASE_INSENSITIVE); + Matcher unicodeOutlierMatcher = unicodeOutliers.matcher(utf8tweet); + utf8tweet = unicodeOutlierMatcher.replaceAll(" "); + return utf8tweet; + } public static boolean isDarkMode(Context context) { int nightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK; @@ -198,7 +221,8 @@ public static String getLastMessage(BaseMessage lastMessage) { if (lastMessage instanceof TextMessage) { if (isLoggedInUser(lastMessage.getSender())) - message = "You: " + ((TextMessage) lastMessage).getText(); + message = "You: " + (((TextMessage) lastMessage).getText()==null + ?"This message was deleted":((TextMessage) lastMessage).getText()); else message = lastMessage.getSender().getName() + ": " + ((TextMessage) lastMessage).getText(); @@ -262,15 +286,9 @@ public static GroupMember UserToGroupMember(User user, boolean isScopeUpdate, St return groupMember; } - public static String getHeaderDate(TextView textView, long timestamp) { - Calendar messageTimestamp = Calendar.getInstance(); - messageTimestamp.setTimeInMillis(timestamp); - Calendar now = Calendar.getInstance(); -// if (now.get(5) == messageTimestamp.get(5)) { - return DateFormat.format("hh:mm a", messageTimestamp).toString(); -// } else { -// return now.get(5) - messageTimestamp.get(5) == 1 ? "Yesterday " + DateFormat.format("hh:mm a", messageTimestamp).toString() : DateFormat.format("d MMMM", messageTimestamp).toString() + " " + DateFormat.format("hh:mm a", messageTimestamp).toString(); -// } + public static String getMessageDate(long timestamp) { + String messageDate = new SimpleDateFormat("dd/MM/yyyy hh:mm a").format(new java.util.Date(timestamp * 1000)); + return messageDate; } public static String getHeaderDate(long timestamp) { @@ -598,67 +616,22 @@ public static void createDirectory(String var0) { } } - public static List checkSmartReply(BaseMessage lastMessage) { - if (lastMessage!=null && !lastMessage.getSender().getUid().equals(CometChat.getLoggedInUser().getUid())) { - if (lastMessage.getMetadata()!=null) { - return getSmartReplyList(lastMessage); - } - } - return null; - } - - private static List getSmartReplyList(BaseMessage baseMessage){ - - HashMap extensionList = Utils.extensionCheck(baseMessage); - if (extensionList != null && extensionList.containsKey("smartReply")) { - JSONObject replyObject = extensionList.get("smartReply"); - List replyList = new ArrayList<>(); - try { - replyList.add(replyObject.getString("reply_positive")); - replyList.add(replyObject.getString("reply_neutral")); - replyList.add(replyObject.getString("reply_negative")); - } catch (Exception e) { - Log.e(TAG, "onSuccess: " + e.getMessage()); - } - return replyList; - } - return null; - } - - public static HashMap extensionCheck(BaseMessage baseMessage) - { - JSONObject metadata = baseMessage.getMetadata(); - HashMap extensionMap = new HashMap<>(); - try { - if (metadata != null) { - JSONObject injectedObject = metadata.getJSONObject("@injected"); - if (injectedObject != null && injectedObject.has("extensions")) { - JSONObject extensionsObject = injectedObject.getJSONObject("extensions"); - if (extensionsObject != null && extensionsObject.has("link-preview")) { - JSONObject linkPreviewObject = extensionsObject.getJSONObject("link-preview"); - JSONArray linkPreview = linkPreviewObject.getJSONArray("links"); - if (linkPreview.length() > 0) { - extensionMap.put("linkPreview",linkPreview.getJSONObject(0)); - } - - } - if (extensionsObject !=null && extensionsObject.has("smart-reply")) { - extensionMap.put("smartReply",extensionsObject.getJSONObject("smart-reply")); - } - } - return extensionMap; - } - else - return null; - } catch (Exception e) { - Log.e(TAG, "isLinkPreview: "+e.getMessage() ); - } - return null; + public static Bitmap blur(Context context, Bitmap image) { + int width = Math.round(image.getWidth() * 0.6f); + int height = Math.round(image.getHeight() * 0.6f); + Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false); + Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap); + RenderScript rs = RenderScript.create(context); + ScriptIntrinsicBlur intrinsicBlur = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs)); + Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap); + Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap); + intrinsicBlur.setRadius(15f); + intrinsicBlur.setInput(tmpIn); + intrinsicBlur.forEach(tmpOut); + tmpOut.copyTo(outputBitmap); + return outputBitmap; } - - - public static void startCallIntent(Context context, User user, String type, boolean isOutgoing, @NonNull String sessionId) { Intent videoCallIntent = new Intent(context, CometChatCallActivity.class); diff --git a/uikit/src/main/java/viewmodel/ConversationViewModel.java b/uikit/src/main/java/viewmodel/ConversationViewModel.java index d18a4003..bf25dae9 100644 --- a/uikit/src/main/java/viewmodel/ConversationViewModel.java +++ b/uikit/src/main/java/viewmodel/ConversationViewModel.java @@ -39,7 +39,8 @@ public void add(Conversation conversation){ } private void setAdapter(CometChatConversationList cometChatConversationList){ - conversationListAdapter=new ConversationListAdapter(context); + if (conversationListAdapter==null) + conversationListAdapter=new ConversationListAdapter(context); cometChatConversationList.setAdapter(conversationListAdapter); } diff --git a/uikit/src/main/java/viewmodel/GroupListViewModel.java b/uikit/src/main/java/viewmodel/GroupListViewModel.java index dcfd23d9..4ed64cbc 100644 --- a/uikit/src/main/java/viewmodel/GroupListViewModel.java +++ b/uikit/src/main/java/viewmodel/GroupListViewModel.java @@ -66,9 +66,9 @@ public void remove(Group group){ } - public void update(Group group) { + public void update(Group group,int i) { if (groupListAdapter!=null) - groupListAdapter.updateGroup(group); + groupListAdapter.updateGroup(group,i); } public void add(Group group) { diff --git a/uikit/src/main/res/drawable/bottom_border.xml b/uikit/src/main/res/drawable/bottom_border.xml index 39ca93c4..f43a6e8d 100644 --- a/uikit/src/main/res/drawable/bottom_border.xml +++ b/uikit/src/main/res/drawable/bottom_border.xml @@ -3,8 +3,7 @@ - - + \ No newline at end of file diff --git a/uikit/src/main/res/drawable/ic_baseline_edit_24.xml b/uikit/src/main/res/drawable/ic_baseline_edit_24.xml new file mode 100644 index 00000000..635e27e5 --- /dev/null +++ b/uikit/src/main/res/drawable/ic_baseline_edit_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/uikit/src/main/res/drawable/ic_baseline_forward_24.xml b/uikit/src/main/res/drawable/ic_baseline_forward_24.xml new file mode 100644 index 00000000..3c23ad29 --- /dev/null +++ b/uikit/src/main/res/drawable/ic_baseline_forward_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/uikit/src/main/res/drawable/ic_baseline_more_vert_24.xml b/uikit/src/main/res/drawable/ic_baseline_more_vert_24.xml new file mode 100644 index 00000000..48272f66 --- /dev/null +++ b/uikit/src/main/res/drawable/ic_baseline_more_vert_24.xml @@ -0,0 +1,10 @@ + + + diff --git a/uikit/src/main/res/drawable/ic_hand.xml b/uikit/src/main/res/drawable/ic_hand.xml new file mode 100644 index 00000000..c3b2281c --- /dev/null +++ b/uikit/src/main/res/drawable/ic_hand.xml @@ -0,0 +1,5 @@ + + + diff --git a/uikit/src/main/res/drawable/ic_lock_24dp.xml b/uikit/src/main/res/drawable/ic_lock_24dp.xml new file mode 100644 index 00000000..65c69862 --- /dev/null +++ b/uikit/src/main/res/drawable/ic_lock_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/uikit/src/main/res/drawable/ic_nav_chat.xml b/uikit/src/main/res/drawable/ic_nav_chat.xml index ca69f009..ce7ea35d 100644 --- a/uikit/src/main/res/drawable/ic_nav_chat.xml +++ b/uikit/src/main/res/drawable/ic_nav_chat.xml @@ -1,5 +1,5 @@ - + diff --git a/uikit/src/main/res/drawable/ic_reply_24dp.xml b/uikit/src/main/res/drawable/ic_reply_24dp.xml new file mode 100644 index 00000000..f49d97d8 --- /dev/null +++ b/uikit/src/main/res/drawable/ic_reply_24dp.xml @@ -0,0 +1,10 @@ + + + diff --git a/uikit/src/main/res/drawable/ic_share_24dp.xml b/uikit/src/main/res/drawable/ic_share_24dp.xml new file mode 100644 index 00000000..071a23ea --- /dev/null +++ b/uikit/src/main/res/drawable/ic_share_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/uikit/src/main/res/drawable/left_border_lmessage.xml b/uikit/src/main/res/drawable/left_border_lmessage.xml new file mode 100644 index 00000000..8a5ec9ac --- /dev/null +++ b/uikit/src/main/res/drawable/left_border_lmessage.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/drawable/left_border_rmessage.xml b/uikit/src/main/res/drawable/left_border_rmessage.xml new file mode 100644 index 00000000..47a5e4bc --- /dev/null +++ b/uikit/src/main/res/drawable/left_border_rmessage.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/drawable/rounded_border.xml b/uikit/src/main/res/drawable/rounded_border.xml new file mode 100644 index 00000000..fa6e9c67 --- /dev/null +++ b/uikit/src/main/res/drawable/rounded_border.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/drawable/rounded_dialog.xml b/uikit/src/main/res/drawable/rounded_dialog.xml new file mode 100644 index 00000000..fb23872b --- /dev/null +++ b/uikit/src/main/res/drawable/rounded_dialog.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/layout/activity_comet_chat_group_detail_screen.xml b/uikit/src/main/res/layout/activity_comet_chat_group_detail_screen.xml index 207c14ac..22a28f08 100644 --- a/uikit/src/main/res/layout/activity_comet_chat_group_detail_screen.xml +++ b/uikit/src/main/res/layout/activity_comet_chat_group_detail_screen.xml @@ -58,12 +58,10 @@ tools:text="@tools:sample/full_names" /> + tools:text="@tools:sample/lorem/random" /> @@ -220,7 +219,7 @@ android:id="@+id/rl_add_member" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_below="@id/tvMember" + android:layout_below="@id/tv_members" android:clickable="true" android:foreground="?attr/selectableItemBackground" android:paddingTop="8dp" diff --git a/uikit/src/main/res/layout/activity_comet_chat_thread_message.xml b/uikit/src/main/res/layout/activity_comet_chat_thread_message.xml new file mode 100644 index 00000000..c32b9dc2 --- /dev/null +++ b/uikit/src/main/res/layout/activity_comet_chat_thread_message.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/layout/alert_reply_layout.xml b/uikit/src/main/res/layout/alert_reply_layout.xml new file mode 100644 index 00000000..c3dcd9a9 --- /dev/null +++ b/uikit/src/main/res/layout/alert_reply_layout.xml @@ -0,0 +1,31 @@ + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/layout/block_user_message_layout.xml b/uikit/src/main/res/layout/block_user_message_layout.xml new file mode 100644 index 00000000..d4db19d1 --- /dev/null +++ b/uikit/src/main/res/layout/block_user_message_layout.xml @@ -0,0 +1,37 @@ + + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/layout/chat_screen_toolbar.xml b/uikit/src/main/res/layout/chat_screen_toolbar.xml index 2ff6e4ec..9028238b 100644 --- a/uikit/src/main/res/layout/chat_screen_toolbar.xml +++ b/uikit/src/main/res/layout/chat_screen_toolbar.xml @@ -23,12 +23,12 @@ android:id="@+id/iv_copy_message_action" android:layout_centerVertical="true" android:layout_alignParentRight="true" - android:layout_marginEnd="16dp" - android:layout_marginTop="8dp" - android:layout_marginBottom="8dp" - android:layout_marginStart="16dp" + android:paddingEnd="16dp" + android:paddingTop="8dp" + android:paddingBottom="8dp" + android:paddingStart="16dp" android:src="@drawable/ic_content_copy_black_24dp" - android:layout_width="40dp" + android:layout_width="wrap_content" android:layout_height="wrap_content"/> + + + + + + + + + + + - + + + + + + + + + - + + + + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/layout/fragment_chat_screen.xml b/uikit/src/main/res/layout/fragment_chat_screen.xml index feb5ed00..c24c26c9 100644 --- a/uikit/src/main/res/layout/fragment_chat_screen.xml +++ b/uikit/src/main/res/layout/fragment_chat_screen.xml @@ -14,77 +14,23 @@ android:layout_height="match_parent" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" android:layout_above="@+id/bottom_layout"/> + + - - - - - - - - - - - + + + + + - - - - - - - - - - - - + \ No newline at end of file diff --git a/uikit/src/main/res/layout/fragment_message_actions.xml b/uikit/src/main/res/layout/fragment_message_actions.xml new file mode 100644 index 00000000..ff0ea808 --- /dev/null +++ b/uikit/src/main/res/layout/fragment_message_actions.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + diff --git a/uikit/src/main/res/layout/fragment_thread_message.xml b/uikit/src/main/res/layout/fragment_thread_message.xml new file mode 100644 index 00000000..9e7467f0 --- /dev/null +++ b/uikit/src/main/res/layout/fragment_thread_message.xml @@ -0,0 +1,234 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/layout/group_list_row.xml b/uikit/src/main/res/layout/group_list_row.xml index b69cd627..e711899c 100644 --- a/uikit/src/main/res/layout/group_list_row.xml +++ b/uikit/src/main/res/layout/group_list_row.xml @@ -39,6 +39,9 @@ diff --git a/uikit/src/main/res/layout/join_ongoing_call_layout.xml b/uikit/src/main/res/layout/join_ongoing_call_layout.xml new file mode 100644 index 00000000..8566b453 --- /dev/null +++ b/uikit/src/main/res/layout/join_ongoing_call_layout.xml @@ -0,0 +1,27 @@ + + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/layout/left_message_item.xml b/uikit/src/main/res/layout/left_message_item.xml index 36ea8985..c0ffbab2 100644 --- a/uikit/src/main/res/layout/left_message_item.xml +++ b/uikit/src/main/res/layout/left_message_item.xml @@ -38,8 +38,45 @@ android:background="@drawable/cc_message_bubble_left" android:layout_marginStart="10dp" android:layout_marginBottom="1dp"> - + + + + + - + + + + + + + + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/layout/message_left_link_item.xml b/uikit/src/main/res/layout/message_left_link_item.xml index d3eb7521..bfdf9505 100644 --- a/uikit/src/main/res/layout/message_left_link_item.xml +++ b/uikit/src/main/res/layout/message_left_link_item.xml @@ -16,7 +16,7 @@ android:layout_width="24dp" android:id="@+id/iv_user" tools:src="@tools:sample/avatars" - android:layout_alignBottom="@id/cv_image_message_container" + android:layout_alignTop="@id/cv_link_message_container" android:layout_marginBottom="4dp" android:layout_marginStart="4dp" android:layout_height="24dp"/> @@ -33,7 +33,7 @@ + + + + @@ -51,10 +51,36 @@ android:layout_height="200dp" android:adjustViewBounds="true" android:background="@color/textColorWhite" - android:scaleType="fitCenter" + android:scaleType="centerCrop" android:src="@drawable/ic_defaulf_image" /> + + + + + + + + + diff --git a/uikit/src/main/res/layout/message_left_list_video_item.xml b/uikit/src/main/res/layout/message_left_list_video_item.xml index 7aa60e84..35d3b2a4 100644 --- a/uikit/src/main/res/layout/message_left_list_video_item.xml +++ b/uikit/src/main/res/layout/message_left_list_video_item.xml @@ -14,6 +14,7 @@ android:id="@+id/iv_user" android:layout_width="24dp" android:layout_height="24dp" + android:layout_alignTop="@+id/cv_image_message_container" android:layout_marginStart="4dp" android:layout_marginBottom="4dp" tools:src="@tools:sample/avatars" /> @@ -68,17 +69,41 @@ /> + + + + @@ -14,7 +13,8 @@ + + + + @@ -14,7 +13,7 @@ + android:adjustViewBounds="true" /> + + + + + @@ -54,17 +78,40 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" tools:text="11:00 PM" - android:layout_marginStart="16dp" - android:layout_marginEnd="16dp" + android:layout_marginBottom="8dp" android:textSize="12sp" - android:layout_alignEnd="@id/cv_image_message_container" android:layout_gravity="center" - android:layout_below="@id/cv_image_message_container" + tools:drawableEnd="@drawable/ic_double_tick" + android:layout_alignBottom="@+id/cv_image_message_container" + android:layout_toLeftOf="@+id/cv_image_message_container" android:textColor="@color/secondaryTextColor" android:textStyle="bold" tools:visibility="visible" android:visibility="gone" /> - + + + + diff --git a/uikit/src/main/res/layout/message_right_list_video_item.xml b/uikit/src/main/res/layout/message_right_list_video_item.xml index 98ed964d..990c42c1 100644 --- a/uikit/src/main/res/layout/message_right_list_video_item.xml +++ b/uikit/src/main/res/layout/message_right_list_video_item.xml @@ -2,7 +2,6 @@ @@ -14,7 +13,7 @@ + + + + diff --git a/uikit/src/main/res/layout/reply_message_layout.xml b/uikit/src/main/res/layout/reply_message_layout.xml new file mode 100644 index 00000000..0a0e8d15 --- /dev/null +++ b/uikit/src/main/res/layout/reply_message_layout.xml @@ -0,0 +1,49 @@ + + + + + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/layout/right_message_item.xml b/uikit/src/main/res/layout/right_message_item.xml index e21a5566..a6eebf1d 100644 --- a/uikit/src/main/res/layout/right_message_item.xml +++ b/uikit/src/main/res/layout/right_message_item.xml @@ -24,34 +24,65 @@ android:background="@drawable/cc_message_bubble_right" android:layout_marginLeft="10dp" android:layout_marginBottom="1dp"> + + android:padding="10dp" + android:textColor="@color/textColorWhite" + android:maxWidth="250dp" + tools:text="message" /> - + + + + diff --git a/uikit/src/main/res/layout/right_reply_message_item.xml b/uikit/src/main/res/layout/right_reply_message_item.xml new file mode 100644 index 00000000..2f211225 --- /dev/null +++ b/uikit/src/main/res/layout/right_reply_message_item.xml @@ -0,0 +1,52 @@ + + + + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/layout/shared_media_image_row.xml b/uikit/src/main/res/layout/shared_media_image_row.xml index cfc8677b..ca7e138a 100644 --- a/uikit/src/main/res/layout/shared_media_image_row.xml +++ b/uikit/src/main/res/layout/shared_media_image_row.xml @@ -1,5 +1,6 @@ - + + + + \ No newline at end of file diff --git a/uikit/src/main/res/layout/thread_message_audio_layout.xml b/uikit/src/main/res/layout/thread_message_audio_layout.xml new file mode 100644 index 00000000..6b10d6e0 --- /dev/null +++ b/uikit/src/main/res/layout/thread_message_audio_layout.xml @@ -0,0 +1,143 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/layout/thread_message_file_item.xml b/uikit/src/main/res/layout/thread_message_file_item.xml new file mode 100644 index 00000000..9e9ab5c8 --- /dev/null +++ b/uikit/src/main/res/layout/thread_message_file_item.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/uikit/src/main/res/layout/thread_message_image_item.xml b/uikit/src/main/res/layout/thread_message_image_item.xml new file mode 100644 index 00000000..74fa2f8a --- /dev/null +++ b/uikit/src/main/res/layout/thread_message_image_item.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/uikit/src/main/res/layout/thread_message_item.xml b/uikit/src/main/res/layout/thread_message_item.xml new file mode 100644 index 00000000..2ab0449b --- /dev/null +++ b/uikit/src/main/res/layout/thread_message_item.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/uikit/src/main/res/layout/thread_message_link_item.xml b/uikit/src/main/res/layout/thread_message_link_item.xml new file mode 100644 index 00000000..bfc0cb83 --- /dev/null +++ b/uikit/src/main/res/layout/thread_message_link_item.xml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/uikit/src/main/res/layout/thread_message_video_item.xml b/uikit/src/main/res/layout/thread_message_video_item.xml new file mode 100644 index 00000000..69299d06 --- /dev/null +++ b/uikit/src/main/res/layout/thread_message_video_item.xml @@ -0,0 +1,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/uikit/src/main/res/layout/thread_screen_toolbar.xml b/uikit/src/main/res/layout/thread_screen_toolbar.xml new file mode 100644 index 00000000..29490f86 --- /dev/null +++ b/uikit/src/main/res/layout/thread_screen_toolbar.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/uikit/src/main/res/menu/group_action_menu.xml b/uikit/src/main/res/menu/group_action_menu.xml index c3b2232a..dd8d697b 100644 --- a/uikit/src/main/res/menu/group_action_menu.xml +++ b/uikit/src/main/res/menu/group_action_menu.xml @@ -2,11 +2,11 @@

+ android:title="@string/remove" /> + android:title="@string/ban" /> + android:title="@string/make_admin"/> \ No newline at end of file diff --git a/uikit/src/main/res/values/strings.xml b/uikit/src/main/res/values/strings.xml index deeb1143..b1ea368d 100644 --- a/uikit/src/main/res/values/strings.xml +++ b/uikit/src/main/res/values/strings.xml @@ -14,7 +14,7 @@ - message + Write a message You won\'t be able send or receive messages Unblock Unable to join group @@ -98,14 +98,14 @@ Exit Group Exit from group ? Exit - Delete + Delete Message Delete Group Delete the group Group Deletion Failed Can\'t remove %1$s Unable to leave group Blocked userlist retrieval failed - Edit + Edit Message Preview Password Join @@ -128,7 +128,7 @@ Actions User Blocked users - Forward + Forward Message Add Add as Admin Groups @@ -185,6 +185,26 @@ Group not updated Enter Old Password Enter new password + Reply in Message + Shared a Image + Shared a Audio File %1$s + Shared a Video + Shared a File %1$s + Share + Share a message + Shared from cometchat + Unsafe Content. + The following message include potentially sensitive content. + View + Sentiment Alert + Would you like to view this message it may contains sensitive content. + Reply a message + Start a ThreadK + Ban + Thread + Thread in %1$s + Sent at : %1$s + Copy Message Public Group Private Group diff --git a/uikit/src/main/res/values/styles.xml b/uikit/src/main/res/values/styles.xml index 9282bb54..5cdf2bbe 100644 --- a/uikit/src/main/res/values/styles.xml +++ b/uikit/src/main/res/values/styles.xml @@ -9,6 +9,16 @@ true @android:style/Animation @color/colorPrimary + @style/AppBottomSheetDialogTheme + + +