This commit is contained in:
2025-10-20 10:16:44 +08:00
commit 437a623f81
3089 changed files with 1418412 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
plugins {
id 'com.android.library'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
namespace "com.tencent.qcloud.tuikit.tuiconversation"
defaultConfig {
minSdkVersion 19
targetSdkVersion 30
}
buildFeatures {
buildConfig = true
}
buildTypes {
release {
minifyEnabled false
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
sourceSets {
main {
res.srcDirs += "src/main/res-minimalistui"
res.srcDirs += "src/main/res-light"
res.srcDirs += "src/main/res-lively"
res.srcDirs += "src/main/res-serious"
}
}
}
dependencies {
/*plugin-build-Begin
compileOnly fileTree(include: ['*.jar','*.aar'], dir: '../../../../tuikit/android/libs')
plugin-build-End*/
implementation 'androidx.appcompat:appcompat:1.3.0'
implementation 'com.google.android.material:material:1.3.0'
implementation 'com.google.code.gson:gson:2.9.1'
implementation project(':tuichat')
annotationProcessor 'com.google.auto.service:auto-service:1.1.1'
api project(':timcommon')
api project(':moduleUtil')
}

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<!-- **************** Classic UI Activity Start **************** -->
<activity
android:name="com.tencent.qcloud.tuikit.tuiconversation.classicui.page.TUIForwardSelectActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.tencent.qcloud.tuikit.tuiconversation.classicui.page.TUIFoldedConversationActivity"
android:screenOrientation="portrait" />
<!-- **************** Classic UI Activity End **************** -->
<!-- **************** Minimalist UI Activity Start **************** -->
<activity
android:name="com.tencent.qcloud.tuikit.tuiconversation.minimalistui.page.TUIForwardSelectMinimalistActivity"
android:theme="@style/ConversationTransparentPopActivityStyle"
android:screenOrientation="portrait" />
<activity
android:name="com.tencent.qcloud.tuikit.tuiconversation.minimalistui.page.TUIFoldedConversationMinimalistActivity"
android:screenOrientation="portrait" />
<!-- **************** Minimalist UI Activity End **************** -->
</application>
</manifest>

View File

@@ -0,0 +1,38 @@
package com.tencent.qcloud.tuikit.tuiconversation;
public class TUIConversationConstants {
public static final String FORWARD_SELECT_CONVERSATION_KEY = "forward_select_conversation_key";
public static final int FORWARD_SELECT_ACTIVTY_CODE = 101;
public static final String FORWARD_CREATE_NEW_CHAT = "forward_create_new_chat";
public static final String EVENT_CONVERSATION_GROUP_CHANGE_KEY = "conversationGroupChangeKey";
public static final String EVENT_CONVERSATION_GROUP_CHANGE_ADD = "conversationGroupChangeAdd";
public static final String EVENT_CONVERSATION_GROUP_ADD_DATA = "conversationGroupAddData";
public static final String EVENT_CONVERSATION_GROUP_ADD_MARK_DATA = "conversationGroupAddMarkData";
public static final String EVENT_CONVERSATION_GROUP_CHANGE_DELETE = "conversationGroupChangeDelete";
public static final String EVENT_CONVERSATION_GROUP_CHANGE_RENAME = "conversationGroupChangeRename";
public static final String EVENT_CONVERSATION_GROUP_CHANGE_GROUP_NAME = "conversationGroupChangeGroupname";
public static final String EVENT_CONVERSATION_GROUP_CHANGE_UNREAD_COUNT = "conversationGroupChangeUnreadCount";
public static final String CONVERSATION_MARK_NAME_KEY = "conversationMarkNameKey";
public static final String CONVERSATION_GROUP_NAME_KEY = "conversationGroupNameKey";
public static final String CONVERSATION_MARK_DATA_REFRESH_KEY = "conversationMarkDataRefreshKey";
public static final String CONVERSATION_MARK_DATA_REFRESH_SUBKEY = "conversationMarkDataRefreshSubKey";
public static final String CONVERSATION_MARK_DATA_REFRESH_VALUE = "conversationMarkDataRefreshValue";
public static final String CONVERSATION_ALL_GROUP_UNREAD_CHANGE_BY_DIFF = "conversationAllGroupUnreadChangeByDiff";
public static final String CONVERSATION_ALL_GROUP_UNREAD_DIFF = "conversationAllGroupUnreadDiff";
public static class GroupType {
public static final String TYPE = "type";
public static final String GROUP = "isGroup";
public static final int PRIVATE = 0;
public static final int PUBLIC = 1;
public static final int CHAT_ROOM = 2;
public static final int COMMUNITY = 3;
}
public static final String CONVERSATION_SETTINGS_SP_NAME = "conversation_settings_sp";
public static final String HIDE_FOLD_ITEM_SP_KEY_PREFIX = "hide_fold_item_";
public static final String FOLD_ITEM_IS_UNREAD_SP_KEY_PREFIX = "fold_item_is_unread_";
}

View File

@@ -0,0 +1,542 @@
package com.tencent.qcloud.tuikit.tuiconversation;
import android.content.Context;
import android.os.Bundle;
import android.text.TextUtils;
import com.google.auto.service.AutoService;
import com.tencent.imsdk.v2.V2TIMConversation;
import com.tencent.imsdk.v2.V2TIMConversationListener;
import com.tencent.imsdk.v2.V2TIMManager;
import com.tencent.imsdk.v2.V2TIMSDKListener;
import com.tencent.imsdk.v2.V2TIMUserStatus;
import com.tencent.qcloud.tuicore.ServiceInitializer;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuicore.TUILogin;
import com.tencent.qcloud.tuicore.TUIThemeManager;
import com.tencent.qcloud.tuicore.annotations.TUIInitializerDependency;
import com.tencent.qcloud.tuicore.annotations.TUIInitializerID;
import com.tencent.qcloud.tuicore.interfaces.ITUINotification;
import com.tencent.qcloud.tuicore.interfaces.ITUIService;
import com.tencent.qcloud.tuicore.interfaces.TUIInitializer;
import com.tencent.qcloud.tuikit.timcommon.bean.TUIMessageBean;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationGroupBean;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.ConversationUtils;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.TUIConversationLog;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.ConversationEventListener;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.ConversationGroupNotifyListener;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationPresenter;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@AutoService(TUIInitializer.class)
@TUIInitializerDependency("TIMCommon")
@TUIInitializerID("TUIConversation")
public class TUIConversationService implements TUIInitializer, ITUIService, ITUINotification {
public static final String TAG = TUIConversationService.class.getSimpleName();
private static TUIConversationService instance;
public static TUIConversationService getInstance() {
return instance;
}
private boolean syncFinished = false;
private final List<SoftReference<ConversationEventListener>> conversationEventListenerList = new ArrayList<>();
private SoftReference<ConversationGroupNotifyListener> conversationGroupNotifyListener;
private int conversationAllGroupUnreadDiff = 0;
@Override
public void init(Context context) {
instance = this;
initTheme();
initService();
initEvent();
initIMListener();
}
private void initTheme() {
TUIThemeManager.addLightTheme(R.style.TUIConversationLightTheme);
TUIThemeManager.addLivelyTheme(R.style.TUIConversationLivelyTheme);
TUIThemeManager.addSeriousTheme(R.style.TUIConversationSeriousTheme);
}
private void initService() {
TUICore.registerService(TUIConstants.TUIConversation.SERVICE_NAME, this);
}
private void initEvent() {
TUICore.registerEvent(TUIConstants.TUIContact.EVENT_GROUP, TUIConstants.TUIContact.EVENT_SUB_KEY_EXIT_GROUP, this);
TUICore.registerEvent(TUIConstants.TUIContact.EVENT_GROUP, TUIConstants.TUIContact.EVENT_SUB_KEY_MEMBER_KICKED_GROUP, this);
TUICore.registerEvent(TUIConstants.TUIContact.EVENT_GROUP, TUIConstants.TUIContact.EVENT_SUB_KEY_GROUP_DISMISS, this);
TUICore.registerEvent(TUIConstants.TUIContact.EVENT_GROUP, TUIConstants.TUIContact.EVENT_SUB_KEY_GROUP_RECYCLE, this);
TUICore.registerEvent(TUIConstants.TUIContact.EVENT_FRIEND_INFO_CHANGED, TUIConstants.TUIContact.EVENT_SUB_KEY_FRIEND_REMARK_CHANGED, this);
TUICore.registerEvent(TUIConstants.TUIContact.EVENT_GROUP, TUIConstants.TUIContact.EVENT_SUB_KEY_CLEAR_GROUP_MESSAGE, this);
TUICore.registerEvent(TUIConstants.TUIContact.EVENT_USER, TUIConstants.TUIContact.EVENT_SUB_KEY_CLEAR_C2C_MESSAGE, this);
TUICore.registerEvent(TUIConstants.TUIChat.EVENT_KEY_RECEIVE_MESSAGE, TUIConstants.TUIChat.EVENT_SUB_KEY_CONVERSATION_ID, this);
TUICore.registerEvent(TUIConstants.TUIConversation.EVENT_KEY_MESSAGE_SEND_FOR_CONVERSATION,
TUIConstants.TUIConversation.EVENT_SUB_KEY_MESSAGE_SEND_FOR_CONVERSATION, this);
TUICore.registerEvent(TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_KEY, TUIConversationConstants.EVENT_CONVERSATION_GROUP_ADD_DATA, this);
TUICore.registerEvent(
TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_KEY, TUIConversationConstants.EVENT_CONVERSATION_GROUP_ADD_MARK_DATA, this);
TUICore.registerEvent(TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_KEY, TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_ADD, this);
TUICore.registerEvent(
TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_KEY, TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_DELETE, this);
TUICore.registerEvent(
TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_KEY, TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_RENAME, this);
TUICore.registerEvent(
TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_KEY, TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_UNREAD_COUNT, this);
TUICore.registerEvent(
TUIConstants.TUIChat.Event.MessageDisplayString.KEY, TUIConstants.TUIChat.Event.MessageDisplayString.SUB_KEY_PROCESS_MESSAGE, this);
}
@Override
public Object onCall(String method, Map<String, Object> param) {
Bundle result = new Bundle();
if (TextUtils.equals(method, TUIConversationConstants.CONVERSATION_ALL_GROUP_UNREAD_CHANGE_BY_DIFF)) {
if (param == null) {
return result;
}
ConversationEventListener eventListener = getConversationEventListener();
if (eventListener != null) {
int diff = (int) param.get(TUIConversationConstants.CONVERSATION_ALL_GROUP_UNREAD_DIFF);
int count = conversationAllGroupUnreadDiff + diff;
ConversationPresenter presenter = new ConversationPresenter();
presenter.updateUnreadTotalByDiff(count);
}
} else if (TextUtils.equals(TUIConstants.TUIConversation.METHOD_IS_TOP_CONVERSATION, method)) {
ConversationEventListener conversationEventListener = getConversationEventListener();
if (conversationEventListener != null) {
String chatId = (String) param.get(TUIConstants.TUIConversation.CHAT_ID);
if (!TextUtils.isEmpty(chatId)) {
boolean isTop = conversationEventListener.isTopConversation(chatId);
result.putBoolean(TUIConstants.TUIConversation.IS_TOP, isTop);
}
}
} else if (TextUtils.equals(TUIConstants.TUIConversation.METHOD_SET_TOP_CONVERSATION, method)) {
ConversationEventListener conversationEventListener = getConversationEventListener();
if (conversationEventListener != null) {
String chatId = (String) param.get(TUIConstants.TUIConversation.CHAT_ID);
boolean isTop = (boolean) param.get(TUIConstants.TUIConversation.IS_SET_TOP);
if (!TextUtils.isEmpty(chatId)) {
conversationEventListener.setConversationTop(chatId, isTop, new IUIKitCallback<Void>() {
@Override
public void onSuccess(Void data) {}
@Override
public void onError(String module, int errCode, String errMsg) {}
});
}
}
} else if (TextUtils.equals(TUIConstants.TUIConversation.METHOD_GET_TOTAL_UNREAD_COUNT, method)) {
ConversationEventListener conversationEventListener = getConversationEventListener();
if (conversationEventListener != null) {
return conversationEventListener.getUnreadTotal();
}
} else if (TextUtils.equals(TUIConstants.TUIConversation.METHOD_UPDATE_TOTAL_UNREAD_COUNT, method)) {
ConversationEventListener conversationEventListener = getConversationEventListener();
if (conversationEventListener != null) {
HashMap<String, Object> unreadMap = new HashMap<>();
long totalUnread = conversationEventListener.getUnreadTotal();
unreadMap.put(TUIConstants.TUIConversation.TOTAL_UNREAD_COUNT, totalUnread);
TUICore.notifyEvent(TUIConstants.TUIConversation.EVENT_UNREAD, TUIConstants.TUIConversation.EVENT_SUB_KEY_UNREAD_CHANGED, unreadMap);
}
} else if (TextUtils.equals(TUIConstants.TUIConversation.METHOD_DELETE_CONVERSATION, method)) {
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
for (ConversationEventListener conversationEventObserver : conversationEventObserverList) {
if (conversationEventObserver != null) {
String conversationId = (String) param.get(TUIConstants.TUIConversation.CONVERSATION_ID);
conversationEventObserver.clearFoldMarkAndDeleteConversation(conversationId);
}
}
}
return result;
}
@Override
public void onNotifyEvent(String key, String subKey, Map<String, Object> param) {
if (TextUtils.equals(key, TUIConstants.TUIContact.EVENT_GROUP)) {
handleGroupEvent(subKey, param);
} else if (key.equals(TUIConstants.TUIContact.EVENT_USER)) {
handleContactUserEvent(subKey, param);
} else if (key.equals(TUIConstants.TUIContact.EVENT_FRIEND_INFO_CHANGED)) {
handleFriendInfoChangedEvent(subKey, param);
} else if (key.equals(TUIConstants.TUIChat.EVENT_KEY_RECEIVE_MESSAGE)) {
handleChatReceiveMessageEvent(subKey, param);
} else if (TextUtils.equals(key, TUIConstants.TUIConversation.EVENT_KEY_MESSAGE_SEND_FOR_CONVERSATION)) {
handleConversationEvent(subKey, param);
} else if (TextUtils.equals(key, TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_KEY)) {
handleConversationGroupChangedEvent(subKey, param);
} else if (TextUtils.equals(key, TUIConstants.TUIChat.Event.MessageDisplayString.KEY)) {
handleMessageBeanUpdateEvent(subKey, param);
}
}
private void handleConversationEvent(String subKey, Map<String, Object> param) {
if (TextUtils.equals(subKey, TUIConstants.TUIConversation.EVENT_SUB_KEY_MESSAGE_SEND_FOR_CONVERSATION)) {
if (param == null || param.isEmpty()) {
return;
}
String conversationID = (String) param.get(TUIConstants.TUIConversation.CONVERSATION_ID);
List<ConversationEventListener> conversationEventListenerList = getConversationEventListenerList();
for (ConversationEventListener conversationEventListener : conversationEventListenerList) {
if (conversationEventListener != null) {
conversationEventListener.onMessageSendForHideConversation(conversationID);
}
}
}
}
private void handleConversationGroupChangedEvent(String subKey, Map<String, Object> param) {
if (TextUtils.equals(subKey, TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_ADD)) {
if (param == null || param.isEmpty()) {
TUIConversationLog.e(TAG, "EVENT_CONVERSATION_GROUP_CHANGE_ADD param is null");
return;
}
ConversationGroupBean bean = (ConversationGroupBean) param.get(TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_ADD);
ConversationGroupNotifyListener eventListener = getConversationGroupNotifyListener();
if (eventListener != null) {
eventListener.notifyGroupAdd(bean);
} else {
TUIConversationLog.e(TAG, "eventListener is null");
}
} else if (TextUtils.equals(subKey, TUIConversationConstants.EVENT_CONVERSATION_GROUP_ADD_DATA)) {
if (param == null || param.isEmpty()) {
TUIConversationLog.e(TAG, "EVENT_CONVERSATION_GROUP_ADD_DATA param is null");
return;
}
List<ConversationGroupBean> beans = (List<ConversationGroupBean>) param.get(TUIConversationConstants.EVENT_CONVERSATION_GROUP_ADD_DATA);
ConversationGroupNotifyListener eventListener = getConversationGroupNotifyListener();
if (eventListener != null) {
eventListener.notifyGroupsAdd(beans);
} else {
TUIConversationLog.e(TAG, "eventListener is null");
}
} else if (TextUtils.equals(subKey, TUIConversationConstants.EVENT_CONVERSATION_GROUP_ADD_MARK_DATA)) {
if (param == null || param.isEmpty()) {
TUIConversationLog.e(TAG, "EVENT_CONVERSATION_GROUP_ADD_MARK_DATA param is null");
return;
}
List<ConversationGroupBean> beans = (List<ConversationGroupBean>) param.get(TUIConversationConstants.EVENT_CONVERSATION_GROUP_ADD_MARK_DATA);
ConversationGroupNotifyListener eventListener = getConversationGroupNotifyListener();
if (eventListener != null) {
eventListener.notifyMarkGroupsAdd(beans);
} else {
TUIConversationLog.e(TAG, "eventListener is null");
}
} else if (TextUtils.equals(subKey, TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_DELETE)) {
if (param == null || param.isEmpty()) {
TUIConversationLog.e(TAG, "EVENT_CONVERSATION_GROUP_CHANGE_DELETE param is null");
return;
}
String groupName = (String) param.get(TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_DELETE);
ConversationGroupNotifyListener eventListener = getConversationGroupNotifyListener();
if (eventListener != null) {
eventListener.notifyGroupDelete(groupName);
} else {
TUIConversationLog.e(TAG, "eventListener is null");
}
} else if (TextUtils.equals(subKey, TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_RENAME)) {
if (param == null || param.isEmpty()) {
TUIConversationLog.e(TAG, "EVENT_CONVERSATION_GROUP_CHANGE_RENAME param is null");
return;
}
String oldName = (String) param.get(TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_RENAME);
String newName = (String) param.get(TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_GROUP_NAME);
ConversationGroupNotifyListener eventListener = getConversationGroupNotifyListener();
if (eventListener != null) {
eventListener.notifyGroupRename(oldName, newName);
} else {
TUIConversationLog.e(TAG, "eventListener is null");
}
} else if (TextUtils.equals(subKey, TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_UNREAD_COUNT)) {
if (param == null || param.isEmpty()) {
TUIConversationLog.e(TAG, "EVENT_CONVERSATION_GROUP_CHANGE_UNREAD_COUNT param is null");
return;
}
long count = (long) param.get(TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_UNREAD_COUNT);
String groupName = (String) param.get(TUIConversationConstants.EVENT_CONVERSATION_GROUP_CHANGE_GROUP_NAME);
ConversationGroupNotifyListener eventListener = getConversationGroupNotifyListener();
if (eventListener != null) {
eventListener.notifyGroupUnreadMessageCountChanged(groupName, count);
} else {
TUIConversationLog.e(TAG, "eventListener is null");
}
}
}
private ConversationEventListener getConversationEventListener() {
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
if (!conversationEventObserverList.isEmpty()) {
return conversationEventObserverList.get(0);
}
return null;
}
private void handleChatReceiveMessageEvent(String subKey, Map<String, Object> param) {
if (subKey.equals(TUIConstants.TUIChat.EVENT_SUB_KEY_CONVERSATION_ID)) {
if (param == null || param.isEmpty()) {
return;
}
String conversationID = (String) param.get(TUIConstants.TUIChat.CONVERSATION_ID);
boolean isTypingMessage = false;
if (param.containsKey(TUIConstants.TUIChat.IS_TYPING_MESSAGE)) {
isTypingMessage = (Boolean) param.get(TUIConstants.TUIChat.IS_TYPING_MESSAGE);
}
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
for (ConversationEventListener conversationEventObserver : conversationEventObserverList) {
if (conversationEventObserver != null) {
conversationEventObserver.onReceiveMessage(conversationID, isTypingMessage);
}
}
}
}
private void handleFriendInfoChangedEvent(String subKey, Map<String, Object> param) {
if (subKey.equals(TUIConstants.TUIContact.EVENT_SUB_KEY_FRIEND_REMARK_CHANGED)) {
if (param == null || param.isEmpty()) {
return;
}
String id = (String) param.get(TUIConstants.TUIContact.FRIEND_ID);
String remark = (String) param.get(TUIConstants.TUIContact.FRIEND_REMARK);
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
for (ConversationEventListener conversationEventObserver : conversationEventObserverList) {
if (conversationEventObserver != null) {
conversationEventObserver.onFriendRemarkChanged(id, remark);
}
}
}
}
private void handleContactUserEvent(String subKey, Map<String, Object> param) {
if (subKey.equals(TUIConstants.TUIContact.EVENT_SUB_KEY_CLEAR_C2C_MESSAGE)) {
if (param == null || param.isEmpty()) {
return;
}
String userID = (String) getOrDefault(param.get(TUIConstants.TUIContact.FRIEND_ID), "");
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
for (ConversationEventListener conversationEventObserver : conversationEventObserverList) {
if (conversationEventObserver != null) {
conversationEventObserver.clearConversationMessage(userID, false);
}
}
}
}
private void handleGroupEvent(String subKey, Map<String, Object> param) {
if (TextUtils.equals(subKey, TUIConstants.TUIContact.EVENT_SUB_KEY_EXIT_GROUP)
|| TextUtils.equals(subKey, TUIConstants.TUIContact.EVENT_SUB_KEY_GROUP_DISMISS)
|| TextUtils.equals(subKey, TUIConstants.TUIContact.EVENT_SUB_KEY_GROUP_RECYCLE)) {
String groupId = null;
if (param != null) {
groupId = (String) getOrDefault(param.get(TUIConstants.TUIContact.GROUP_ID), "");
}
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
for (ConversationEventListener conversationEventObserver : conversationEventObserverList) {
if (conversationEventObserver != null) {
conversationEventObserver.deleteConversation(groupId, true);
}
}
} else if (TextUtils.equals(subKey, TUIConstants.TUIContact.EVENT_SUB_KEY_MEMBER_KICKED_GROUP)) {
if (param == null) {
return;
}
String groupId = (String) getOrDefault(param.get(TUIConstants.TUIContact.GROUP_ID), "");
ArrayList<String> memberList = (ArrayList<String>) param.get(TUIConstants.TUIContact.GROUP_MEMBER_ID_LIST);
if (TextUtils.isEmpty(groupId) || memberList == null || memberList.isEmpty()) {
return;
}
for (String id : memberList) {
if (TextUtils.equals(id, TUILogin.getLoginUser())) {
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
for (ConversationEventListener conversationEventObserver : conversationEventObserverList) {
if (conversationEventObserver != null) {
conversationEventObserver.deleteConversation(groupId, true);
}
}
break;
}
}
} else if (TextUtils.equals(subKey, TUIConstants.TUIContact.EVENT_SUB_KEY_CLEAR_GROUP_MESSAGE)) {
String groupId = (String) getOrDefault(param.get(TUIConstants.TUIContact.GROUP_ID), "");
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
for (ConversationEventListener conversationEventObserver : conversationEventObserverList) {
if (conversationEventObserver != null) {
conversationEventObserver.clearConversationMessage(groupId, true);
}
}
}
}
private void handleMessageBeanUpdateEvent(String subKey, Map<String, Object> param) {
if (TextUtils.equals(TUIConstants.TUIChat.Event.MessageDisplayString.SUB_KEY_PROCESS_MESSAGE, subKey)) {
String conversationID = (String) param.get(TUIConstants.TUIChat.Event.MessageDisplayString.CONVERSATION_ID);
TUIMessageBean messageBean = (TUIMessageBean) param.get(TUIConstants.TUIChat.Event.MessageDisplayString.MESSAGE_BEAN);
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
for (ConversationEventListener conversationEventObserver : conversationEventObserverList) {
if (conversationEventObserver != null) {
conversationEventObserver.onConversationLastMessageBeanChanged(conversationID, messageBean);
}
}
}
}
private Object getOrDefault(Object value, Object defaultValue) {
if (value != null) {
return value;
}
return defaultValue;
}
private void initIMListener() {
V2TIMManager.getConversationManager().addConversationListener(new V2TIMConversationListener() {
@Override
public void onSyncServerStart() {
syncFinished = false;
}
@Override
public void onSyncServerFinish() {
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
for (ConversationEventListener conversationEventObserver : conversationEventObserverList) {
if (conversationEventObserver != null) {
conversationEventObserver.onSyncServerFinish();
}
}
syncFinished = true;
}
@Override
public void onSyncServerFailed() {
syncFinished = false;
}
@Override
public void onNewConversation(List<V2TIMConversation> conversationList) {
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
for (ConversationEventListener conversationEventObserver : conversationEventObserverList) {
if (conversationEventObserver != null) {
List<ConversationInfo> conversationInfoList = ConversationUtils.convertV2TIMConversationList(conversationList);
conversationEventObserver.onNewConversation(conversationInfoList);
}
}
}
@Override
public void onConversationChanged(List<V2TIMConversation> conversationList) {
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
for (ConversationEventListener conversationEventObserver : conversationEventObserverList) {
if (conversationEventObserver != null) {
List<ConversationInfo> conversationInfoList = ConversationUtils.convertV2TIMConversationList(conversationList);
conversationEventObserver.onConversationChanged(conversationInfoList);
}
}
}
@Override
public void onTotalUnreadMessageCountChanged(long totalUnreadCount) {
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
for (ConversationEventListener conversationEventObserver : conversationEventObserverList) {
if (conversationEventObserver != null) {
conversationEventObserver.updateTotalUnreadMessageCount(totalUnreadCount);
}
}
}
@Override
public void onConversationDeleted(List<String> conversationIDList) {
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
for (ConversationEventListener conversationEventObserver : conversationEventObserverList) {
if (conversationEventObserver != null) {
conversationEventObserver.onConversationDeleted(conversationIDList);
}
}
}
});
V2TIMSDKListener v2TIMSDKListener = new V2TIMSDKListener() {
@Override
public void onUserStatusChanged(List<V2TIMUserStatus> userStatusList) {
List<ConversationEventListener> conversationEventObserverList = getConversationEventListenerList();
for (ConversationEventListener conversationEventObserver : conversationEventObserverList) {
conversationEventObserver.onUserStatusChanged(userStatusList);
}
}
};
V2TIMManager.getInstance().addIMSDKListener(v2TIMSDKListener);
}
public void addConversationEventListener(ConversationEventListener conversationEventListener) {
if (conversationEventListener == null) {
return;
}
for (SoftReference<ConversationEventListener> listenerWeakReference : conversationEventListenerList) {
if (listenerWeakReference.get() == conversationEventListener) {
return;
}
}
conversationEventListenerList.add(new SoftReference<>(conversationEventListener));
}
public void removeConversationEventListener(ConversationEventListener conversationEventListener) {
if (conversationEventListener == null) {
return;
}
for (SoftReference<ConversationEventListener> listenerWeakReference : conversationEventListenerList) {
if (listenerWeakReference.get() == conversationEventListener) {
conversationEventListenerList.remove(listenerWeakReference);
break;
}
}
}
public List<ConversationEventListener> getConversationEventListenerList() {
List<ConversationEventListener> listeners = new ArrayList<>();
Iterator<SoftReference<ConversationEventListener>> iterator = conversationEventListenerList.listIterator();
while (iterator.hasNext()) {
SoftReference<ConversationEventListener> listenerWeakReference = iterator.next();
ConversationEventListener listener = listenerWeakReference.get();
if (listener == null) {
iterator.remove();
} else {
listeners.add(listener);
}
}
return listeners;
}
public void setConversationGroupNotifyListener(ConversationGroupNotifyListener listener) {
this.conversationGroupNotifyListener = new SoftReference<>(listener);
}
public ConversationGroupNotifyListener getConversationGroupNotifyListener() {
if (conversationGroupNotifyListener != null) {
return conversationGroupNotifyListener.get();
}
return null;
}
public void setConversationGroupNotifyListenerNull() {
this.conversationGroupNotifyListener = null;
}
public void setConversationAllGroupUnreadDiff(int diff) {
this.conversationAllGroupUnreadDiff = diff;
}
public static Context getAppContext() {
return ServiceInitializer.getAppContext();
}
}

View File

@@ -0,0 +1,109 @@
package com.tencent.qcloud.tuikit.tuiconversation.bean;
public class ConversationGroupBean {
public static final int CONVERSATION_GROUP_TYPE_DEFAULT = 101;
public static final int CONVERSATION_GROUP_TYPE_MARK = 102;
public static final int CONVERSATION_GROUP_TYPE_GROUP = 103;
public static final int CONVERSATION_ALL_GROUP_WEIGHT = 0;
public static final int CONVERSATION_DEFAULT_GROUP_WEIGHT = 2;
public static final int CONVERSATION_MARK_START_GROUP_WEIGHT = 4;
public static final int CONVERSATION_GROUP_START_GROUP_WEIGHT = 5;
private transient String title;
private int weight = 0;
private boolean isHide;
private transient int groupType;
private transient long unReadCount;
private transient long markType = -1;
public long getUnReadCount() {
return unReadCount;
}
public void setUnReadCount(long unReadCount) {
this.unReadCount = unReadCount;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public long getMarkType() {
return markType;
}
public void setMarkType(long markType) {
this.markType = markType;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public int getGroupType() {
return groupType;
}
public void setGroupType(int groupType) {
this.groupType = groupType;
}
public boolean getIsHide() {
return isHide;
}
public void setIsHide(boolean head) {
this.isHide = head;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
ConversationGroupBean bean = (ConversationGroupBean) o;
// return Objects.equals(title, bean.title);
return beanEquals(title, bean.title);
}
private boolean beanEquals(Object a, Object b) {
if (a == b) {
return true;
}
if (a == null || b == null) {
return false;
}
return a.equals(b);
}
@Override
public int hashCode() {
// return Objects.hash(title);
int result = 17;
result = 31 * result + ((title == null) ? 0 : title.hashCode());
result = 31 * result + (int) unReadCount;
result = 31 * result + (int) markType;
result = 31 * result + weight;
result = 31 * result + groupType;
return result;
}
@Override
public String toString() {
return "ConversationGroupBean{"
+ "title=" + title + ", unReadCount=" + unReadCount + ", markType='" + markType + '\'' + ", weight='" + weight + '\'' + ", groupType='" + groupType
+ '\'' + ", isHide='" + isHide + '\'' + '}';
}
}

View File

@@ -0,0 +1,382 @@
package com.tencent.qcloud.tuikit.tuiconversation.bean;
import androidx.annotation.NonNull;
import com.tencent.imsdk.v2.V2TIMConversation;
import com.tencent.imsdk.v2.V2TIMGroupAtInfo;
import com.tencent.imsdk.v2.V2TIMMessage;
import com.tencent.imsdk.v2.V2TIMUserStatus;
import com.tencent.qcloud.tuikit.timcommon.bean.TUIMessageBean;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class ConversationInfo implements Serializable, Comparable<ConversationInfo> {
public static final int TYPE_COMMON = 1;
public static final int TYPE_CUSTOM = 2;
public static final int TYPE_FORWAR_SELECT = 3;
public static final int TYPE_RECENT_LABEL = 4;
public static final int AT_TYPE_AT_ME = V2TIMGroupAtInfo.TIM_AT_ME;
public static final int AT_TYPE_AT_ALL = V2TIMGroupAtInfo.TIM_AT_ALL;
public static final int AT_TYPE_AT_ALL_AND_ME = V2TIMGroupAtInfo.TIM_AT_ALL_AT_ME;
public static final int AT_TYPE_UNKNOWN = V2TIMGroupAtInfo.TIM_AT_UNKNOWN;
public static final int USER_STATUS_UNKNOWN = V2TIMUserStatus.V2TIM_USER_STATUS_UNKNOWN;
public static final int USER_STATUS_ONLINE = V2TIMUserStatus.V2TIM_USER_STATUS_ONLINE;
public static final int LAST_MSG_STATUS_UNKNOWN = 0;
public static final int LAST_MSG_STATUS_SENDING = V2TIMMessage.V2TIM_MSG_STATUS_SENDING;
public static final int LAST_MSG_STATUS_SEND_FAIL = V2TIMMessage.V2TIM_MSG_STATUS_SEND_FAIL;
public static final int LAST_MSG_STATUS_HAS_DELETED = V2TIMMessage.V2TIM_MSG_STATUS_HAS_DELETED;
public static final int LAST_MSG_STATUS_LOCAL_IMPORTED = V2TIMMessage.V2TIM_MSG_STATUS_LOCAL_IMPORTED;
public static final int LAST_MSG_STATUS_LOCAL_REVOKED = V2TIMMessage.V2TIM_MSG_STATUS_LOCAL_REVOKED;
/**
* conversation type
*/
private int type;
private int atType = AT_TYPE_UNKNOWN;
/**
* unread message number
*/
private int unRead;
/**
* conversation ID
*/
private String conversationId;
/**
* ID, C2C is UserID, Group is group ID
*/
private String id;
private int statusType = USER_STATUS_UNKNOWN;
private V2TIMConversation conversation;
private List<Object> iconUrlList = new ArrayList<>();
public List<Object> getIconUrlList() {
return iconUrlList;
}
public void setIconUrlList(List<Object> iconUrlList) {
this.iconUrlList = iconUrlList;
}
public V2TIMConversation getConversation() {
return conversation;
}
public void setConversation(V2TIMConversation conversation) {
this.conversation = conversation;
}
public String getShowName() {
if (conversation != null) {
return conversation.getShowName();
}
return null;
}
private String title;
private String iconPath;
private boolean isGroup;
private boolean top;
/**
* Is folded conversation or not
*/
private boolean isMarkFold;
/**
* Is marked conversation unread or not
*/
private boolean isMarkUnread;
/**
* Is marked conversation hidden or not
*/
private boolean isMarkHidden;
/**
* Is marked conversation local-unread or not
*/
private boolean isMarkLocalUnread;
private boolean isMarkStar;
private long lastMessageTime;
private V2TIMMessage lastMessage;
private TUIMessageBean lastTUIMessageBean;
/**
* "@" message in group
*/
private String atInfoText;
/**
* the conversation item displays the icon of Do Not Disturb
*/
private boolean showDisturbIcon;
private DraftInfo draft;
private String groupType;
/**
* conversation sort key
*/
private long orderKey;
public ConversationInfo() {}
public String getConversationId() {
return conversationId;
}
public void setConversationId(String conversationId) {
this.conversationId = conversationId;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getUnRead() {
return unRead;
}
public void setUnRead(int unRead) {
this.unRead = unRead;
}
public boolean isGroup() {
return isGroup;
}
public void setGroup(boolean group) {
isGroup = group;
}
public boolean isTop() {
return top;
}
public void setTop(boolean top) {
this.top = top;
}
public boolean isMarkFold() {
return isMarkFold;
}
public void setMarkFold(boolean markFold) {
isMarkFold = markFold;
}
public boolean isMarkUnread() {
return isMarkUnread;
}
public void setMarkUnread(boolean markUnread) {
isMarkUnread = markUnread;
}
public boolean isMarkHidden() {
return isMarkHidden;
}
public void setMarkHidden(boolean markHidden) {
isMarkHidden = markHidden;
}
public boolean isMarkLocalUnread() {
return isMarkLocalUnread;
}
public void setMarkLocalUnread(boolean markLocalUnread) {
isMarkLocalUnread = markLocalUnread;
}
public boolean isMarkStar() {
return isMarkStar;
}
public void setMarkStar(boolean markStar) {
isMarkStar = markStar;
}
public List<Long> getMarkList() {
if (conversation == null) {
return null;
}
return conversation.getMarkList();
}
/**
* Get the time of the last message, in seconds
*/
public long getLastMessageTime() {
return lastMessageTime;
}
/**
* Set the time of the last message, in seconds
* @param lastMessageTime
*/
public void setLastMessageTime(long lastMessageTime) {
this.lastMessageTime = lastMessageTime;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public void setAtType(int atType) {
this.atType = atType;
}
public int getAtType() {
return atType;
}
public V2TIMMessage getLastMessage() {
return lastMessage;
}
public void setLastMessage(V2TIMMessage lastMessage) {
this.lastMessage = lastMessage;
}
public void setAtInfoText(String atInfoText) {
this.atInfoText = atInfoText;
}
public String getAtInfoText() {
return atInfoText;
}
public boolean isShowDisturbIcon() {
return showDisturbIcon;
}
public void setShowDisturbIcon(boolean showDisturbIcon) {
this.showDisturbIcon = showDisturbIcon;
}
public void setDraft(DraftInfo draft) {
this.draft = draft;
}
public DraftInfo getDraft() {
return this.draft;
}
public String getGroupType() {
return groupType;
}
public void setGroupType(String groupType) {
this.groupType = groupType;
}
public String getIconPath() {
return iconPath;
}
public void setIconPath(String iconPath) {
this.iconPath = iconPath;
}
public void setOrderKey(long orderKey) {
this.orderKey = orderKey;
}
public long getOrderKey() {
return orderKey;
}
public List<V2TIMGroupAtInfo> getGroupAtInfoList() {
if (conversation != null) {
return conversation.getGroupAtInfoList();
}
return null;
}
public int getStatusType() {
return statusType;
}
public void setStatusType(int statusType) {
this.statusType = statusType;
}
public List<String> getConversationGroupList() {
if (conversation != null) {
return conversation.getConversationGroupList();
}
return null;
}
public int getLastMessageStatus() {
if (conversation != null) {
if (conversation.getLastMessage() != null) {
return conversation.getLastMessage().getStatus();
}
}
return LAST_MSG_STATUS_UNKNOWN;
}
public TUIMessageBean getLastTUIMessageBean() {
return lastTUIMessageBean;
}
public void setLastTUIMessageBean(TUIMessageBean lastTUIMessageBean) {
this.lastTUIMessageBean = lastTUIMessageBean;
}
@Override
public int compareTo(@NonNull ConversationInfo other) {
if (this.isTop() && !other.isTop()) {
return -1;
} else if (!this.isTop() && other.isTop()) {
return 1;
} else {
long thisOrderKey = this.orderKey;
long otherOrderKey = other.orderKey;
if (thisOrderKey > otherOrderKey) {
return -1;
} else if (thisOrderKey == otherOrderKey) {
return 0;
} else {
return 1;
}
}
}
@Override
public String toString() {
return "ConversationInfo{"
+ "type=" + type + ", unRead=" + unRead + ", conversationId='" + conversationId + '\'' + ", id='" + id + '\'' + ", iconUrl='" + iconUrlList.size()
+ '\'' + ", title='" + title + '\'' + ", iconPath=" + iconPath + ", isGroup=" + isGroup + ", top=" + top + ", lastMessageTime=" + lastMessageTime
+ ", lastMessage=" + lastMessage + ", draftText=" + draft + ", groupType=" + groupType + ", statusType=" + statusType + '}';
}
}

View File

@@ -0,0 +1,10 @@
package com.tencent.qcloud.tuikit.tuiconversation.bean;
import android.view.View;
public class ConversationPopMenuItem {
public String text;
public int iconResId;
public boolean isAlert;
public View.OnClickListener onClickListener;
}

View File

@@ -0,0 +1,31 @@
package com.tencent.qcloud.tuikit.tuiconversation.bean;
import com.tencent.imsdk.v2.V2TIMUserStatus;
public class ConversationUserStatusBean {
public static final int USER_STATUS_UNKNOWN = V2TIMUserStatus.V2TIM_USER_STATUS_UNKNOWN;
public static final int USER_STATUS_ONLINE = V2TIMUserStatus.V2TIM_USER_STATUS_ONLINE;
public static final int USER_STATUS_OFFLINE = V2TIMUserStatus.V2TIM_USER_STATUS_OFFLINE;
public static final int USER_STATUS_UNLOGINED = V2TIMUserStatus.V2TIM_USER_STATUS_UNLOGINED;
private V2TIMUserStatus v2TIMUserStatus;
public void setV2TIMUserStatus(V2TIMUserStatus v2TIMUserStatus) {
this.v2TIMUserStatus = v2TIMUserStatus;
}
public String getUserID() {
if (v2TIMUserStatus != null) {
return v2TIMUserStatus.getUserID();
}
return "";
}
public int getStatusType() {
if (v2TIMUserStatus != null) {
return v2TIMUserStatus.getStatusType();
}
return 0;
}
}

View File

@@ -0,0 +1,30 @@
package com.tencent.qcloud.tuikit.tuiconversation.bean;
import java.io.Serializable;
public class DraftInfo implements Serializable {
private String draftText;
private long draftTime;
public String getDraftText() {
return draftText;
}
public void setDraftText(String draftText) {
this.draftText = draftText;
}
public long getDraftTime() {
return draftTime;
}
public void setDraftTime(long draftTime) {
this.draftTime = draftTime;
}
@Override
public String toString() {
return "DraftInfo{"
+ "draftText='" + draftText + '\'' + ", draftTime=" + draftTime + '}';
}
}

View File

@@ -0,0 +1,37 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces;
import android.view.View;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.ILayout;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
public interface IConversationLayout extends ILayout {
View getConversationList();
void setConversationTop(ConversationInfo conversation, IUIKitCallback callBack);
void deleteConversation(ConversationInfo conversation);
void clearConversationMessage(ConversationInfo conversation);
/**
* Hide normal conversation
*/
void markConversationHidden(ConversationInfo conversation);
/**
* Mark conversation read or unread
*/
void markConversationUnread(ConversationInfo conversationInfo, boolean markUnread);
/**
* Hide folded conversation item
*/
void hideFoldedItem(boolean needHide);
/**
* Clear unread status of fold item
*/
void clearUnreadStatusOfFoldItem();
}

View File

@@ -0,0 +1,25 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces;
import android.view.View;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.widget.ConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
public interface IConversationListLayout {
void setBackground(int resId);
void setOnConversationAdapterListener(OnConversationAdapterListener listener);
/**
* Do not display the switch for the number of unread messages with the small red dot
*
* @param flag false
*/
void disableItemUnreadDot(boolean flag);
View getListLayout();
ConversationListAdapter getAdapter();
void setAdapter(IConversationListAdapter adapter);
}

View File

@@ -0,0 +1,46 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import java.util.List;
public interface IConversationProvider {
/**
* Get a specific session data set, and ConversationContainer displays the session list based on the data set
*
* @return
*/
List<ConversationInfo> getDataSource();
/**
* Bulk add session entries
*
* @param conversations
* @return
*/
boolean addConversations(List<ConversationInfo> conversations);
/**
* Delete session entries
*
* @param conversations
* @return
*/
boolean deleteConversations(List<ConversationInfo> conversations);
/**
* Update session entries
*
* @param conversations
* @return
*/
boolean updateConversations(List<ConversationInfo> conversations);
/**
* Called when a session adapter is bound, automatically called when {@link
* com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter#setDataProvider} is called
*/
void attachAdapter(IConversationListAdapter adapter);
}

View File

@@ -0,0 +1,15 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces;
import android.view.View;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import java.util.List;
public interface OnConversationAdapterListener {
void onItemClick(View view, int viewType, ConversationInfo conversationInfo);
void onItemLongClick(View view, ConversationInfo conversationInfo);
void onConversationChanged(List<ConversationInfo> dataSource);
}

View File

@@ -0,0 +1,331 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.page;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.PopupWindow;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuicore.interfaces.TUIExtensionEventListener;
import com.tencent.qcloud.tuicore.interfaces.TUIExtensionInfo;
import com.tencent.qcloud.tuicore.util.ScreenUtil;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopActionClickListener;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopDialogAdapter;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopMenuAction;
import com.tencent.qcloud.tuikit.timcommon.component.dialog.TUIKitDialog;
import com.tencent.qcloud.tuikit.timcommon.config.classicui.TUIConfigClassic;
import com.tencent.qcloud.tuikit.timcommon.util.LayoutUtil;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationGroupBean;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces.OnConversationAdapterListener;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.util.TUIConversationUtils;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.widget.ConversationLayout;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.ConversationUtils;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.TUIConversationLog;
import com.tencent.qcloud.tuikit.tuiconversation.config.classicui.TUIConversationConfigClassic;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationPresenter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TUIConversationFragment extends Fragment {
private static final String TAG = TUIConversationFragment.class.getSimpleName();
private View mBaseView;
private ConversationLayout mConversationLayout;
private ListView mConversationPopList;
private PopDialogAdapter mConversationPopAdapter;
private PopupWindow mConversationPopWindow;
private List<PopMenuAction> mConversationPopActions = new ArrayList<>();
private ConversationPresenter presenter;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
TUIConversationLog.d(TAG, "onCreateView");
mBaseView = inflater.inflate(R.layout.conversation_fragment, container, false);
initView();
return mBaseView;
}
@Override
public void onResume() {
super.onResume();
presenter.setFocus(true);
TUIConversationLog.d(TAG, "onResume");
}
@Override
public void onPause() {
super.onPause();
presenter.setFocus(false);
TUIConversationLog.d(TAG, "onPause");
}
public static TUIConversationFragment newInstance() {
TUIConversationFragment fragment = new TUIConversationFragment();
return fragment;
}
private void initView() {
mConversationLayout = mBaseView.findViewById(R.id.conversation_layout);
TUIConfigClassic.setMessageListAvatarSize(100);
TUIConfigClassic.setMessageListAvatarRadius(50);
presenter = new ConversationPresenter();
presenter.setConversationListener();
presenter.setShowType(ConversationPresenter.SHOW_TYPE_CONVERSATION_LIST_WITH_FOLD);
presenter.setConversationGroupType(ConversationGroupBean.CONVERSATION_GROUP_TYPE_DEFAULT);
mConversationLayout.setPresenter(presenter);
mConversationLayout.initDefault();
mConversationLayout.getConversationList().setOnConversationAdapterListener(new OnConversationAdapterListener() {
@Override
public void onItemClick(View view, int viewType, ConversationInfo conversationInfo) {
if (conversationInfo.isMarkFold()) {
mConversationLayout.clearUnreadStatusOfFoldItem();
startFoldedConversationActivity();
} else {
TUIConversationUtils.startChatActivity(conversationInfo);
}
}
@Override
public void onItemLongClick(View view, ConversationInfo conversationInfo) {
showItemPopMenu(view, conversationInfo);
}
@Override
public void onConversationChanged(List<ConversationInfo> dataSource) {
if (dataSource == null) {
return;
}
ConversationInfo conversationInfo = dataSource.get(0);
if (conversationInfo == null) {
return;
}
}
});
restoreConversationItemBackground();
}
public void restoreConversationItemBackground() {
if (mConversationLayout.getConversationList().getAdapter() != null && mConversationLayout.getConversationList().getAdapter().isClick()) {
mConversationLayout.getConversationList().getAdapter().setClick(false);
mConversationLayout.getConversationList().getAdapter().notifyItemChanged(
mConversationLayout.getConversationList().getAdapter().getCurrentPosition());
}
}
private PopMenuAction getMarkUnreadPopMenuAction(boolean markUnread) {
PopMenuAction markUnreadAction = new PopMenuAction();
markUnreadAction.setActionClickListener(new PopActionClickListener() {
@Override
public void onActionClick(int index, Object data) {
mConversationLayout.markConversationUnread((ConversationInfo) data, markUnread);
}
});
if (markUnread) {
markUnreadAction.setActionName(getResources().getString(R.string.mark_unread));
} else {
markUnreadAction.setActionName(getResources().getString(R.string.mark_read));
}
markUnreadAction.setWeight(900);
return markUnreadAction;
}
private PopMenuAction getDeletePopMenuAction() {
PopMenuAction action = new PopMenuAction();
action.setActionClickListener(new PopActionClickListener() {
@Override
public void onActionClick(int index, Object data) {
TUIKitDialog tipsDialog =
new TUIKitDialog(getContext())
.builder()
.setCancelable(true)
.setCancelOutside(true)
.setTitle(getContext().getString(R.string.conversation_delete_tips))
.setDialogWidth(0.75f)
.setPositiveButton(getContext().getString(com.tencent.qcloud.tuicore.R.string.sure),
new View.OnClickListener() {
@Override
public void onClick(View v) {
mConversationLayout.deleteConversation((ConversationInfo) data);
}
})
.setNegativeButton(getContext().getString(com.tencent.qcloud.tuicore.R.string.cancel), new View.OnClickListener() {
@Override
public void onClick(View v) {}
});
tipsDialog.show();
}
});
action.setActionName(getResources().getString(R.string.chat_delete));
action.setWeight(700);
return action;
}
private void showItemPopMenu(View view, final ConversationInfo conversationInfo) {
mConversationPopActions.clear();
PopMenuAction hideAction = new PopMenuAction();
hideAction.setActionName(getResources().getString(R.string.not_display));
hideAction.setWeight(800);
hideAction.setActionClickListener(new PopActionClickListener() {
@Override
public void onActionClick(int index, Object data) {
ConversationInfo conversationInfo = (ConversationInfo) data;
if (conversationInfo.isMarkFold()) {
mConversationLayout.hideFoldedItem(true);
} else {
mConversationLayout.markConversationHidden(conversationInfo);
}
}
});
mConversationPopActions.add(hideAction);
PopMenuAction markUnreadAction = null;
PopMenuAction deleteAction = null;
if (!conversationInfo.isMarkFold()) {
if (conversationInfo.getUnRead() > 0) {
markUnreadAction = getMarkUnreadPopMenuAction(false);
} else {
if (conversationInfo.isMarkUnread()) {
markUnreadAction = getMarkUnreadPopMenuAction(false);
} else {
markUnreadAction = getMarkUnreadPopMenuAction(true);
}
}
deleteAction = getDeletePopMenuAction();
mConversationPopActions.add(markUnreadAction);
mConversationPopActions.add(deleteAction);
mConversationPopActions.addAll(addMoreConversationAction(conversationInfo));
}
View itemPop = LayoutInflater.from(getActivity()).inflate(R.layout.conversation_pop_menu_layout, null);
mConversationPopList = itemPop.findViewById(R.id.pop_menu_list);
mConversationPopList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
PopMenuAction action = mConversationPopActions.get(position);
if (action.getActionClickListener() != null) {
action.getActionClickListener().onActionClick(position, conversationInfo);
}
mConversationPopWindow.dismiss();
restoreConversationItemBackground();
}
});
TUIConversationConfigClassic.ConversationMenuItemDataSource dataSource = TUIConversationConfigClassic.getConversationMenuItemDataSource();
if (dataSource != null) {
List<Integer> excludeList = dataSource.conversationShouldHideItemsInMoreMenu(conversationInfo);
if (excludeList != null && !excludeList.isEmpty()) {
if (excludeList.contains(TUIConversationConfigClassic.HIDE)) {
mConversationPopActions.remove(hideAction);
}
if (excludeList.contains(TUIConversationConfigClassic.DELETE)) {
mConversationPopActions.remove(deleteAction);
}
}
List<PopMenuAction> conversationPopMenuItems = dataSource.conversationShouldAddNewItemsToMoreMenu(conversationInfo);
if (conversationPopMenuItems != null && !conversationPopMenuItems.isEmpty()) {
mConversationPopActions.addAll(conversationPopMenuItems);
}
}
Collections.sort(mConversationPopActions, new Comparator<PopMenuAction>() {
@Override
public int compare(PopMenuAction o1, PopMenuAction o2) {
return o2.getWeight() - o1.getWeight();
}
});
mConversationPopAdapter = new PopDialogAdapter();
mConversationPopList.setAdapter(mConversationPopAdapter);
mConversationPopAdapter.setDataSource(mConversationPopActions);
mConversationPopWindow = new PopupWindow(itemPop, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
mConversationPopWindow.setBackgroundDrawable(new ColorDrawable());
mConversationPopWindow.setOutsideTouchable(true);
int width = ConversationUtils.getListUnspecifiedWidth(mConversationPopAdapter, mConversationPopList);
mConversationPopWindow.setWidth(width);
mConversationPopWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
restoreConversationItemBackground();
}
});
int x = view.getWidth() / 2;
if (LayoutUtil.isRTL()) {
x = -x;
}
int y = -view.getHeight() / 3;
int popHeight = ScreenUtil.dip2px(45) * 3;
if (y + popHeight + view.getY() + view.getHeight() > mConversationLayout.getBottom()) {
y = y - popHeight;
}
mConversationPopWindow.showAsDropDown(view, x, y, Gravity.TOP | Gravity.START);
}
private void startFoldedConversationActivity() {
Intent intent = new Intent(getActivity(), TUIFoldedConversationActivity.class);
startActivity(intent);
}
protected List<PopMenuAction> addMoreConversationAction(ConversationInfo conversationInfo) {
List<PopMenuAction> settingsList = new ArrayList<>();
Map<String, Object> param = new HashMap<>();
param.put(TUIConstants.TUIConversation.CONTEXT, getContext());
param.put(TUIConstants.TUIConversation.KEY_CONVERSATION_INFO, conversationInfo);
List<TUIExtensionInfo> extensionList = TUICore.getExtensionList(TUIConstants.TUIConversation.Extension.ConversationPopMenu.CLASSIC_EXTENSION_ID, param);
for (TUIExtensionInfo extensionInfo : extensionList) {
String text = extensionInfo.getText();
if (!TextUtils.isEmpty(text)) {
PopMenuAction action = new PopMenuAction();
action.setActionClickListener(new PopActionClickListener() {
@Override
public void onActionClick(int index, Object data) {
TUIExtensionEventListener listener = extensionInfo.getExtensionListener();
if (listener != null) {
listener.onClicked(null);
}
}
});
action.setWeight(extensionInfo.getWeight());
action.setActionName(text);
settingsList.add(action);
}
}
return settingsList;
}
@Override
public void onDestroy() {
super.onDestroy();
TUIConversationLog.d(TAG, "onDestroy");
if (presenter != null) {
presenter.destroy();
presenter = null;
}
}
}

View File

@@ -0,0 +1,441 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.page;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuicore.TUIThemeManager;
import com.tencent.qcloud.tuicore.interfaces.TUIExtensionInfo;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.TUIConversationConstants;
import com.tencent.qcloud.tuikit.tuiconversation.TUIConversationService;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationGroupBean;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.widget.ConversationTabLayoutMediator;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.TUIConversationLog;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.ConversationGroupNotifyListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
public class TUIConversationFragmentContainer extends Fragment {
private static final String TAG = TUIConversationFragmentContainer.class.getSimpleName();
private List<ConversationGroupBean> mConversationGroupBeans = new ArrayList<>();
private View mBaseView;
private ViewGroup searchLayout;
private ViewGroup mTabLayout;
private TabLayout mConversationTabLayout;
private ViewGroup mConversationGroupSettingLayout;
private ViewPager2 mViewPager;
private ConversationTabLayoutMediator mediator;
private FragmentStateAdapter adapter;
private ConversationGroupNotifyListener conversationGroupNotifyListener;
private int selectedColor;
private int selectedPosition;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
TUIConversationLog.d(TAG, "onCreateView");
mBaseView = inflater.inflate(R.layout.conversation_base_fragment, container, false);
searchLayout = mBaseView.findViewById(R.id.conversation_search_layout);
mTabLayout = mBaseView.findViewById(R.id.conversation_tab_layout);
mConversationTabLayout = (TabLayout) mBaseView.findViewById(R.id.conversation_tabs);
mConversationGroupSettingLayout = mBaseView.findViewById(R.id.conversation_group_setting);
mViewPager = (ViewPager2) mBaseView.findViewById(R.id.converstion_viewpager);
initSearchView();
initGroupView();
return mBaseView;
}
private Fragment newConversationMarkFragment(ConversationGroupBean bean) {
Map<String, Object> param = new HashMap<>();
param.put(TUIConversationConstants.CONVERSATION_MARK_NAME_KEY, bean.getMarkType());
Object markFragment = TUICore.createObject(
TUIConstants.TUIConversationMarkPlugin.OBJECT_FACTORY_NAME, TUIConstants.TUIConversationMarkPlugin.OBJECT_CONVERSATION_MARK_FRAGMENT, param);
if (markFragment instanceof Fragment) {
return (Fragment) markFragment;
}
return null;
}
private Fragment newConversationGroupFragment(ConversationGroupBean bean) {
Map<String, Object> param = new HashMap<>();
param.put(TUIConversationConstants.CONVERSATION_GROUP_NAME_KEY, bean.getTitle());
Object groupFragment = TUICore.createObject(
TUIConstants.TUIConversationGroupPlugin.OBJECT_FACTORY_NAME, TUIConstants.TUIConversationGroupPlugin.OBJECT_CONVERSATION_GROUP_FRAGMENT, param);
if (groupFragment instanceof Fragment) {
return (Fragment) groupFragment;
}
return null;
}
private void refreshConversationGroupSort() {
Collections.sort(mConversationGroupBeans, new Comparator<ConversationGroupBean>() {
@Override
public int compare(ConversationGroupBean o1, ConversationGroupBean o2) {
return o1.getWeight() - o2.getWeight();
}
});
}
private List<ConversationGroupBean> getGroupExtensionMoreSettings() {
List<ConversationGroupBean> groupBeanList = new ArrayList<>();
List<TUIExtensionInfo> extensionList =
TUICore.getExtensionList(TUIConstants.TUIConversation.Extension.ConversationGroupBean.CLASSIC_EXTENSION_ID, null);
for (TUIExtensionInfo extensionInfo : extensionList) {
Map<String, Object> paramMap = extensionInfo.getData();
Object beanObjectList = paramMap.get(TUIConstants.TUIConversation.Extension.ConversationGroupBean.KEY_DATA);
if (beanObjectList != null && beanObjectList instanceof List) {
groupBeanList = (List<ConversationGroupBean>) beanObjectList;
}
}
return groupBeanList;
}
private List<ConversationGroupBean> getMarkExtensionMoreSettings() {
List<ConversationGroupBean> groupBeanList = new ArrayList<>();
List<TUIExtensionInfo> extensionList =
TUICore.getExtensionList(TUIConstants.TUIConversation.Extension.ConversationMarkBean.CLASSIC_EXTENSION_ID, null);
for (TUIExtensionInfo extensionInfo : extensionList) {
Map<String, Object> paramMap = extensionInfo.getData();
Object beanObjectList = paramMap.get(TUIConstants.TUIConversation.Extension.ConversationMarkBean.KEY_DATA);
if (beanObjectList != null && beanObjectList instanceof List) {
groupBeanList = (List<ConversationGroupBean>) beanObjectList;
}
}
return groupBeanList;
}
private void refreshGroupView(boolean hide) {
if (hide) {
mTabLayout.setVisibility(View.GONE);
} else {
mTabLayout.setVisibility(View.VISIBLE);
HashMap<String, Object> param = new HashMap<>();
param.put(TUIConstants.TUIConversationGroupPlugin.CONTEXT, getContext());
TUICore.raiseExtension(TUIConstants.TUIConversationGroupPlugin.EXTENSION_GROUP_SETTING_MENU, mConversationGroupSettingLayout, param);
}
}
private void initGroupView() {
mConversationGroupBeans.clear();
List<ConversationGroupBean> groupBeanList = getGroupExtensionMoreSettings();
List<ConversationGroupBean> markBeanList = getMarkExtensionMoreSettings();
if (groupBeanList != null && !groupBeanList.isEmpty()) {
mConversationGroupBeans.addAll(groupBeanList);
}
if (markBeanList != null && !markBeanList.isEmpty()) {
mConversationGroupBeans.addAll(markBeanList);
}
if (mConversationGroupBeans.isEmpty()) {
refreshGroupView(true);
} else {
refreshGroupView(false);
}
ConversationGroupBean bean = new ConversationGroupBean();
bean.setTitle(getString(R.string.conversation_page_all));
bean.setWeight(ConversationGroupBean.CONVERSATION_ALL_GROUP_WEIGHT);
bean.setGroupType(ConversationGroupBean.CONVERSATION_GROUP_TYPE_DEFAULT);
if (!mConversationGroupBeans.contains(bean)) {
mConversationGroupBeans.add(bean);
}
refreshConversationGroupSort();
mViewPager.setOffscreenPageLimit(3);
adapter = new FragmentStateAdapter(getChildFragmentManager(), getLifecycle()) {
@NonNull
@Override
public Fragment createFragment(int position) {
ConversationGroupBean bean = mConversationGroupBeans.get(position);
if (bean.getGroupType() == ConversationGroupBean.CONVERSATION_GROUP_TYPE_DEFAULT) {
return TUIConversationFragment.newInstance();
} else if (bean.getGroupType() == ConversationGroupBean.CONVERSATION_GROUP_TYPE_GROUP) {
return newConversationGroupFragment(bean);
} else if (bean.getGroupType() == ConversationGroupBean.CONVERSATION_GROUP_TYPE_MARK) {
return newConversationMarkFragment(bean);
} else {
return TUIConversationFragment.newInstance();
}
}
@Override
public int getItemCount() {
return mConversationGroupBeans.size();
}
@Override
public long getItemId(int position) {
return mConversationGroupBeans.get(position).hashCode();
}
@Override
public boolean containsItem(long itemId) {
for (ConversationGroupBean bean : mConversationGroupBeans) {
if (itemId == bean.hashCode()) {
return true;
}
}
return false;
}
};
mViewPager.setAdapter(adapter);
selectedPosition = 0;
mViewPager.setCurrentItem(selectedPosition);
mViewPager.registerOnPageChangeCallback(changeCallback);
selectedColor = getResources().getColor(TUIThemeManager.getAttrResId(getContext(), R.attr.conversation_tab_selected));
mConversationTabLayout.setTabTextColors(getResources().getColor(com.tencent.qcloud.tuikit.timcommon.R.color.black), selectedColor);
adapter.notifyDataSetChanged();
// mViewPager.setUserInputEnabled(false);
mediator =
new ConversationTabLayoutMediator(mConversationTabLayout, mViewPager, true, false, new ConversationTabLayoutMediator.TabConfigurationStrategy() {
@Override
public void onConfigureTab(@NonNull TabLayout.Tab tab, int position) {
TUIConversationLog.d(TAG, "onConfigureTab position" + position);
View layoutView = LayoutInflater.from(getContext()).inflate(R.layout.conversation_group_tab_item, null, false);
TextView titileView = layoutView.findViewById(R.id.tab_title);
TextView unreadView = layoutView.findViewById(R.id.tab_unread);
titileView.setText(mConversationGroupBeans.get(position).getTitle());
long count = mConversationGroupBeans.get(position).getUnReadCount();
if (count == 0) {
unreadView.setText("");
} else if (count > 99) {
unreadView.setText("99+");
} else {
unreadView.setText(String.valueOf(count));
}
tab.setCustomView(layoutView);
if (position == selectedPosition) {
titileView.setTextColor(selectedColor);
}
}
});
mediator.attach();
conversationGroupNotifyListener = new ConversationGroupNotifyListener() {
@Override
public void notifyGroupsAdd(List<ConversationGroupBean> beans) {
addRefreshData(beans, false);
}
@Override
public void notifyMarkGroupsAdd(List<ConversationGroupBean> beans) {
addRefreshData(beans, true);
}
@Override
public void notifyGroupAdd(ConversationGroupBean bean) {
TUIConversationLog.d(TAG, "notifyGroupAdd");
if (!mConversationGroupBeans.contains(bean)) {
mConversationGroupBeans.add(bean);
if (bean.getGroupType() == ConversationGroupBean.CONVERSATION_GROUP_TYPE_MARK) {
refreshConversationGroupSort();
adapter.notifyDataSetChanged();
} else {
int notifyIndex = mConversationGroupBeans.size() - 1;
adapter.notifyItemInserted(notifyIndex);
}
} else {
TUIConversationLog.d(TAG, "notifyGroupAdd contains groupName = " + bean.getTitle());
}
}
@Override
public void notifyGroupDelete(String groupName) {
TUIConversationLog.d(TAG, "notifyGroupDelete");
ListIterator<ConversationGroupBean> iterator = mConversationGroupBeans.listIterator();
int index = 0;
while (iterator.hasNext()) {
ConversationGroupBean next = iterator.next();
if (next.getTitle().equals(groupName)) {
iterator.remove();
adapter.notifyItemRangeRemoved(index, 1);
break;
} else {
index++;
}
}
}
@Override
public void notifyGroupRename(String oldName, String newName) {
TUIConversationLog.d(TAG, "notifyGroupRename");
ListIterator<ConversationGroupBean> iterator = mConversationGroupBeans.listIterator();
int index = 0;
while (iterator.hasNext()) {
ConversationGroupBean next = iterator.next();
if (next.getTitle().equals(oldName)) {
next.setTitle(newName);
adapter.notifyItemChanged(index);
break;
} else {
index++;
}
}
}
@Override
public void notifyGroupUnreadMessageCountChanged(String groupName, long totalUnreadCount) {
TUIConversationLog.d(TAG, "notifyGroupUnreadMessageCountChanged groupName =" + groupName + "count =" + totalUnreadCount);
ListIterator<ConversationGroupBean> iterator = mConversationGroupBeans.listIterator();
int index = 0;
while (iterator.hasNext()) {
ConversationGroupBean next = iterator.next();
if (next.getTitle().equals(groupName)) {
next.setUnReadCount(totalUnreadCount);
refreshTabUnreadCount(index, totalUnreadCount);
break;
} else {
index++;
}
}
}
};
TUIConversationService.getInstance().setConversationGroupNotifyListener(conversationGroupNotifyListener);
}
private void refreshTabUnreadCount(int position, long unreadCount) {
TabLayout.Tab tab = mConversationTabLayout.getTabAt(position);
if (tab != null) {
View layoutView = tab.getCustomView();
if (layoutView != null) {
TextView unreadView = layoutView.findViewById(R.id.tab_unread);
if (unreadCount == 0) {
unreadView.setText("");
} else if (unreadCount > 99) {
unreadView.setText("99+");
} else {
unreadView.setText(String.valueOf(unreadCount));
}
}
int selectPositon = mConversationTabLayout.getSelectedTabPosition();
if (selectPositon >= 0) {
TabLayout.Tab selectedTab = mConversationTabLayout.getTabAt(selectPositon);
if (selectedTab != null) {
selectedTab.select();
}
}
}
}
private void addRefreshData(List<ConversationGroupBean> beans, boolean isMark) {
List<ConversationGroupBean> markBeans = new ArrayList<>();
List<ConversationGroupBean> groupBeans = new ArrayList<>();
for (ConversationGroupBean bean : mConversationGroupBeans) {
if (bean.getGroupType() == ConversationGroupBean.CONVERSATION_GROUP_TYPE_MARK) {
markBeans.add(bean);
} else if (bean.getGroupType() == ConversationGroupBean.CONVERSATION_GROUP_TYPE_GROUP) {
groupBeans.add(bean);
}
}
if (beans == null || beans.isEmpty()) {
if (isMark) {
mConversationGroupBeans.removeAll(markBeans);
} else {
mConversationGroupBeans.removeAll(groupBeans);
}
} else {
mConversationGroupBeans.clear();
if (isMark) {
mConversationGroupBeans.addAll(groupBeans);
mConversationGroupBeans.addAll(beans);
} else {
mConversationGroupBeans.addAll(beans);
mConversationGroupBeans.addAll(markBeans);
}
}
if (mConversationGroupBeans.isEmpty()) {
refreshGroupView(true);
} else {
refreshGroupView(false);
}
ConversationGroupBean bean = new ConversationGroupBean();
bean.setTitle(getString(R.string.conversation_page_all));
bean.setWeight(ConversationGroupBean.CONVERSATION_ALL_GROUP_WEIGHT);
bean.setGroupType(ConversationGroupBean.CONVERSATION_GROUP_TYPE_DEFAULT);
if (!mConversationGroupBeans.contains(bean)) {
mConversationGroupBeans.add(bean);
}
refreshConversationGroupSort();
adapter.notifyDataSetChanged();
}
private ViewPager2.OnPageChangeCallback changeCallback = new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageSelected(int position) {
TUIConversationLog.d(TAG, "onPageSelected position" + position);
selectedPosition = position;
int tabCount = mConversationTabLayout.getTabCount();
for (int i = 0; i < tabCount; i++) {
TabLayout.Tab tab = mConversationTabLayout.getTabAt(i);
View layoutView = tab.getCustomView();
TextView titileView = layoutView.findViewById(R.id.tab_title);
if (tab.getPosition() == position) {
titileView.setTextColor(selectedColor);
} else {
titileView.setTextColor(getResources().getColor(com.tencent.qcloud.tuikit.timcommon.R.color.black));
}
}
}
};
public void initSearchView() {
TUICore.raiseExtension(TUIConstants.TUIConversation.Extension.ConversationListHeader.CLASSIC_EXTENSION_ID, searchLayout, null);
}
@Override
public void onResume() {
TUIConversationLog.d(TAG, "onResume");
super.onResume();
}
@Override
public void onDestroy() {
TUIConversationLog.d(TAG, "onDestroy");
mediator.detach();
mViewPager.unregisterOnPageChangeCallback(changeCallback);
mConversationGroupBeans.clear();
TUIConversationService.getInstance().setConversationGroupNotifyListenerNull();
conversationGroupNotifyListener = null;
super.onDestroy();
}
}

View File

@@ -0,0 +1,23 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.page;
import android.os.Bundle;
import androidx.annotation.Nullable;
import com.tencent.qcloud.tuikit.timcommon.component.activities.BaseLightActivity;
import com.tencent.qcloud.tuikit.tuiconversation.R;
public class TUIFoldedConversationActivity extends BaseLightActivity {
private TUIFoldedConversationFragment mTUIFoldedConversationFragment;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.conversation_folded_activity);
init();
}
private void init() {
mTUIFoldedConversationFragment = new TUIFoldedConversationFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.empty_view, mTUIFoldedConversationFragment).commitAllowingStateLoss();
}
}

View File

@@ -0,0 +1,273 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.page;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.PopupWindow;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuicore.interfaces.TUIExtensionEventListener;
import com.tencent.qcloud.tuicore.interfaces.TUIExtensionInfo;
import com.tencent.qcloud.tuikit.timcommon.component.TitleBarLayout;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopActionClickListener;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopDialogAdapter;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopMenuAction;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.ITitleBarLayout;
import com.tencent.qcloud.tuikit.timcommon.util.ScreenUtil;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces.OnConversationAdapterListener;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.util.TUIConversationUtils;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.widget.FoldedConversationLayout;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.ConversationUtils;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationFoldPresenter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TUIFoldedConversationFragment extends Fragment {
private View mBaseView;
private TitleBarLayout mTitleBarLayout;
private FoldedConversationLayout mFoldedLayout;
private PopDialogAdapter mConversationPopAdapter;
private ListView mConversationPopList;
private PopupWindow mConversationPopWindow;
private String popWindowConversationId;
private List<PopMenuAction> mConversationPopActions = new ArrayList<>();
private ConversationFoldPresenter presenter;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mBaseView = inflater.inflate(R.layout.conversation_folded_fragment, container, false);
initView();
return mBaseView;
}
private void initView() {
mFoldedLayout = mBaseView.findViewById(R.id.folded_conversation_layout);
mTitleBarLayout = mFoldedLayout.getTitleBar();
mTitleBarLayout.setTitle(getResources().getString(R.string.folded_group_chat), ITitleBarLayout.Position.MIDDLE);
mTitleBarLayout.setOnLeftClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().finish();
}
});
presenter = new ConversationFoldPresenter();
presenter.initListener();
mFoldedLayout.setPresenter(presenter);
mFoldedLayout.initDefault();
mFoldedLayout.getConversationList().setOnConversationAdapterListener(new OnConversationAdapterListener() {
@Override
public void onItemClick(View view, int viewType, ConversationInfo conversationInfo) {
TUIConversationUtils.startChatActivity(conversationInfo);
}
@Override
public void onItemLongClick(View view, ConversationInfo conversationInfo) {
showItemPopMenu(view, conversationInfo);
}
@Override
public void onConversationChanged(List<ConversationInfo> dataSource) {
if (dataSource == null) {
return;
}
ConversationInfo conversationInfo = dataSource.get(0);
if (conversationInfo == null) {
return;
}
if (!TextUtils.isEmpty(popWindowConversationId) && popWindowConversationId.equals(conversationInfo.getConversationId())) {
if (mConversationPopWindow != null) {
mConversationPopWindow.dismiss();
}
}
}
});
restoreConversationItemBackground();
}
private void initPopMenuAction() {
PopMenuAction action = new PopMenuAction();
action.setActionName(getResources().getString(R.string.not_display));
action.setWeight(800);
action.setActionClickListener(new PopActionClickListener() {
@Override
public void onActionClick(int index, Object data) {
ConversationInfo conversationInfo = (ConversationInfo) data;
mFoldedLayout.markConversationHidden((ConversationInfo) data);
}
});
List<PopMenuAction> conversationPopActions = new ArrayList<PopMenuAction>();
conversationPopActions.add(action);
action = new PopMenuAction();
action.setActionClickListener(new PopActionClickListener() {
@Override
public void onActionClick(int index, Object data) {
mFoldedLayout.deleteConversation((ConversationInfo) data);
}
});
action.setActionName(getResources().getString(R.string.chat_delete));
action.setWeight(700);
conversationPopActions.add(action);
mConversationPopActions.clear();
mConversationPopActions.addAll(conversationPopActions);
}
private void restoreConversationItemBackground() {
if (mFoldedLayout.getConversationList().getAdapter() != null && mFoldedLayout.getConversationList().getAdapter().isClick()) {
mFoldedLayout.getConversationList().getAdapter().setClick(false);
mFoldedLayout.getConversationList().getAdapter().notifyItemChanged(mFoldedLayout.getConversationList().getAdapter().getCurrentPosition());
}
}
private void addMarkUnreadPopMenuAction(boolean markUnread) {
PopMenuAction action = new PopMenuAction();
action.setActionClickListener(new PopActionClickListener() {
@Override
public void onActionClick(int index, Object data) {
mFoldedLayout.markConversationUnread((ConversationInfo) data, markUnread);
}
});
if (markUnread) {
action.setActionName(getResources().getString(R.string.mark_unread));
} else {
action.setActionName(getResources().getString(R.string.mark_read));
}
action.setWeight(900);
mConversationPopActions.add(0, action);
}
private void showItemPopMenu(View view, final ConversationInfo conversationInfo) {
initPopMenuAction();
if (conversationInfo.getUnRead() > 0) {
addMarkUnreadPopMenuAction(false);
} else {
if (conversationInfo.isMarkUnread()) {
addMarkUnreadPopMenuAction(false);
} else {
addMarkUnreadPopMenuAction(true);
}
}
mConversationPopActions.addAll(addMoreConversationAction(conversationInfo));
Collections.sort(mConversationPopActions, new Comparator<PopMenuAction>() {
@Override
public int compare(PopMenuAction o1, PopMenuAction o2) {
return o2.getWeight() - o1.getWeight();
}
});
View itemPop = LayoutInflater.from(getActivity()).inflate(R.layout.conversation_pop_menu_layout, null);
mConversationPopList = itemPop.findViewById(R.id.pop_menu_list);
mConversationPopList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
PopMenuAction action = mConversationPopActions.get(position);
if (action.getActionClickListener() != null) {
action.getActionClickListener().onActionClick(position, conversationInfo);
}
mConversationPopWindow.dismiss();
restoreConversationItemBackground();
}
});
for (int i = 0; i < mConversationPopActions.size(); i++) {
PopMenuAction action = mConversationPopActions.get(i);
if (conversationInfo.isTop()) {
if (action.getActionName().equals(getResources().getString(R.string.chat_top))) {
action.setActionName(getResources().getString(R.string.quit_chat_top));
}
} else {
if (action.getActionName().equals(getResources().getString(R.string.quit_chat_top))) {
action.setActionName(getResources().getString(R.string.chat_top));
}
}
}
mConversationPopAdapter = new PopDialogAdapter();
mConversationPopList.setAdapter(mConversationPopAdapter);
mConversationPopAdapter.setDataSource(mConversationPopActions);
mConversationPopWindow = new PopupWindow(itemPop, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
mConversationPopWindow.setBackgroundDrawable(new ColorDrawable());
mConversationPopWindow.setOutsideTouchable(true);
popWindowConversationId = conversationInfo.getConversationId();
int width = ConversationUtils.getListUnspecifiedWidth(mConversationPopAdapter, mConversationPopList);
mConversationPopWindow.setWidth(width);
mConversationPopWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
restoreConversationItemBackground();
popWindowConversationId = "";
}
});
int x = view.getWidth() / 2;
int y = -view.getHeight() / 3;
int popHeight = ScreenUtil.dip2px(45) * 3;
if (y + popHeight + view.getY() + view.getHeight() > mFoldedLayout.getBottom()) {
y = y - popHeight;
}
mConversationPopWindow.showAsDropDown(view, x, y, Gravity.TOP | Gravity.START);
}
@Override
public void onDestroy() {
super.onDestroy();
if (presenter != null) {
presenter.destroy();
presenter = null;
}
}
protected List<PopMenuAction> addMoreConversationAction(ConversationInfo conversationInfo) {
List<PopMenuAction> settingsList = new ArrayList<>();
Map<String, Object> param = new HashMap<>();
param.put(TUIConstants.TUIConversation.CONTEXT, getContext());
param.put(TUIConstants.TUIConversation.KEY_CONVERSATION_INFO, conversationInfo);
List<TUIExtensionInfo> extensionList = TUICore.getExtensionList(TUIConstants.TUIConversation.Extension.ConversationPopMenu.CLASSIC_EXTENSION_ID, param);
for (TUIExtensionInfo extensionInfo : extensionList) {
String text = extensionInfo.getText();
if (!TextUtils.isEmpty(text)) {
PopMenuAction action = new PopMenuAction();
action.setActionClickListener(new PopActionClickListener() {
@Override
public void onActionClick(int index, Object data) {
TUIExtensionEventListener listener = extensionInfo.getExtensionListener();
if (listener != null) {
listener.onClicked(null);
}
}
});
action.setWeight(extensionInfo.getWeight());
action.setActionName(text);
settingsList.add(action);
}
}
return settingsList;
}
}

View File

@@ -0,0 +1,39 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.page;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.Nullable;
import com.tencent.qcloud.tuikit.timcommon.component.activities.BaseLightActivity;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.TUIConversationLog;
public class TUIForwardSelectActivity extends BaseLightActivity {
private static final String TAG = TUIForwardSelectActivity.class.getSimpleName();
private TUIForwardSelectFragment mTUIForwardSelectFragment;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.conversation_forward_activity_layout);
init();
}
@Override
protected void onNewIntent(Intent intent) {
TUIConversationLog.i(TAG, "onNewIntent");
super.onNewIntent(intent);
}
@Override
protected void onResume() {
TUIConversationLog.i(TAG, "onResume");
super.onResume();
}
private void init() {
mTUIForwardSelectFragment = new TUIForwardSelectFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.empty_view, mTUIForwardSelectFragment).commitAllowingStateLoss();
}
}

View File

@@ -0,0 +1,336 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.page;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.activity.result.ActivityResult;
import androidx.activity.result.ActivityResultCallback;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuikit.timcommon.component.CustomLinearLayoutManager;
import com.tencent.qcloud.tuikit.timcommon.component.TitleBarLayout;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.ITitleBarLayout;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.TUIConversationConstants;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces.OnConversationAdapterListener;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.widget.ConversationListLayout;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.widget.ForwardConversationSelectorAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.widget.ForwardSelectLayout;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.TUIConversationLog;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationPresenter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class TUIForwardSelectFragment extends Fragment {
private View mBaseView;
private TitleBarLayout mTitleBarLayout;
private ForwardSelectLayout mForwardLayout;
private RecyclerView mForwardSelectlistView;
private ForwardConversationSelectorAdapter mAdapter;
private List<ConversationInfo> mDataSource = new ArrayList<>();
private List<ConversationInfo> mContactDataSource = new ArrayList<>();
private List<ConversationInfo> mAllSelectedConversations = new ArrayList<>();
private RelativeLayout mForwardSelectlistViewLayout;
private TextView mSureView;
private ConversationPresenter presenter;
private static final String TAG = TUIForwardSelectFragment.class.getSimpleName();
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
mBaseView = inflater.inflate(R.layout.conversation_forward_fragment, container, false);
return mBaseView;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
mForwardLayout = view.findViewById(R.id.forward_conversation_layout);
presenter = new ConversationPresenter();
mForwardLayout.setPresenter(presenter);
mForwardLayout.initDefault();
customizeConversation();
mForwardLayout.getConversationList().setOnConversationAdapterListener(new OnConversationAdapterListener() {
@Override
public void onItemClick(View view, int viewType, ConversationInfo conversationInfo) {
if (viewType == ConversationInfo.TYPE_RECENT_LABEL) {
return;
} else if (viewType == ConversationInfo.TYPE_FORWAR_SELECT) {
if (mTitleBarLayout.getLeftTitle().getText().equals(getString(R.string.titlebar_cancle))) {
selectContactsToForward();
} else if (mTitleBarLayout.getLeftTitle().getText().equals(getString(R.string.titlebar_close))) {
createNewConversationToForward();
} else {
TUIConversationLog.d(TAG, "Titlebar exception");
}
} else {
if (mTitleBarLayout.getLeftTitle().getText().equals(getString(R.string.titlebar_cancle))) {
mDataSource = mForwardLayout.getConversationList().getAdapter().getSelectedItem();
checkRepeat();
refreshSelectConversations();
} else if (mTitleBarLayout.getLeftTitle().getText().equals(getString(R.string.titlebar_close))) {
forwardMessages(conversationInfo);
} else {
forwardMessages(conversationInfo);
}
}
}
@Override
public void onItemLongClick(View view, ConversationInfo conversationInfo) {}
@Override
public void onConversationChanged(List<ConversationInfo> dataSource) {}
});
mForwardSelectlistViewLayout = view.findViewById(R.id.forward_select_list_layout);
mForwardSelectlistViewLayout.setVisibility(View.VISIBLE);
mForwardSelectlistView = view.findViewById(R.id.forward_select_list);
mForwardSelectlistView.setLayoutManager(new CustomLinearLayoutManager(getContext(), CustomLinearLayoutManager.HORIZONTAL, false));
mAdapter = new ForwardConversationSelectorAdapter(this.getContext());
mForwardSelectlistView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(new ForwardConversationSelectorAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int position) {
boolean needFresh = false;
if (mDataSource != null && mDataSource.size() != 0) {
if (position < mDataSource.size()) {
mDataSource.remove(position);
mForwardLayout.getConversationList().getAdapter().setSelectConversations(mDataSource);
needFresh = true;
}
}
if (!needFresh) {
if (mContactDataSource != null && mContactDataSource.size() != 0) {
int dataSourcePosition = mDataSource == null ? 0 : mDataSource.size();
if (position - dataSourcePosition < mContactDataSource.size()) {
mContactDataSource.remove(position - dataSourcePosition);
needFresh = true;
}
}
}
if (needFresh) {
refreshSelectConversations();
}
}
});
mSureView = view.findViewById(R.id.btn_msg_ok);
mSureView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (getActivity() != null) {
HashMap<String, Boolean> conversationMap = new HashMap<>();
if (mDataSource != null && mDataSource.size() != 0) {
for (int i = 0; i < mDataSource.size(); i++) {
conversationMap.put(mDataSource.get(i).getId(), mDataSource.get(i).isGroup());
}
}
if (mContactDataSource != null && mContactDataSource.size() != 0) {
for (int i = 0; i < mContactDataSource.size(); i++) {
conversationMap.put(mContactDataSource.get(i).getId(), mContactDataSource.get(i).isGroup());
}
}
Intent intent = new Intent();
intent.putExtra(TUIConversationConstants.FORWARD_SELECT_CONVERSATION_KEY, conversationMap);
getActivity().setResult(TUIConversationConstants.FORWARD_SELECT_ACTIVTY_CODE, intent);
getActivity().finish();
}
}
});
refreshSelectConversations();
initTitleAction();
}
private void createNewConversationToForward() {
Bundle param = new Bundle();
param.putInt(TUIConversationConstants.GroupType.TYPE, TUIConversationConstants.GroupType.PUBLIC);
param.putBoolean(TUIConversationConstants.FORWARD_CREATE_NEW_CHAT, true);
TUICore.startActivityForResult(TUIForwardSelectFragment.this, "ForwardSelectGroupActivity", param, new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (getActivity() != null) {
getActivity().setResult(TUIConversationConstants.FORWARD_SELECT_ACTIVTY_CODE, result.getData());
getActivity().finish();
}
}
});
}
private void selectContactsToForward() {
Bundle param = new Bundle();
param.putInt(TUIConversationConstants.GroupType.TYPE, TUIConversationConstants.GroupType.PUBLIC);
param.putBoolean(TUIConversationConstants.FORWARD_CREATE_NEW_CHAT, false);
TUICore.startActivityForResult(TUIForwardSelectFragment.this, "ForwardSelectGroupActivity", param, new ActivityResultCallback<ActivityResult>() {
@Override
public void onActivityResult(ActivityResult result) {
if (result.getData() == null) {
return;
}
HashMap<String, String> conversationMap =
(HashMap<String, String>) result.getData().getSerializableExtra(TUIConversationConstants.FORWARD_SELECT_CONVERSATION_KEY);
if (conversationMap == null || conversationMap.isEmpty()) {
mContactDataSource.clear();
refreshSelectConversations();
return;
}
mContactDataSource.clear();
for (Map.Entry<String, String> entry : conversationMap.entrySet()) {
ConversationInfo conversationInfo = new ConversationInfo();
List<Object> iconList = new ArrayList<>();
iconList.add(entry.getValue());
conversationInfo.setIconUrlList(iconList);
conversationInfo.setId(entry.getKey());
conversationInfo.setGroup(false);
mContactDataSource.add(conversationInfo);
}
checkRepeat();
refreshSelectConversations();
}
});
}
private void refreshSelectConversations() {
mAllSelectedConversations.clear();
mDataSource = mForwardLayout.getConversationList().getAdapter().getSelectedItem();
if (mDataSource != null && mDataSource.size() != 0) {
mAllSelectedConversations.addAll(mDataSource);
}
if (mContactDataSource != null && mContactDataSource.size() != 0) {
mAllSelectedConversations.addAll(mContactDataSource);
}
mAdapter.setDataSource(mAllSelectedConversations);
if (mAllSelectedConversations == null || mAllSelectedConversations.size() == 0) {
mSureView.setText(getString(com.tencent.qcloud.tuicore.R.string.sure));
mSureView.setVisibility(View.GONE);
mForwardSelectlistViewLayout.setVisibility(View.GONE);
} else {
mForwardSelectlistViewLayout.setVisibility(View.VISIBLE);
mSureView.setVisibility(View.VISIBLE);
mSureView.setText(getString(com.tencent.qcloud.tuicore.R.string.sure) + "(" + mAllSelectedConversations.size() + ")");
}
}
private void forwardMessages(final ConversationInfo conversationInfo) {
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("");
builder.setMessage(getString(R.string.forward_alert_title));
builder.setCancelable(true);
builder.setPositiveButton(getString(com.tencent.qcloud.tuicore.R.string.sure), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (getActivity() != null) {
HashMap<String, Boolean> chatInfo = new HashMap<>();
chatInfo.put(conversationInfo.getId(), conversationInfo.isGroup());
Intent intent = new Intent();
intent.putExtra(TUIConversationConstants.FORWARD_SELECT_CONVERSATION_KEY, chatInfo);
getActivity().setResult(TUIConversationConstants.FORWARD_SELECT_ACTIVTY_CODE, intent);
getActivity().finish();
}
dialog.dismiss();
}
});
builder.setNegativeButton(getString(com.tencent.qcloud.tuicore.R.string.cancel), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
private void customizeConversation() {
mTitleBarLayout = mForwardLayout.getTitleBar();
mTitleBarLayout.setTitle("", TitleBarLayout.Position.MIDDLE);
mTitleBarLayout.getLeftGroup().setVisibility(View.VISIBLE);
mTitleBarLayout.getRightGroup().setVisibility(View.VISIBLE);
mTitleBarLayout.setTitle(getString(R.string.titlebar_close), ITitleBarLayout.Position.LEFT);
mTitleBarLayout.setTitle(getString(R.string.titlebar_mutiselect), TitleBarLayout.Position.RIGHT);
mTitleBarLayout.getLeftIcon().setVisibility(View.GONE);
mTitleBarLayout.getRightIcon().setVisibility(View.GONE);
}
private void initTitleAction() {
mForwardLayout.getTitleBar().setOnLeftClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mTitleBarLayout.getLeftTitle().getText().equals(getString(R.string.titlebar_cancle))) {
mTitleBarLayout.getRightGroup().setVisibility(View.VISIBLE);
mTitleBarLayout.setTitle(getString(R.string.titlebar_close), TitleBarLayout.Position.LEFT);
mTitleBarLayout.setTitle(getString(R.string.titlebar_mutiselect), TitleBarLayout.Position.RIGHT);
ConversationListLayout listLayout = mForwardLayout.getConversationList();
listLayout.getAdapter().setShowMultiSelectCheckBox(false);
listLayout.getAdapter().notifyDataSetChanged();
mForwardSelectlistViewLayout.setVisibility(View.GONE);
mAdapter.setDataSource(null);
mAllSelectedConversations.clear();
} else if (mTitleBarLayout.getLeftTitle().getText().equals(getString(R.string.titlebar_close))) {
getActivity().finish();
} else {
TUIConversationLog.d(TAG, "Titlebar exception");
}
}
});
mForwardLayout.getTitleBar().setOnRightClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mTitleBarLayout.getRightGroup().setVisibility(View.GONE);
mTitleBarLayout.setTitle(getString(R.string.titlebar_cancle), TitleBarLayout.Position.LEFT);
ConversationListLayout listLayout = mForwardLayout.getConversationList();
listLayout.getAdapter().setShowMultiSelectCheckBox(true);
listLayout.getAdapter().notifyDataSetChanged();
}
});
}
private void checkRepeat() {
Iterator<ConversationInfo> iterator = mContactDataSource.iterator();
while (iterator.hasNext()) {
ConversationInfo conversationInfo = iterator.next();
if (mDataSource != null && mDataSource.size() != 0) {
for (int i = 0; i < mDataSource.size(); i++) {
if (conversationInfo.getId().equals(mDataSource.get(i).getId())) {
iterator.remove();
break;
}
}
}
}
}
}

View File

@@ -0,0 +1,34 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.util;
import android.os.Bundle;
import com.tencent.imsdk.v2.V2TIMConversation;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import java.io.Serializable;
public class TUIConversationUtils {
public static void startChatActivity(ConversationInfo conversationInfo) {
Bundle param = new Bundle();
param.putInt(TUIConstants.TUIChat.CHAT_TYPE, conversationInfo.isGroup() ? V2TIMConversation.V2TIM_GROUP : V2TIMConversation.V2TIM_C2C);
param.putString(TUIConstants.TUIChat.CHAT_ID, conversationInfo.getId());
param.putString(TUIConstants.TUIChat.CHAT_NAME, conversationInfo.getTitle());
if (conversationInfo.getDraft() != null) {
param.putString(TUIConstants.TUIChat.DRAFT_TEXT, conversationInfo.getDraft().getDraftText());
param.putLong(TUIConstants.TUIChat.DRAFT_TIME, conversationInfo.getDraft().getDraftTime());
}
param.putBoolean(TUIConstants.TUIChat.IS_TOP_CHAT, conversationInfo.isTop());
param.putString(TUIConstants.TUIChat.FACE_URL, conversationInfo.getIconPath());
if (conversationInfo.isGroup()) {
param.putString(TUIConstants.TUIChat.GROUP_TYPE, conversationInfo.getGroupType());
param.putSerializable(TUIConstants.TUIChat.AT_INFO_LIST, (Serializable) conversationInfo.getGroupAtInfoList());
}
if (conversationInfo.isGroup()) {
TUICore.startActivity(TUIConstants.TUIChat.GROUP_CHAT_ACTIVITY_NAME, param);
} else {
TUICore.startActivity(TUIConstants.TUIChat.C2C_CHAT_ACTIVITY_NAME, param);
}
}
}

View File

@@ -0,0 +1,23 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.widget;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
public abstract class ConversationBaseHolder extends RecyclerView.ViewHolder {
protected View rootView;
protected ConversationListAdapter mAdapter;
public ConversationBaseHolder(View itemView) {
super(itemView);
rootView = itemView;
}
public void setAdapter(RecyclerView.Adapter adapter) {
mAdapter = (ConversationListAdapter) adapter;
}
public abstract void layoutViews(ConversationInfo conversationInfo, int position);
}

View File

@@ -0,0 +1,317 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.widget;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.text.Html;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.tencent.qcloud.tuicore.TUIThemeManager;
import com.tencent.qcloud.tuikit.timcommon.bean.TUIMessageBean;
import com.tencent.qcloud.tuikit.timcommon.component.UnreadCountTextView;
import com.tencent.qcloud.tuikit.timcommon.component.face.FaceManager;
import com.tencent.qcloud.tuikit.timcommon.util.DateTimeUtil;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.bean.DraftInfo;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.TUIConversationLog;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.TUIConversationUtils;
import com.tencent.qcloud.tuikit.tuiconversation.config.classicui.TUIConversationConfigClassic;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationPresenter;
import java.util.Date;
import java.util.HashMap;
public class ConversationCommonHolder extends ConversationBaseHolder {
public ConversationIconView conversationIconView;
protected LinearLayout leftItemLayout;
protected TextView titleText;
protected TextView messageText;
protected TextView timelineText;
protected UnreadCountTextView unreadText;
protected TextView atAllTv;
protected TextView atMeTv;
protected TextView draftTv;
protected TextView riskTv;
protected TextView foldGroupNameTv;
protected TextView foldGroupNameDivider;
protected ImageView disturbView;
protected ImageView markBannerView;
protected CheckBox multiSelectCheckBox;
protected RelativeLayout messageStatusLayout;
public ImageView messageSending;
public ImageView messageFailed;
private boolean isForwardMode = false;
protected View userStatusView;
private boolean showFoldedStyle = true;
private ConversationInfo currentConversation;
public ConversationCommonHolder(View itemView) {
super(itemView);
leftItemLayout = rootView.findViewById(R.id.item_left);
conversationIconView = rootView.findViewById(R.id.conversation_icon);
titleText = rootView.findViewById(R.id.conversation_title);
messageText = rootView.findViewById(R.id.conversation_last_msg);
timelineText = rootView.findViewById(R.id.conversation_time);
unreadText = rootView.findViewById(R.id.conversation_unread);
foldGroupNameTv = rootView.findViewById(R.id.fold_group_name);
foldGroupNameDivider = rootView.findViewById(R.id.fold_group_name_divider);
atAllTv = rootView.findViewById(R.id.conversation_at_all);
atMeTv = rootView.findViewById(R.id.conversation_at_me);
draftTv = rootView.findViewById(R.id.conversation_draft);
riskTv = rootView.findViewById(R.id.conversation_risk);
disturbView = rootView.findViewById(R.id.not_disturb);
markBannerView = rootView.findViewById(R.id.mark_banner);
multiSelectCheckBox = rootView.findViewById(R.id.select_checkbox);
messageStatusLayout = rootView.findViewById(R.id.message_status_layout);
messageFailed = itemView.findViewById(R.id.message_status_failed);
messageSending = itemView.findViewById(R.id.message_status_sending);
userStatusView = itemView.findViewById(R.id.user_status);
}
public void setForwardMode(boolean forwardMode) {
isForwardMode = forwardMode;
}
public void setShowFoldedStyle(boolean showFoldedStyle) {
this.showFoldedStyle = showFoldedStyle;
}
public void layoutViews(ConversationInfo conversation, int position) {
currentConversation = conversation;
if (showFoldedStyle && conversation.isMarkFold()) {
titleText.setText(R.string.folded_group_chat);
timelineText.setVisibility(View.GONE);
foldGroupNameTv.setVisibility(View.VISIBLE);
foldGroupNameDivider.setVisibility(View.VISIBLE);
foldGroupNameTv.setText(conversation.getTitle());
} else {
titleText.setText(conversation.getTitle());
foldGroupNameTv.setVisibility(View.GONE);
foldGroupNameDivider.setVisibility(View.GONE);
}
messageText.setText("");
timelineText.setText("");
setLastMessageAndStatus(conversation);
if (!mAdapter.hasItemUnreadDot()) {
unreadText.setVisibility(View.GONE);
}
conversationIconView.setShowFoldedStyle(showFoldedStyle);
conversationIconView.setConversation(conversation);
if (conversation.isShowDisturbIcon() && !isForwardMode) {
if (showFoldedStyle && conversation.isMarkFold()) {
disturbView.setVisibility(View.GONE);
} else {
disturbView.setVisibility(View.VISIBLE);
}
} else {
disturbView.setVisibility(View.GONE);
}
if (conversation.isMarkStar() && !isForwardMode) {
if (showFoldedStyle && conversation.isMarkFold()) {
markBannerView.setVisibility(View.GONE);
} else {
markBannerView.setVisibility(View.VISIBLE);
timelineText.setVisibility(View.GONE);
}
} else {
markBannerView.setVisibility(View.GONE);
timelineText.setVisibility(View.VISIBLE);
}
if (isForwardMode) {
messageText.setVisibility(View.GONE);
timelineText.setVisibility(View.GONE);
unreadText.setVisibility(View.GONE);
messageStatusLayout.setVisibility(View.GONE);
messageFailed.setVisibility(View.GONE);
messageSending.setVisibility(View.GONE);
atAllTv.setVisibility(View.GONE);
atMeTv.setVisibility(View.GONE);
draftTv.setVisibility(View.GONE);
riskTv.setVisibility(View.GONE);
}
if (!conversation.isGroup() && TUIConversationConfigClassic.isShowUserOnlineStatusIcon()) {
userStatusView.setVisibility(View.VISIBLE);
if (conversation.getStatusType() == ConversationInfo.USER_STATUS_ONLINE) {
userStatusView.setBackgroundResource(
TUIThemeManager.getAttrResId(rootView.getContext(), com.tencent.qcloud.tuikit.timcommon.R.attr.user_status_online));
} else {
userStatusView.setBackgroundResource(
TUIThemeManager.getAttrResId(rootView.getContext(), com.tencent.qcloud.tuikit.timcommon.R.attr.user_status_offline));
}
} else {
userStatusView.setVisibility(View.GONE);
}
applyCustomConfig();
}
private void applyCustomConfig() {
if (currentConversation.isTop() && !isForwardMode) {
Drawable pinnedCellBackground = TUIConversationConfigClassic.getPinnedCellBackground();
if (pinnedCellBackground != null) {
leftItemLayout.setBackground(pinnedCellBackground);
} else {
leftItemLayout.setBackgroundColor(rootView.getResources().getColor(R.color.conversation_item_top_color));
}
} else {
Drawable cellBackground = TUIConversationConfigClassic.getCellBackground();
if (cellBackground != null) {
leftItemLayout.setBackground(cellBackground);
} else {
leftItemLayout.setBackgroundColor(Color.WHITE);
}
}
if (!TUIConversationConfigClassic.isShowCellUnreadCount()) {
unreadText.setVisibility(View.GONE);
disturbView.setVisibility(View.GONE);
}
if (!TUIConversationConfigClassic.isShowUserOnlineStatusIcon()) {
userStatusView.setVisibility(View.GONE);
}
if (TUIConversationConfigClassic.getCellTitleLabelFontSize() != TUIConversationConfigClassic.UNDEFINED) {
titleText.setTextSize(TUIConversationConfigClassic.getCellTitleLabelFontSize());
}
if (TUIConversationConfigClassic.getCellSubtitleLabelFontSize() != TUIConversationConfigClassic.UNDEFINED) {
messageText.setTextSize(TUIConversationConfigClassic.getCellSubtitleLabelFontSize());
}
if (TUIConversationConfigClassic.getCellTimeLabelFontSize() != TUIConversationConfigClassic.UNDEFINED) {
timelineText.setTextSize(TUIConversationConfigClassic.getCellTimeLabelFontSize());
}
if (TUIConversationConfigClassic.getAvatarCornerRadius() != TUIConversationConfigClassic.UNDEFINED) {
conversationIconView.setRadius(TUIConversationConfigClassic.getAvatarCornerRadius());
}
}
private void setLastMessageAndStatus(ConversationInfo conversation) {
DraftInfo draftInfo = conversation.getDraft();
String draftText = "";
if (draftInfo != null) {
Gson gson = new Gson();
HashMap draftJsonMap;
draftText = draftInfo.getDraftText();
try {
draftJsonMap = gson.fromJson(draftInfo.getDraftText(), HashMap.class);
if (draftJsonMap != null) {
draftText = (String) draftJsonMap.get("content");
}
} catch (JsonSyntaxException e) {
TUIConversationLog.e("ConversationCommonHolder", " getDraftJsonMap error ");
}
}
atAllTv.setVisibility(View.GONE);
atMeTv.setVisibility(View.GONE);
draftTv.setVisibility(View.GONE);
riskTv.setVisibility(View.GONE);
if (draftInfo != null) {
messageText.setText(FaceManager.emojiJudge(draftText));
timelineText.setText(DateTimeUtil.getTimeFormatText(new Date(draftInfo.getDraftTime() * 1000)));
} else {
if (TUIConversationUtils.hasRiskContent(conversation.getLastMessage())) {
riskTv.setVisibility(View.VISIBLE);
} else {
TUIMessageBean lasTUIMessageBean = conversation.getLastTUIMessageBean();
if (lasTUIMessageBean != null) {
String displayString = ConversationPresenter.getMessageDisplayString(lasTUIMessageBean);
messageText.setText(displayString);
messageText.setTextColor(rootView.getResources().getColor(R.color.list_bottom_text_bg));
}
if (conversation.getLastMessage() != null) {
timelineText.setText(DateTimeUtil.getTimeFormatText(new Date(conversation.getLastMessageTime() * 1000)));
}
}
}
if (conversation.isShowDisturbIcon()) {
if ((showFoldedStyle && conversation.isMarkFold())) {
if (conversation.isMarkLocalUnread()) {
unreadText.setVisibility(View.VISIBLE);
unreadText.setText("");
} else {
unreadText.setVisibility(View.GONE);
}
} else {
if (conversation.getUnRead() == 0) {
if (conversation.isMarkUnread()) {
unreadText.setVisibility(View.VISIBLE);
unreadText.setText("");
} else {
unreadText.setVisibility(View.GONE);
}
} else {
unreadText.setVisibility(View.VISIBLE);
unreadText.setText("");
if (messageText.getText() != null) {
String text = messageText.getText().toString();
messageText.setText("[" + conversation.getUnRead() + " " + rootView.getContext().getString(R.string.message_num) + "] " + text);
}
}
}
} else if (conversation.getUnRead() > 0) {
unreadText.setVisibility(View.VISIBLE);
if (conversation.getUnRead() > 99) {
unreadText.setText("99+");
} else {
unreadText.setText("" + conversation.getUnRead());
}
} else {
if (conversation.isMarkUnread()) {
unreadText.setVisibility(View.VISIBLE);
unreadText.setText("1");
} else {
unreadText.setVisibility(View.GONE);
}
}
if (conversation.getAtType() == ConversationInfo.AT_TYPE_AT_ME) {
atMeTv.setVisibility(View.VISIBLE);
} else if (conversation.getAtType() == ConversationInfo.AT_TYPE_AT_ALL) {
atAllTv.setVisibility(View.VISIBLE);
} else if (conversation.getAtType() == ConversationInfo.AT_TYPE_AT_ALL_AND_ME) {
atAllTv.setVisibility(View.VISIBLE);
atMeTv.setVisibility(View.VISIBLE);
}
if (draftInfo != null) {
draftTv.setVisibility(View.VISIBLE);
messageStatusLayout.setVisibility(View.GONE);
messageFailed.setVisibility(View.GONE);
messageSending.setVisibility(View.GONE);
} else {
if (TUIConversationUtils.hasRiskContent(conversation.getLastMessage())) {
messageFailed.setVisibility(View.VISIBLE);
messageStatusLayout.setVisibility(View.VISIBLE);
messageSending.setVisibility(View.GONE);
} else {
int status = conversation.getLastMessageStatus();
if (status == ConversationInfo.LAST_MSG_STATUS_SEND_FAIL) {
messageStatusLayout.setVisibility(View.VISIBLE);
messageFailed.setVisibility(View.VISIBLE);
messageSending.setVisibility(View.GONE);
} else if (status == ConversationInfo.LAST_MSG_STATUS_SENDING) {
messageStatusLayout.setVisibility(View.VISIBLE);
messageFailed.setVisibility(View.GONE);
messageSending.setVisibility(View.VISIBLE);
} else {
messageStatusLayout.setVisibility(View.GONE);
messageFailed.setVisibility(View.GONE);
messageSending.setVisibility(View.GONE);
}
}
}
}
}

View File

@@ -0,0 +1,53 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.widget;
import android.graphics.Color;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
public class ConversationCustomHolder extends ConversationBaseHolder {
protected LinearLayout leftItemLayout;
protected TextView titleText;
protected TextView messageText;
protected TextView timelineText;
protected TextView unreadText;
protected ConversationIconView conversationIconView;
public ConversationCustomHolder(View itemView) {
super(itemView);
leftItemLayout = rootView.findViewById(R.id.item_left);
conversationIconView = rootView.findViewById(R.id.conversation_icon);
titleText = rootView.findViewById(R.id.conversation_title);
messageText = rootView.findViewById(R.id.conversation_last_msg);
timelineText = rootView.findViewById(R.id.conversation_time);
unreadText = rootView.findViewById(R.id.conversation_unread);
}
@Override
public void layoutViews(ConversationInfo conversation, int position) {
if (conversation.isTop()) {
leftItemLayout.setBackgroundColor(rootView.getResources().getColor(R.color.conversation_item_top_color));
} else {
leftItemLayout.setBackgroundColor(Color.WHITE);
}
conversationIconView.setConversation(conversation);
titleText.setText(conversation.getTitle());
messageText.setText("");
timelineText.setText("");
if (conversation.getUnRead() > 0) {
unreadText.setVisibility(View.VISIBLE);
if (conversation.getUnRead() > 99) {
unreadText.setText("99+");
} else {
unreadText.setText("" + conversation.getUnRead());
}
} else {
unreadText.setVisibility(View.GONE);
}
}
}

View File

@@ -0,0 +1,165 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.widget;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import com.tencent.qcloud.tuicore.TUIConfig;
import com.tencent.qcloud.tuikit.timcommon.component.gatherimage.SynthesizedImageView;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.timcommon.util.ImageUtil;
import com.tencent.qcloud.tuikit.timcommon.util.ScreenUtil;
import com.tencent.qcloud.tuikit.timcommon.util.TUIUtil;
import com.tencent.qcloud.tuikit.timcommon.util.ThreadUtils;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationIconPresenter;
import java.util.ArrayList;
import java.util.List;
public class ConversationIconView extends RelativeLayout {
private static final int icon_size = ScreenUtil.getPxByDp(50);
private ImageView mIconView;
private boolean showFoldedStyle = false;
private ConversationIconPresenter presenter;
public ConversationIconView(Context context) {
super(context);
init();
}
public ConversationIconView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ConversationIconView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
inflate(getContext(), com.tencent.qcloud.tuikit.timcommon.R.layout.common_profile_icon_view, this);
mIconView = findViewById(com.tencent.qcloud.tuikit.timcommon.R.id.profile_icon);
((SynthesizedImageView) mIconView).defaultImage(TUIConfig.getDefaultAvatarImage());
presenter = new ConversationIconPresenter();
}
public void setShowFoldedStyle(boolean showFoldedStyle) {
this.showFoldedStyle = showFoldedStyle;
}
public void setIconUrls(final List<Object> iconUrls, final String conversationId) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
if (mIconView instanceof SynthesizedImageView) {
((SynthesizedImageView) (mIconView)).displayImage(iconUrls).load(conversationId);
}
}
});
}
public void setConversation(ConversationInfo conversationInfo) {
if (showFoldedStyle && conversationInfo.isMarkFold()) {
mIconView.setImageResource(R.drawable.conversation_ic_fold);
} else if (mIconView instanceof SynthesizedImageView) {
((SynthesizedImageView) (mIconView)).setImageId(conversationInfo.getConversationId());
if (conversationInfo.isGroup()) {
fillConversationUrlForGroup(conversationInfo);
} else {
setIconUrls(conversationInfo.getIconUrlList(), conversationInfo.getConversationId());
}
}
}
private void fillConversationUrlForGroup(final ConversationInfo info) {
List<Object> iconUrlList = info.getIconUrlList();
if (iconUrlList == null || iconUrlList.size() == 0) {
if (!TUIConfig.isEnableGroupGridAvatar()) {
List<Object> faceList = new ArrayList<>();
faceList.add(TUIConfig.getDefaultGroupAvatarImage());
setIconUrls(faceList, info.getConversationId());
return;
}
ThreadUtils.execute(new Runnable() {
@Override
public void run() {
final String savedIcon = ImageUtil.getGroupConversationAvatar(info.getConversationId());
if (TextUtils.isEmpty(savedIcon)) {
fillFaceUrlList(info.getId(), info);
} else {
List<Object> list = new ArrayList<>();
list.add(savedIcon);
info.setIconUrlList(list);
setIconUrls(list, info.getConversationId());
}
}
});
} else {
if (!TUIConfig.isEnableGroupGridAvatar() && iconUrlList.size() > 1) {
List<Object> faceList = new ArrayList<>();
faceList.add(TUIConfig.getDefaultGroupAvatarImage());
setIconUrls(faceList, info.getConversationId());
} else {
setIconUrls(iconUrlList, info.getConversationId());
}
}
}
private void fillFaceUrlList(final String groupID, final ConversationInfo info) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
clearImage();
presenter.getGroupMemberIconList(groupID, new IUIKitCallback<List<Object>>() {
@Override
public void onSuccess(List<Object> data) {
info.setIconUrlList(data);
setIconUrls(data, info.getConversationId());
}
@Override
public void onError(String module, int errCode, String errMsg) {
if (mIconView instanceof SynthesizedImageView) {
((SynthesizedImageView) (mIconView)).defaultImage(TUIUtil.getDefaultGroupIconResIDByGroupType(getContext(), info.getGroupType()));
}
setIconUrls(null, info.getConversationId());
}
});
}
});
}
public void setRadius(int radius) {
if (mIconView instanceof SynthesizedImageView) {
((SynthesizedImageView) (mIconView)).setRadius(radius);
}
}
public void setDefaultImageResId(int resId) {
BitmapDrawable bd = (BitmapDrawable) getContext().getResources().getDrawable(resId);
mIconView.setImageBitmap(bd.getBitmap());
}
public void setBitmapResId(int resId) {
BitmapDrawable bd = (BitmapDrawable) getContext().getResources().getDrawable(resId);
Bitmap bitmap = ImageUtil.toRoundBitmap(bd.getBitmap());
mIconView.setImageBitmap(bitmap);
}
public void clearImage() {
if (mIconView instanceof SynthesizedImageView) {
((SynthesizedImageView) mIconView).clear();
}
}
}

View File

@@ -0,0 +1,129 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.widget;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
import com.tencent.qcloud.tuikit.timcommon.component.TitleBarLayout;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces.IConversationLayout;
import com.tencent.qcloud.tuikit.tuiconversation.config.classicui.TUIConversationConfigClassic;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationPresenter;
public class ConversationLayout extends RelativeLayout implements IConversationLayout {
private ConversationListLayout mConversationList;
private ConversationPresenter presenter;
public ConversationLayout(Context context) {
super(context);
init();
}
public ConversationLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ConversationLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void setPresenter(ConversationPresenter presenter) {
this.presenter = presenter;
if (mConversationList != null) {
mConversationList.setPresenter(presenter);
}
}
private void init() {
inflate(getContext(), R.layout.conversation_layout, this);
mConversationList = findViewById(R.id.conversation_list);
applyCustomConfig();
}
private void applyCustomConfig() {
Drawable listBackground = TUIConversationConfigClassic.getListBackground();
if (listBackground != null) {
mConversationList.setBackground(listBackground);
}
}
public void initDefault() {
final ConversationListAdapter adapter = new ConversationListAdapter();
if (presenter != null) {
adapter.setShowFoldedStyle(true);
}
mConversationList.setAdapter((IConversationListAdapter) adapter);
if (presenter != null) {
presenter.setAdapter(adapter);
}
mConversationList.loadConversation();
mConversationList.loadMarkedConversation();
}
@Override
public void setParentLayout(Object parent) {}
@Override
public ConversationListLayout getConversationList() {
return mConversationList;
}
@Override
public void setConversationTop(ConversationInfo conversation, IUIKitCallback callBack) {
if (presenter != null) {
presenter.setConversationTop(conversation, callBack);
}
}
@Override
public void deleteConversation(ConversationInfo conversation) {
if (presenter != null) {
presenter.deleteConversation(conversation);
}
}
@Override
public void clearConversationMessage(ConversationInfo conversation) {
if (presenter != null) {
presenter.clearConversationMessage(conversation);
}
}
@Override
public void markConversationHidden(ConversationInfo conversation) {
if (presenter != null) {
presenter.markConversationHidden(conversation, true);
}
}
@Override
public void markConversationUnread(ConversationInfo conversationInfo, boolean markUnread) {
if (presenter != null) {
presenter.markConversationUnreadAndCleanUnreadCount(conversationInfo, markUnread);
}
}
@Override
public void hideFoldedItem(boolean needHide) {
if (presenter != null) {
presenter.hideFoldItem(needHide);
}
}
@Override
public void clearUnreadStatusOfFoldItem() {
if (presenter != null) {
presenter.setUnreadStatusOfFoldItem(false);
}
}
@Override
public TitleBarLayout getTitleBar() {
return null;
}
}

View File

@@ -0,0 +1,569 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.widget;
import android.graphics.Color;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.tencent.qcloud.tuikit.timcommon.util.ScreenUtil;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.TUIConversationService;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces.OnConversationAdapterListener;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.ConversationUtils;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class ConversationListAdapter extends RecyclerView.Adapter implements IConversationListAdapter {
public static final int ITEM_TYPE_HEADER_SEARCH = 101;
public static final int ITEM_TYPE_FOOTER_LOADING = -99;
public static final int ITEM_TYPE_NULL_DATA = 102;
public static final int HEADER_COUNT = 1;
public static final int FOOTER_COUNT = 1;
public static final int SELECT_COUNT = 1;
public static final int SELECT_LABEL_COUNT = 1;
private boolean mHasShowUnreadDot = true;
protected List<ConversationInfo> mDataSource = new ArrayList<>();
private OnConversationAdapterListener mOnConversationAdapterListener;
private final HashMap<String, Boolean> mSelectedPositions = new HashMap<>();
private boolean isShowMultiSelectCheckBox = false;
private boolean isForwardFragment = false;
private boolean isOnlyConversationSelect = false;
protected List<String> mCannotSelectIds = new ArrayList<>();
private boolean mIsLoading = false;
private boolean isClick = false;
private int currentPosition = -1;
private View searchView;
private boolean showFoldedStyle = true;
private String conversationGroupName = ConversationUtils.getConversationAllGroupName();
public ConversationListAdapter() {
mCannotSelectIds.clear();
}
public int getCurrentPosition() {
return currentPosition;
}
public boolean isClick() {
return isClick;
}
public void setClick(boolean click) {
isClick = click;
}
public void setCannotSelectIds(List<String> list) {
this.mCannotSelectIds = list;
}
private boolean isInCannotSelectIds(String id) {
if (mCannotSelectIds.isEmpty()) {
return false;
}
if (mCannotSelectIds.contains(id)) {
return true;
} else {
return false;
}
}
public void setCurrentPosition(int currentPosition, boolean isClick) {
this.currentPosition = currentPosition;
this.isClick = isClick;
}
public void setShowMultiSelectCheckBox(boolean show) {
isShowMultiSelectCheckBox = show;
if (!isShowMultiSelectCheckBox) {
mSelectedPositions.clear();
}
}
public void setForwardFragment(boolean forwardFragment) {
isForwardFragment = forwardFragment;
}
public void setIsOnlyConversationSelect(boolean is) {
this.isOnlyConversationSelect = is;
}
public void setSearchView(View searchView) {
this.searchView = searchView;
}
public void setShowFoldedStyle(boolean showFoldedStyle) {
this.showFoldedStyle = showFoldedStyle;
}
public void setItemChecked(String conversationId, boolean isChecked) {
mSelectedPositions.put(conversationId, isChecked);
}
private boolean isItemChecked(String id) {
if (mSelectedPositions.size() <= 0) {
return false;
}
if (mSelectedPositions.containsKey(id)) {
return mSelectedPositions.get(id);
} else {
return false;
}
}
public List<ConversationInfo> getSelectedItem() {
if (mSelectedPositions.size() == 0) {
return null;
}
List<ConversationInfo> selectList = new ArrayList<>();
for (int i = 0; i < getItemCount() - 1; i++) {
ConversationInfo conversationInfo = getItem(i);
if (conversationInfo == null) {
continue;
}
if (isItemChecked(conversationInfo.getConversationId())) {
selectList.add(conversationInfo);
}
}
return selectList;
}
public void setSelectConversations(List<ConversationInfo> dataSource) {
if (dataSource == null || dataSource.size() == 0) {
mSelectedPositions.clear();
notifyDataSetChanged();
return;
}
mSelectedPositions.clear();
for (int i = 0; i < dataSource.size(); i++) {
for (int j = 0; j < mDataSource.size(); j++) {
if (TextUtils.equals(dataSource.get(i).getConversationId(), mDataSource.get(j).getConversationId())) {
setItemChecked(mDataSource.get(j).getConversationId(), true);
notifyDataSetChanged();
break;
}
}
}
}
public void setOnConversationAdapterListener(OnConversationAdapterListener listener) {
this.mOnConversationAdapterListener = listener;
}
public void setConversationGroupName(String groupName) {
this.conversationGroupName = groupName;
}
private boolean isShowNullConversationText() {
if (mDataSource.isEmpty() && showFoldedStyle) {
return true;
}
return false;
}
@Override
public void onDataSourceChanged(List<ConversationInfo> dataSource) {
this.mDataSource = dataSource;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
ConversationBaseHolder holder = null;
View view;
if (viewType == ITEM_TYPE_HEADER_SEARCH) {
if (searchView == null) {
searchView = new View(parent.getContext());
}
return new HeaderViewHolder(searchView);
} else if (viewType == ConversationInfo.TYPE_CUSTOM) {
view = inflater.inflate(R.layout.conversation_custom_adapter, parent, false);
holder = new ConversationCustomHolder(view);
} else if (viewType == ITEM_TYPE_FOOTER_LOADING) {
view = inflater.inflate(R.layout.conversation_loading_progress_bar, parent, false);
return new FooterViewHolder(view);
} else if (viewType == ConversationInfo.TYPE_FORWAR_SELECT) {
view = inflater.inflate(R.layout.conversation_forward_select_adapter, parent, false);
return new ForwardSelectHolder(view);
} else if (viewType == ConversationInfo.TYPE_RECENT_LABEL) {
view = inflater.inflate(R.layout.conversation_forward_label_adapter, parent, false);
return new ForwardLabelHolder(view);
} else if (viewType == ITEM_TYPE_NULL_DATA) {
view = inflater.inflate(R.layout.conversation_null_layout, parent, false);
return new RecyclerView.ViewHolder(view) {};
} else {
view = inflater.inflate(R.layout.conversation_list_item_layout, parent, false);
holder = new ConversationCommonHolder(view);
((ConversationCommonHolder) holder).setForwardMode(isForwardFragment);
((ConversationCommonHolder) holder).setShowFoldedStyle(showFoldedStyle);
}
holder.setAdapter(this);
return holder;
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
final ConversationInfo conversationInfo = getItem(position);
ConversationBaseHolder baseHolder = null;
if (conversationInfo != null) {
baseHolder = (ConversationBaseHolder) holder;
}
switch (getItemViewType(position)) {
case ConversationInfo.TYPE_CUSTOM:
case ConversationInfo.TYPE_RECENT_LABEL:
break;
case ITEM_TYPE_NULL_DATA:
TextView nullTextView = holder.itemView.findViewById(R.id.conversation_null_text);
nullTextView.setText(holder.itemView.getResources().getString(R.string.conversation_null_text, conversationGroupName));
return;
case ITEM_TYPE_FOOTER_LOADING: {
if (holder instanceof FooterViewHolder) {
((ConversationBaseHolder) holder).layoutViews(null, position);
}
break;
}
case ConversationInfo.TYPE_FORWAR_SELECT: {
ForwardSelectHolder selectHolder = (ForwardSelectHolder) holder;
selectHolder.refreshTitle(!isShowMultiSelectCheckBox);
setOnClickListener(holder, getItemViewType(position), conversationInfo);
break;
}
default:
setOnClickListener(holder, getItemViewType(position), conversationInfo);
}
if (baseHolder != null) {
if (getCurrentPosition() == position && isClick()) {
baseHolder.itemView.setBackgroundResource(R.color.conversation_item_clicked_color);
}
baseHolder.layoutViews(conversationInfo, position);
setCheckBoxStatus(conversationInfo, position, baseHolder);
}
}
private void setOnClickListener(RecyclerView.ViewHolder holder, int viewType, ConversationInfo conversationInfo) {
if (holder instanceof HeaderViewHolder) {
return;
}
if (mOnConversationAdapterListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mOnConversationAdapterListener.onItemClick(view, viewType, conversationInfo);
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
mOnConversationAdapterListener.onItemLongClick(view, conversationInfo);
int position = getIndexInAdapter(conversationInfo);
if (position != -1) {
setCurrentPosition(position, true);
notifyItemChanged(position);
}
return true;
}
});
}
}
private void setCheckBoxStatus(final ConversationInfo conversationInfo, int position, ConversationBaseHolder baseHolder) {
if (!(baseHolder instanceof ConversationCommonHolder) || ((ConversationCommonHolder) baseHolder).multiSelectCheckBox == null) {
return;
}
int viewType = getItemViewType(position);
String conversationId = conversationInfo.getConversationId();
ConversationCommonHolder commonHolder = (ConversationCommonHolder) baseHolder;
if (!isShowMultiSelectCheckBox) {
commonHolder.multiSelectCheckBox.setVisibility(View.GONE);
} else {
commonHolder.multiSelectCheckBox.setVisibility(View.VISIBLE);
if (isInCannotSelectIds(conversationId)) {
commonHolder.itemView.setEnabled(false);
commonHolder.multiSelectCheckBox.setEnabled(false);
commonHolder.itemView.setAlpha(0.5f);
commonHolder.multiSelectCheckBox.setChecked(true);
} else {
commonHolder.itemView.setEnabled(true);
commonHolder.multiSelectCheckBox.setEnabled(true);
commonHolder.itemView.setAlpha(1f);
commonHolder.multiSelectCheckBox.setChecked(isItemChecked(conversationId));
}
commonHolder.multiSelectCheckBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setItemChecked(conversationId, !isItemChecked(conversationId));
if (mOnConversationAdapterListener != null) {
mOnConversationAdapterListener.onItemClick(v, viewType, conversationInfo);
}
}
});
baseHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setItemChecked(conversationId, !isItemChecked(conversationId));
int currentPosition = getIndexInAdapter(conversationInfo);
if (currentPosition != -1) {
notifyItemChanged(currentPosition);
}
if (mOnConversationAdapterListener != null) {
mOnConversationAdapterListener.onItemClick(v, viewType, conversationInfo);
}
}
});
}
}
public int getIndexInAdapter(ConversationInfo conversationInfo) {
int position = -1;
if (mDataSource != null) {
int indexInData = mDataSource.indexOf(conversationInfo);
if (indexInData != -1) {
position = getItemIndexInAdapter(indexInData);
}
}
return position;
}
@Override
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
if (holder instanceof ConversationCommonHolder) {
((ConversationCommonHolder) holder).conversationIconView.clearImage();
}
}
public ConversationInfo getItem(int position) {
if (mDataSource.isEmpty() || position == getItemCount() - 1) {
return null;
}
int dataPosition;
if (isForwardFragment) {
if (isOnlyConversationSelect) {
dataPosition = position - SELECT_LABEL_COUNT;
} else {
dataPosition = position - SELECT_COUNT - SELECT_LABEL_COUNT;
}
} else {
dataPosition = position - HEADER_COUNT;
}
if (dataPosition < mDataSource.size() && dataPosition >= 0) {
return mDataSource.get(dataPosition);
}
return null;
}
@Override
public int getItemCount() {
int listSize = mDataSource.size();
if (isForwardFragment) {
if (isOnlyConversationSelect) {
return listSize + SELECT_LABEL_COUNT + FOOTER_COUNT;
}
return listSize + SELECT_COUNT + SELECT_LABEL_COUNT + FOOTER_COUNT;
} else if (isShowNullConversationText()) {
return 1;
}
return listSize + HEADER_COUNT + FOOTER_COUNT;
}
@Override
public int getItemViewType(int position) {
if (isForwardFragment) {
if (isOnlyConversationSelect) {
if (position == 0) {
return ConversationInfo.TYPE_RECENT_LABEL;
}
} else {
if (position == 0) {
return ConversationInfo.TYPE_FORWAR_SELECT;
} else if (position == 1) {
return ConversationInfo.TYPE_RECENT_LABEL;
}
}
} else if (isShowNullConversationText()) {
return ITEM_TYPE_NULL_DATA;
} else {
if (position == 0) {
return ITEM_TYPE_HEADER_SEARCH;
}
}
if (position == getItemCount() - 1) {
return ITEM_TYPE_FOOTER_LOADING;
} else if (mDataSource != null) {
ConversationInfo conversationInfo = getItem(position);
if (conversationInfo != null) {
return conversationInfo.getType();
}
}
return ConversationInfo.TYPE_COMMON;
}
private int getItemIndexInAdapter(int index) {
int itemIndex;
if (isForwardFragment) {
if (isOnlyConversationSelect) {
itemIndex = index + SELECT_LABEL_COUNT;
} else {
itemIndex = index + SELECT_LABEL_COUNT + SELECT_COUNT;
}
} else {
itemIndex = index + HEADER_COUNT;
}
return itemIndex;
}
@Override
public void onItemRemoved(int position) {
int itemIndex = getItemIndexInAdapter(position);
notifyItemRemoved(itemIndex);
}
@Override
public void onItemInserted(int position) {
int itemIndex = getItemIndexInAdapter(position);
notifyItemInserted(itemIndex);
}
@Override
public void onItemMoved(int fromPosition, int toPosition) {
int fromIndex = getItemIndexInAdapter(fromPosition);
int toIndex = getItemIndexInAdapter(toPosition);
notifyItemMoved(fromIndex, toIndex);
}
@Override
public void onItemChanged(int position) {
int itemIndex = getItemIndexInAdapter(position);
notifyItemChanged(itemIndex);
}
@Override
public void onItemRangeChanged(int startPosition, int count) {
int itemStartIndex = getItemIndexInAdapter(startPosition);
notifyItemRangeChanged(itemStartIndex, count);
}
@Override
public void onConversationChanged(List<ConversationInfo> conversationInfoList) {
if (mOnConversationAdapterListener != null) {
mOnConversationAdapterListener.onConversationChanged(conversationInfoList);
}
}
public void disableItemUnreadDot(boolean flag) {
mHasShowUnreadDot = !flag;
}
public boolean hasItemUnreadDot() {
return mHasShowUnreadDot;
}
@Override
public void onLoadingStateChanged(boolean isLoading) {
this.mIsLoading = isLoading;
notifyItemChanged(getItemCount() - 1);
}
@Override
public void onViewNeedRefresh() {
notifyDataSetChanged();
}
// header
static class HeaderViewHolder extends RecyclerView.ViewHolder {
public HeaderViewHolder(@NonNull View itemView) {
super(itemView);
}
}
// footer
class FooterViewHolder extends ConversationBaseHolder {
public FooterViewHolder(@NonNull View itemView) {
super(itemView);
}
@Override
public void layoutViews(ConversationInfo conversationInfo, int position) {
RecyclerView.LayoutParams param = (RecyclerView.LayoutParams) rootView.getLayoutParams();
if (mIsLoading) {
param.height = LinearLayout.LayoutParams.WRAP_CONTENT;
param.width = LinearLayout.LayoutParams.MATCH_PARENT;
rootView.setVisibility(View.VISIBLE);
} else {
param.height = 0;
param.width = 0;
rootView.setVisibility(View.GONE);
}
rootView.setLayoutParams(param);
}
}
static class ForwardLabelHolder extends ConversationBaseHolder {
public ForwardLabelHolder(View itemView) {
super(itemView);
}
@Override
public void layoutViews(ConversationInfo conversationInfo, int position) {}
}
static class ForwardSelectHolder extends ConversationBaseHolder {
private final TextView titleView;
public ForwardSelectHolder(View itemView) {
super(itemView);
titleView = itemView.findViewById(R.id.forward_title);
}
@Override
public void layoutViews(ConversationInfo conversationInfo, int position) {}
public void refreshTitle(boolean isCreateGroup) {
if (titleView == null) {
return;
}
if (isCreateGroup) {
titleView.setText(TUIConversationService.getAppContext().getString(R.string.forward_select_new_chat));
} else {
titleView.setText(TUIConversationService.getAppContext().getString(R.string.forward_select_from_contact));
}
}
}
}

View File

@@ -0,0 +1,130 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.widget;
import android.content.Context;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import com.tencent.qcloud.tuikit.timcommon.component.CustomLinearLayoutManager;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces.IConversationListLayout;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces.OnConversationAdapterListener;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationPresenter;
public class ConversationListLayout extends RecyclerView implements IConversationListLayout {
protected ConversationListAdapter mAdapter;
protected ConversationPresenter presenter;
public ConversationListLayout(Context context) {
super(context);
init();
}
public ConversationListLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ConversationListLayout(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void setPresenter(ConversationPresenter presenter) {
this.presenter = presenter;
}
public void init() {
setLayoutFrozen(false);
setItemViewCacheSize(0);
setHasFixedSize(true);
setFocusableInTouchMode(false);
CustomLinearLayoutManager linearLayoutManager = new CustomLinearLayoutManager(getContext());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
setLayoutManager(linearLayoutManager);
SimpleItemAnimator animator = (SimpleItemAnimator) getItemAnimator();
if (animator != null) {
animator.setSupportsChangeAnimations(false);
}
}
@Override
public void setBackground(int resId) {
setBackgroundColor(resId);
}
@Override
public void disableItemUnreadDot(boolean flag) {
mAdapter.disableItemUnreadDot(flag);
}
@Override
public ConversationListLayout getListLayout() {
return this;
}
@Override
public ConversationListAdapter getAdapter() {
return mAdapter;
}
@Override
public void setAdapter(IConversationListAdapter adapter) {
if (adapter instanceof ConversationListAdapter) {
super.setAdapter((ConversationListAdapter) adapter);
mAdapter = (ConversationListAdapter) adapter;
}
}
@Override
public void setOnConversationAdapterListener(OnConversationAdapterListener listener) {
mAdapter.setOnConversationAdapterListener(listener);
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
if (state == RecyclerView.SCROLL_STATE_IDLE) {
LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
if (layoutManager == null) {
return;
}
int lastPosition = layoutManager.findLastCompletelyVisibleItemPosition();
if (mAdapter != null) {
if (lastPosition == mAdapter.getItemCount() - 1 && !isLoadCompleted()) {
mAdapter.onLoadingStateChanged(true);
if (presenter != null) {
presenter.loadMoreConversation();
}
}
}
}
}
public void loadConversation() {
if (presenter != null) {
presenter.loadMoreConversation();
}
}
public void loadMarkedConversation() {
if (presenter != null) {
presenter.loadMarkedConversation();
}
}
public void reLoadConversation() {
if (presenter != null) {
presenter.reLoadConversation();
}
}
boolean isLoadCompleted() {
if (presenter != null) {
return presenter.isLoadFinished();
}
return false;
}
}

View File

@@ -0,0 +1,312 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.widget;
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import static androidx.viewpager2.widget.ViewPager2.SCROLL_STATE_DRAGGING;
import static androidx.viewpager2.widget.ViewPager2.SCROLL_STATE_IDLE;
import static androidx.viewpager2.widget.ViewPager2.SCROLL_STATE_SETTLING;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import java.lang.ref.WeakReference;
/**
* A mediator to link a TabLayout with a ViewPager2. The mediator will synchronize the ViewPager2's
* position with the selected tab when a tab is selected, and the TabLayout's scroll position when
* the user drags the ViewPager2. ConversationTabLayoutMediator will listen to ViewPager2's OnPageChangeCallback
* to adjust tab when ViewPager2 moves. ConversationTabLayoutMediator listens to TabLayout's
* OnTabSelectedListener to adjust VP2 when tab moves. ConversationTabLayoutMediator listens to RecyclerView's
* AdapterDataObserver to recreate tab content when dataset changes.
*
* <p>Establish the link by creating an instance of this class, make sure the ViewPager2 has an
* adapter and then call {@link #attach()} on it. Instantiating a ConversationTabLayoutMediator will only create
* the mediator object, {@link #attach()} will link the TabLayout and the ViewPager2 together. When
* creating an instance of this class, you must supply an implementation of {@link
* ConversationTabLayoutMediator.TabConfigurationStrategy} in which you set the text of the tab, and/or perform any styling of the
* tabs that you require. Changing ViewPager2's adapter will require a {@link #detach()} followed by
* {@link #attach()} call. Changing the ViewPager2 or TabLayout will require a new instantiation of
* ConversationTabLayoutMediator.
*/
public class ConversationTabLayoutMediator {
@NonNull private final TabLayout tabLayout;
@NonNull private final ViewPager2 viewPager;
private final boolean autoRefresh;
private static boolean smoothScroll;
private final ConversationTabLayoutMediator.TabConfigurationStrategy tabConfigurationStrategy;
@Nullable private RecyclerView.Adapter<?> adapter;
private boolean attached;
@Nullable private ConversationTabLayoutMediator.TabLayoutOnPageChangeCallback onPageChangeCallback;
@Nullable private TabLayout.OnTabSelectedListener onTabSelectedListener;
@Nullable private RecyclerView.AdapterDataObserver pagerAdapterObserver;
/**
* A callback interface that must be implemented to set the text and styling of newly created
* tabs.
*/
public interface TabConfigurationStrategy {
/**
* Called to configure the tab for the page at the specified position. Typically calls {@link
* TabLayout.Tab#setText(CharSequence)}, but any form of styling can be applied.
*
* @param tab The Tab which should be configured to represent the title of the item at the given
* position in the data set.
* @param position The position of the item within the adapter's data set.
*/
void onConfigureTab(@NonNull TabLayout.Tab tab, int position);
}
public ConversationTabLayoutMediator(
@NonNull TabLayout tabLayout, @NonNull ViewPager2 viewPager, @NonNull ConversationTabLayoutMediator.TabConfigurationStrategy tabConfigurationStrategy) {
this(tabLayout, viewPager, /* autoRefresh= */ true, tabConfigurationStrategy);
}
public ConversationTabLayoutMediator(@NonNull TabLayout tabLayout, @NonNull ViewPager2 viewPager, boolean autoRefresh,
@NonNull ConversationTabLayoutMediator.TabConfigurationStrategy tabConfigurationStrategy) {
this(tabLayout, viewPager, autoRefresh, /* smoothScroll= */ true, tabConfigurationStrategy);
}
public ConversationTabLayoutMediator(@NonNull TabLayout tabLayout, @NonNull ViewPager2 viewPager, boolean autoRefresh, boolean smoothScroll,
@NonNull ConversationTabLayoutMediator.TabConfigurationStrategy tabConfigurationStrategy) {
this.tabLayout = tabLayout;
this.viewPager = viewPager;
this.autoRefresh = autoRefresh;
this.smoothScroll = smoothScroll;
this.tabConfigurationStrategy = tabConfigurationStrategy;
}
/**
* Link the TabLayout and the ViewPager2 together. Must be called after ViewPager2 has an adapter
* set. To be called on a new instance of ConversationTabLayoutMediator or if the ViewPager2's adapter
* changes.
*
* @throws IllegalStateException If the mediator is already attached, or the ViewPager2 has no
* adapter.
*/
public void attach() {
if (attached) {
throw new IllegalStateException("ConversationTabLayoutMediator is already attached");
}
adapter = viewPager.getAdapter();
if (adapter == null) {
throw new IllegalStateException("ConversationTabLayoutMediator attached before ViewPager2 has an "
+ "adapter");
}
attached = true;
// Add our custom OnPageChangeCallback to the ViewPager
onPageChangeCallback = new ConversationTabLayoutMediator.TabLayoutOnPageChangeCallback(tabLayout);
viewPager.registerOnPageChangeCallback(onPageChangeCallback);
// Now we'll add a tab selected listener to set ViewPager's current item
onTabSelectedListener = new ConversationTabLayoutMediator.ViewPagerOnTabSelectedListener(viewPager, smoothScroll);
tabLayout.addOnTabSelectedListener(onTabSelectedListener);
// Now we'll populate ourselves from the pager adapter, adding an observer if
// autoRefresh is enabled
if (autoRefresh) {
// Register our observer on the new adapter
pagerAdapterObserver = new ConversationTabLayoutMediator.PagerAdapterObserver();
adapter.registerAdapterDataObserver(pagerAdapterObserver);
}
populateTabsFromPagerAdapter();
// Now update the scroll position to match the ViewPager's current item
tabLayout.setScrollPosition(viewPager.getCurrentItem(), 0f, true);
}
/**
* Unlink the TabLayout and the ViewPager. To be called on a stale ConversationTabLayoutMediator if a new one
* is instantiated, to prevent holding on to a view that should be garbage collected. Also to be
* called before {@link #attach()} when a ViewPager2's adapter is changed.
*/
public void detach() {
if (autoRefresh && adapter != null) {
adapter.unregisterAdapterDataObserver(pagerAdapterObserver);
pagerAdapterObserver = null;
}
tabLayout.removeOnTabSelectedListener(onTabSelectedListener);
viewPager.unregisterOnPageChangeCallback(onPageChangeCallback);
onTabSelectedListener = null;
onPageChangeCallback = null;
adapter = null;
attached = false;
}
/**
* Returns whether the {@link TabLayout} and the {@link ViewPager2} are linked together.
*/
public boolean isAttached() {
return attached;
}
@SuppressWarnings("WeakerAccess")
void populateTabsFromPagerAdapter() {
tabLayout.removeAllTabs();
if (adapter != null) {
int adapterCount = adapter.getItemCount();
for (int i = 0; i < adapterCount; i++) {
TabLayout.Tab tab = tabLayout.newTab();
tabConfigurationStrategy.onConfigureTab(tab, i);
tabLayout.addTab(tab, false);
}
// Make sure we reflect the currently set ViewPager item
if (adapterCount > 0) {
int lastItem = tabLayout.getTabCount() - 1;
int currItem = Math.min(viewPager.getCurrentItem(), lastItem);
if (currItem != tabLayout.getSelectedTabPosition()) {
tabLayout.selectTab(tabLayout.getTabAt(currItem));
}
}
}
}
/**
* A {@link ViewPager2.OnPageChangeCallback} class which contains the necessary calls back to the
* provided {@link TabLayout} so that the tab position is kept in sync.
*
* <p>This class stores the provided TabLayout weakly, meaning that you can use {@link
* ViewPager2#registerOnPageChangeCallback(ViewPager2.OnPageChangeCallback)} without removing the
* callback and not cause a leak.
*/
private static class TabLayoutOnPageChangeCallback extends ViewPager2.OnPageChangeCallback {
@NonNull private final WeakReference<TabLayout> tabLayoutRef;
private int previousScrollState;
private int scrollState;
TabLayoutOnPageChangeCallback(TabLayout tabLayout) {
tabLayoutRef = new WeakReference<>(tabLayout);
reset();
}
@Override
public void onPageScrollStateChanged(final int state) {
if (state == SCROLL_STATE_DRAGGING) {
smoothScroll = true;
} else if (state == SCROLL_STATE_IDLE) {
smoothScroll = false;
}
previousScrollState = scrollState;
scrollState = state;
previousScrollState = scrollState;
scrollState = state;
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
TabLayout tabLayout = tabLayoutRef.get();
if (tabLayout != null) {
// Only update the text selection if we're not settling, or we are settling after
// being dragged
boolean updateText = scrollState != SCROLL_STATE_SETTLING || previousScrollState == SCROLL_STATE_DRAGGING;
// Update the indicator if we're not settling after being idle. This is caused
// from a setCurrentItem() call and will be handled by an animation from
// onPageSelected() instead.
boolean updateIndicator = !(scrollState == SCROLL_STATE_SETTLING && previousScrollState == SCROLL_STATE_IDLE);
tabLayout.setScrollPosition(position, positionOffset, updateText, updateIndicator);
}
}
@Override
public void onPageSelected(final int position) {
TabLayout tabLayout = tabLayoutRef.get();
if (tabLayout != null && tabLayout.getSelectedTabPosition() != position && position < tabLayout.getTabCount()) {
// Select the tab, only updating the indicator if we're not being dragged/settled
// (since onPageScrolled will handle that).
boolean updateIndicator =
scrollState == SCROLL_STATE_IDLE || (scrollState == SCROLL_STATE_SETTLING && previousScrollState == SCROLL_STATE_IDLE);
tabLayout.selectTab(tabLayout.getTabAt(position), updateIndicator);
}
}
void reset() {
previousScrollState = scrollState = SCROLL_STATE_IDLE;
}
}
/**
* A {@link TabLayout.OnTabSelectedListener} class which contains the necessary calls back to the
* provided {@link ViewPager2} so that the tab position is kept in sync.
*/
private static class ViewPagerOnTabSelectedListener implements TabLayout.OnTabSelectedListener {
private final ViewPager2 viewPager;
// private boolean smoothScroll;
ViewPagerOnTabSelectedListener(ViewPager2 viewPager, boolean smoothScroll) {
this.viewPager = viewPager;
// this.smoothScroll = smoothScroll;
}
@Override
public void onTabSelected(@NonNull TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition(), smoothScroll);
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
// No-op
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
// No-op
}
}
private class PagerAdapterObserver extends RecyclerView.AdapterDataObserver {
PagerAdapterObserver() {}
@Override
public void onChanged() {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount) {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeChanged(int positionStart, int itemCount, @Nullable Object payload) {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
populateTabsFromPagerAdapter();
}
@Override
public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
populateTabsFromPagerAdapter();
}
}
}

View File

@@ -0,0 +1,103 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
import com.tencent.qcloud.tuikit.timcommon.component.TitleBarLayout;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces.IConversationLayout;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationFoldPresenter;
public class FoldedConversationLayout extends RelativeLayout implements IConversationLayout {
private TitleBarLayout titleBarLayout;
private FoldedConversationListLayout conversationListLayout;
private ConversationFoldPresenter presenter;
public FoldedConversationLayout(Context context) {
super(context);
init();
}
public FoldedConversationLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public FoldedConversationLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void setPresenter(ConversationFoldPresenter presenter) {
this.presenter = presenter;
if (conversationListLayout != null) {
conversationListLayout.setPresenter(presenter);
}
}
private void init() {
inflate(getContext(), R.layout.conversation_folded_layout, this);
titleBarLayout = findViewById(R.id.conversation_title);
conversationListLayout = findViewById(R.id.folded_conversation_list);
}
public void initDefault() {
final ConversationListAdapter adapter = new ConversationListAdapter();
conversationListLayout.setAdapter((IConversationListAdapter) adapter);
adapter.setShowFoldedStyle(false);
if (presenter != null) {
presenter.setAdapter(adapter);
}
conversationListLayout.loadConversation();
}
@Override
public FoldedConversationListLayout getConversationList() {
return conversationListLayout;
}
@Override
public void setConversationTop(ConversationInfo conversation, IUIKitCallback callBack) {}
@Override
public void deleteConversation(ConversationInfo conversation) {
if (presenter != null) {
presenter.deleteConversation(conversation);
}
}
@Override
public void clearConversationMessage(ConversationInfo conversation) {}
@Override
public void markConversationHidden(ConversationInfo conversation) {
if (presenter != null) {
presenter.markConversationHidden(conversation, true);
}
}
@Override
public void markConversationUnread(ConversationInfo conversationInfo, boolean markUnread) {
if (presenter != null) {
presenter.markConversationUnread(conversationInfo, markUnread);
}
}
@Override
public void hideFoldedItem(boolean needHide) {}
@Override
public void clearUnreadStatusOfFoldItem() {}
@Override
public TitleBarLayout getTitleBar() {
return titleBarLayout;
}
@Override
public void setParentLayout(Object parent) {}
}

View File

@@ -0,0 +1,91 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.widget;
import android.content.Context;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import com.tencent.qcloud.tuikit.timcommon.component.CustomLinearLayoutManager;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces.IConversationListLayout;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces.OnConversationAdapterListener;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationFoldPresenter;
public class FoldedConversationListLayout extends RecyclerView implements IConversationListLayout {
private ConversationListAdapter mAdapter;
private ConversationFoldPresenter presenter;
private boolean isFolded = false;
public FoldedConversationListLayout(Context context) {
super(context);
init();
}
public FoldedConversationListLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public FoldedConversationListLayout(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void setPresenter(ConversationFoldPresenter presenter) {
this.presenter = presenter;
}
public void init() {
setLayoutFrozen(false);
setItemViewCacheSize(0);
setHasFixedSize(true);
setFocusableInTouchMode(false);
CustomLinearLayoutManager linearLayoutManager = new CustomLinearLayoutManager(getContext());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
setLayoutManager(linearLayoutManager);
SimpleItemAnimator animator = (SimpleItemAnimator) getItemAnimator();
if (animator != null) {
animator.setSupportsChangeAnimations(false);
}
}
@Override
public void setBackground(int resId) {
setBackgroundColor(resId);
}
@Override
public void disableItemUnreadDot(boolean flag) {
mAdapter.disableItemUnreadDot(flag);
}
@Override
public FoldedConversationListLayout getListLayout() {
return this;
}
@Override
public ConversationListAdapter getAdapter() {
return mAdapter;
}
@Override
public void setAdapter(IConversationListAdapter adapter) {
if (adapter instanceof ConversationListAdapter) {
super.setAdapter((ConversationListAdapter) adapter);
mAdapter = (ConversationListAdapter) adapter;
}
}
@Override
public void setOnConversationAdapterListener(OnConversationAdapterListener listener) {
mAdapter.setOnConversationAdapterListener(listener);
}
public void loadConversation() {
if (presenter != null) {
presenter.loadConversation();
}
}
}

View File

@@ -0,0 +1,80 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.widget;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import java.util.List;
public class ForwardConversationSelectorAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private List<ConversationInfo> list;
private OnItemClickListener mOnItemClickListener;
public ForwardConversationSelectorAdapter(Context context) {
this.context = context;
}
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
}
@NonNull
@Override
public ConversationViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ConversationViewHolder(LayoutInflater.from(context).inflate(R.layout.conversation_forward_conversation_selector_item, parent, false));
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
ConversationViewHolder viewHolder = (ConversationViewHolder) holder;
viewHolder.conversationUserIconView.setVisibility(View.VISIBLE);
viewHolder.conversationUserIconView.setConversation(list.get(position));
viewHolder.conversationUserIconView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mOnItemClickListener.onClick(v, position);
}
});
}
public void setDataSource(List<ConversationInfo> dataSource) {
if (dataSource == null) {
if (list != null) {
list.clear();
}
} else {
list = dataSource;
}
notifyDataSetChanged();
}
@Override
public int getItemCount() {
return list == null ? 0 : list.size();
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.mOnItemClickListener = listener;
}
public interface OnItemClickListener {
void onClick(View view, int position);
}
static class ConversationViewHolder extends RecyclerView.ViewHolder {
public ConversationIconView conversationUserIconView;
public ConversationViewHolder(View itemView) {
super(itemView);
conversationUserIconView = itemView.findViewById(R.id.conversation_user_icon_view);
}
}
}

View File

@@ -0,0 +1,87 @@
package com.tencent.qcloud.tuikit.tuiconversation.classicui.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
import com.tencent.qcloud.tuikit.timcommon.component.TitleBarLayout;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.classicui.interfaces.IConversationLayout;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationPresenter;
public class ForwardSelectLayout extends RelativeLayout implements IConversationLayout {
private TitleBarLayout titleBarLayout;
private ConversationListLayout conversationList;
private ConversationPresenter presenter;
public ForwardSelectLayout(Context context) {
super(context);
init();
}
public ForwardSelectLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ForwardSelectLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void setPresenter(ConversationPresenter presenter) {
this.presenter = presenter;
if (conversationList != null) {
conversationList.setPresenter(presenter);
}
}
private void init() {
inflate(getContext(), R.layout.conversation_forward_layout, this);
titleBarLayout = findViewById(R.id.conversation_title);
conversationList = findViewById(R.id.conversation_list);
}
public void initDefault() {
final ConversationListAdapter adapter = new ConversationListAdapter();
adapter.setForwardFragment(true);
conversationList.setAdapter((IConversationListAdapter) adapter);
presenter.setAdapter(adapter);
presenter.loadMoreConversation();
}
public TitleBarLayout getTitleBar() {
return titleBarLayout;
}
@Override
public void setParentLayout(Object parent) {}
@Override
public ConversationListLayout getConversationList() {
return conversationList;
}
@Override
public void setConversationTop(ConversationInfo conversation, IUIKitCallback callBack) {}
@Override
public void deleteConversation(ConversationInfo conversation) {}
@Override
public void clearConversationMessage(ConversationInfo conversation) {}
@Override
public void markConversationHidden(ConversationInfo conversation) {}
@Override
public void hideFoldedItem(boolean needHide) {}
@Override
public void clearUnreadStatusOfFoldItem() {}
@Override
public void markConversationUnread(ConversationInfo conversationInfo, boolean markRead) {}
}

View File

@@ -0,0 +1,215 @@
package com.tencent.qcloud.tuikit.tuiconversation.commonutil;
import android.text.TextUtils;
import android.view.View;
import android.widget.ListView;
import com.tencent.imsdk.v2.V2TIMConversation;
import com.tencent.imsdk.v2.V2TIMGroupAtInfo;
import com.tencent.imsdk.v2.V2TIMManager;
import com.tencent.imsdk.v2.V2TIMMessage;
import com.tencent.qcloud.tuicore.TUIConfig;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopDialogAdapter;
import com.tencent.qcloud.tuikit.timcommon.util.DateTimeUtil;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.TUIConversationService;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.bean.DraftInfo;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
public class ConversationUtils {
private static final String TAG = ConversationUtils.class.getSimpleName();
public static List<ConversationInfo> convertV2TIMConversationList(List<V2TIMConversation> conversationList) {
List<ConversationInfo> conversationInfoList = new ArrayList<>();
if (conversationList != null) {
for (V2TIMConversation conversation : conversationList) {
conversationInfoList.add(convertV2TIMConversation(conversation));
}
}
return conversationInfoList;
}
public static ConversationInfo convertV2TIMConversation(final V2TIMConversation conversation) {
if (conversation == null) {
return null;
}
TUIConversationLog.i(TAG,
"TIMConversation2ConversationInfo id:" + conversation.getConversationID() + "|name:" + conversation.getShowName()
+ "|unreadNum:" + conversation.getUnreadCount());
final ConversationInfo info = new ConversationInfo();
info.setConversation(conversation);
int type = conversation.getType();
if (type != V2TIMConversation.V2TIM_C2C && type != V2TIMConversation.V2TIM_GROUP) {
return null;
}
String draftText = conversation.getDraftText();
if (!TextUtils.isEmpty(draftText)) {
DraftInfo draftInfo = new DraftInfo();
draftInfo.setDraftText(draftText);
draftInfo.setDraftTime(conversation.getDraftTimestamp());
info.setDraft(draftInfo);
}
V2TIMMessage message = conversation.getLastMessage();
if (message == null) {
long time = DateTimeUtil.getStringToDate("0001-01-01 00:00:00", "yyyy-MM-dd HH:mm:ss");
info.setLastMessageTime(time);
} else {
info.setLastMessageTime(message.getTimestamp());
info.setLastMessage(message);
}
int atInfoType = getAtInfoType(conversation);
switch (atInfoType) {
case V2TIMGroupAtInfo.TIM_AT_ME:
info.setAtInfoText(TUIConversationService.getAppContext().getString(R.string.ui_at_me));
info.setAtType(ConversationInfo.AT_TYPE_AT_ME);
break;
case V2TIMGroupAtInfo.TIM_AT_ALL:
info.setAtInfoText(TUIConversationService.getAppContext().getString(R.string.ui_at_all));
info.setAtType(ConversationInfo.AT_TYPE_AT_ALL);
break;
case V2TIMGroupAtInfo.TIM_AT_ALL_AT_ME:
info.setAtInfoText(TUIConversationService.getAppContext().getString(R.string.ui_at_all_me));
info.setAtType(ConversationInfo.AT_TYPE_AT_ALL_AND_ME);
break;
default:
info.setAtInfoText("");
break;
}
info.setTitle(conversation.getShowName());
List<Object> faceList = new ArrayList<>();
boolean isGroup = type == V2TIMConversation.V2TIM_GROUP;
if (isGroup) {
if (!TextUtils.isEmpty(conversation.getFaceUrl())) {
faceList.add(conversation.getFaceUrl());
}
} else {
if (TextUtils.isEmpty(conversation.getFaceUrl())) {
faceList.add(TUIConfig.getDefaultAvatarImage());
} else {
faceList.add(conversation.getFaceUrl());
}
}
info.setIconPath(conversation.getFaceUrl());
info.setIconUrlList(faceList);
if (isGroup) {
info.setId(conversation.getGroupID());
info.setGroupType(conversation.getGroupType());
} else {
info.setId(conversation.getUserID());
}
if (V2TIMManager.GROUP_TYPE_MEETING.equals(conversation.getGroupType())) {
info.setShowDisturbIcon(false);
} else {
info.setShowDisturbIcon(conversation.getRecvOpt() == V2TIMMessage.V2TIM_RECEIVE_NOT_NOTIFY_MESSAGE);
}
info.setConversationId(conversation.getConversationID());
info.setGroup(isGroup);
if (!V2TIMManager.GROUP_TYPE_AVCHATROOM.equals(conversation.getGroupType())) {
info.setUnRead(conversation.getUnreadCount());
}
info.setTop(conversation.isPinned());
info.setOrderKey(conversation.getOrderKey());
if (conversation.getMarkList() != null) {
if (conversation.getMarkList().contains(V2TIMConversation.V2TIM_CONVERSATION_MARK_TYPE_FOLD)) {
info.setMarkFold(true);
} else {
info.setMarkFold(false);
}
if (conversation.getMarkList().contains(V2TIMConversation.V2TIM_CONVERSATION_MARK_TYPE_UNREAD)) {
info.setMarkUnread(true);
} else {
info.setMarkUnread(false);
}
if (conversation.getMarkList().contains(V2TIMConversation.V2TIM_CONVERSATION_MARK_TYPE_HIDE)) {
info.setMarkHidden(true);
} else {
info.setMarkHidden(false);
}
if (conversation.getMarkList().contains(V2TIMConversation.V2TIM_CONVERSATION_MARK_TYPE_STAR)) {
info.setMarkStar(true);
} else {
info.setMarkStar(false);
}
}
return info;
}
private static int getAtInfoType(V2TIMConversation conversation) {
int atInfoType = 0;
boolean atMe = false;
boolean atAll = false;
List<V2TIMGroupAtInfo> atInfoList = conversation.getGroupAtInfoList();
if (atInfoList == null || atInfoList.isEmpty()) {
return V2TIMGroupAtInfo.TIM_AT_UNKNOWN;
}
for (V2TIMGroupAtInfo atInfo : atInfoList) {
if (atInfo.getAtType() == V2TIMGroupAtInfo.TIM_AT_ME) {
atMe = true;
continue;
}
if (atInfo.getAtType() == V2TIMGroupAtInfo.TIM_AT_ALL) {
atAll = true;
continue;
}
if (atInfo.getAtType() == V2TIMGroupAtInfo.TIM_AT_ALL_AT_ME) {
atMe = true;
atAll = true;
continue;
}
}
if (atAll && atMe) {
atInfoType = V2TIMGroupAtInfo.TIM_AT_ALL_AT_ME;
} else if (atAll) {
atInfoType = V2TIMGroupAtInfo.TIM_AT_ALL;
} else if (atMe) {
atInfoType = V2TIMGroupAtInfo.TIM_AT_ME;
} else {
atInfoType = V2TIMGroupAtInfo.TIM_AT_UNKNOWN;
}
return atInfoType;
}
public static boolean isIgnored(ConversationInfo conversationInfo) {
if (V2TIMManager.GROUP_TYPE_AVCHATROOM.equals(conversationInfo.getGroupType())) {
return true;
}
return false;
}
public static int getListUnspecifiedWidth(PopDialogAdapter adapter, ListView listView) {
if (adapter == null || listView == null) {
return 0;
}
int maxWidth = 0;
View convertView = null;
int childCount = adapter.getCount();
if (childCount <= 0) {
return 0;
}
for (int i = 0; i < childCount; i++) {
View child = adapter.getView(i, convertView, listView);
child.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
maxWidth = Math.max(maxWidth, child.getMeasuredWidth() + child.getPaddingLeft() + child.getPaddingRight());
convertView = child;
}
return maxWidth;
}
public static String getConversationAllGroupName() {
return TUIConversationService.getAppContext().getResources().getString(R.string.conversation_page_all);
}
}

View File

@@ -0,0 +1,35 @@
package com.tencent.qcloud.tuikit.tuiconversation.commonutil;
import com.tencent.imsdk.common.IMLog;
public class TUIConversationLog extends IMLog {
private static final String PRE = "TUIConversation-";
private static String mixTag(String tag) {
return PRE + tag;
}
public static void v(String strTag, String strInfo) {
IMLog.v(mixTag(strTag), strInfo);
}
public static void d(String strTag, String strInfo) {
IMLog.d(mixTag(strTag), strInfo);
}
public static void i(String strTag, String strInfo) {
IMLog.i(mixTag(strTag), strInfo);
}
public static void w(String strTag, String strInfo) {
IMLog.w(mixTag(strTag), strInfo);
}
public static void w(String strTag, String strInfo, Throwable e) {
IMLog.w(mixTag(strTag), strInfo + e.getMessage());
}
public static void e(String strTag, String strInfo) {
IMLog.e(mixTag(strTag), strInfo);
}
}

View File

@@ -0,0 +1,33 @@
package com.tencent.qcloud.tuikit.tuiconversation.commonutil;
import com.tencent.imsdk.v2.V2TIMMessage;
import com.tencent.qcloud.tuicore.util.ErrorMessageConverter;
import com.tencent.qcloud.tuikit.timcommon.bean.TUIMessageBean;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
public class TUIConversationUtils {
public static <T> void callbackOnError(IUIKitCallback<T> callBack, String module, int errCode, String desc) {
if (callBack != null) {
callBack.onError(module, errCode, ErrorMessageConverter.convertIMError(errCode, desc));
}
}
public static <T> void callbackOnError(IUIKitCallback<T> callBack, int errCode, String desc) {
if (callBack != null) {
callBack.onError(null, errCode, ErrorMessageConverter.convertIMError(errCode, desc));
}
}
public static <T> void callbackOnSuccess(IUIKitCallback<T> callBack, T data) {
if (callBack != null) {
callBack.onSuccess(data);
}
}
public static boolean hasRiskContent(V2TIMMessage v2TIMMessage) {
if (v2TIMMessage != null) {
return v2TIMMessage.hasRiskContent() && v2TIMMessage.getStatus() != V2TIMMessage.V2TIM_MSG_STATUS_LOCAL_REVOKED;
}
return false;
}
}

View File

@@ -0,0 +1,23 @@
package com.tencent.qcloud.tuikit.tuiconversation.config;
public class TUIConversationConfig {
public static final String TAG = TUIConversationConfig.class.getSimpleName();
private static TUIConversationConfig instance;
private boolean isShowUserStatus;
public static TUIConversationConfig getInstance() {
if (instance == null) {
instance = new TUIConversationConfig();
}
return instance;
}
public boolean isShowUserStatus() {
return isShowUserStatus;
}
public void setShowUserStatus(boolean showUserStatus) {
isShowUserStatus = showUserStatus;
}
}

View File

@@ -0,0 +1,227 @@
package com.tencent.qcloud.tuikit.tuiconversation.config.classicui;
import static com.tencent.qcloud.tuikit.timcommon.util.TUIUtil.newDrawable;
import android.graphics.drawable.Drawable;
import androidx.annotation.IntDef;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopMenuAction;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationPopMenuItem;
import com.tencent.qcloud.tuikit.tuiconversation.config.TUIConversationConfig;
import java.util.ArrayList;
import java.util.List;
public class TUIConversationConfigClassic {
public static final int UNDEFINED = -1;
private TUIConversationConfigClassic() {}
private static final class TUIConversationConfigClassicHolder {
private static final TUIConversationConfigClassic INSTANCE = new TUIConversationConfigClassic();
}
private static TUIConversationConfigClassic getInstance() {
return TUIConversationConfigClassicHolder.INSTANCE;
}
public static final int HIDE = 1;
public static final int DELETE = 2;
@IntDef({HIDE, DELETE})
public @interface ConversationMenuItem {}
private Drawable listBackground;
private Drawable cellBackground;
private Drawable pinnedCellBackground;
private int cellTitleLabelFontSize = UNDEFINED;
private int cellSubtitleLabelFontSize = UNDEFINED;
private int cellTimeLabelFontSize = UNDEFINED;
private int avatarCornerRadius = UNDEFINED;
private boolean showCellUnreadCount = true;
private ConversationMenuItemDataSource conversationMenuItemDataSource;
/**
* Set the background of the conversation list
* @param listBackground
*/
public static void setListBackground(Drawable listBackground) {
getInstance().listBackground = listBackground;
}
/**
* Get the background of the conversation list
* @return
*/
public static Drawable getListBackground() {
return newDrawable(getInstance().listBackground);
}
/**
* Set the background of the conversation cell
* @param cellBackground
*/
public static void setCellBackground(Drawable cellBackground) {
getInstance().cellBackground = cellBackground;
}
/**
* Get the background of the conversation cell
* @return
*/
public static Drawable getCellBackground() {
return newDrawable(getInstance().cellBackground);
}
/**
* Set the background of the pinned conversation cell
* @param pinnedCellBackground
*/
public static void setPinnedCellBackground(Drawable pinnedCellBackground) {
getInstance().pinnedCellBackground = pinnedCellBackground;
}
/**
* Get the background of the pinned conversation cell
* @return
*/
public static Drawable getPinnedCellBackground() {
return newDrawable(getInstance().pinnedCellBackground);
}
/**
* Set the font size of the conversation cell title label
* @param cellTitleLabelFontSize
*/
public static void setCellTitleLabelFontSize(int cellTitleLabelFontSize) {
getInstance().cellTitleLabelFontSize = cellTitleLabelFontSize;
}
/**
* Get the font size of the conversation cell title label
* @return
*/
public static int getCellTitleLabelFontSize() {
return getInstance().cellTitleLabelFontSize;
}
/**
* Set the font size of the conversation cell subtitle label
* @param cellSubtitleLabelFontSize
*/
public static void setCellSubtitleLabelFontSize(int cellSubtitleLabelFontSize) {
getInstance().cellSubtitleLabelFontSize = cellSubtitleLabelFontSize;
}
/**
* Get the font size of the conversation cell subtitle label
* @return
*/
public static int getCellSubtitleLabelFontSize() {
return getInstance().cellSubtitleLabelFontSize;
}
/**
* Set the font size of the conversation cell time label
* @param cellTimeLabelFontSize
*/
public static void setCellTimeLabelFontSize(int cellTimeLabelFontSize) {
getInstance().cellTimeLabelFontSize = cellTimeLabelFontSize;
}
/**
* Get the font size of the conversation cell time label
* @return
*/
public static int getCellTimeLabelFontSize() {
return getInstance().cellTimeLabelFontSize;
}
/**
* Set the corner radius of the conversation cell avatar
* @param avatarCornerRadius
*/
public static void setAvatarCornerRadius(int avatarCornerRadius) {
getInstance().avatarCornerRadius = avatarCornerRadius;
}
/**
* Get the corner radius of the conversation cell avatar
* @return
*/
public static int getAvatarCornerRadius() {
return getInstance().avatarCornerRadius;
}
/**
* Set whether to show the user online status icon
* @param showUserOnlineStatusIcon
*/
public static void setShowUserOnlineStatusIcon(boolean showUserOnlineStatusIcon) {
TUIConversationConfig.getInstance().setShowUserStatus(showUserOnlineStatusIcon);
}
/**
* Get whether to show the user online status icon on the conversation cell
* @return
*/
public static boolean isShowUserOnlineStatusIcon() {
return TUIConversationConfig.getInstance().isShowUserStatus();
}
/**
* Set whether to show the unread count of the conversation cell
* @param showCellUnreadCount
*/
public static void setShowCellUnreadCount(boolean showCellUnreadCount) {
getInstance().showCellUnreadCount = showCellUnreadCount;
}
/**
* Get whether to show the unread count of the conversation cell
* @return
*/
public static boolean isShowCellUnreadCount() {
return getInstance().showCellUnreadCount;
}
/**
* Set the data source of the conversation long-press menu item
* @param conversationMenuItemDataSource
* @see ConversationMenuItemDataSource
*/
public static void setConversationMenuItemDataSource(ConversationMenuItemDataSource conversationMenuItemDataSource) {
getInstance().conversationMenuItemDataSource = conversationMenuItemDataSource;
}
/**
* Get the data source of the conversation long-press menu item
* @return the data source
* @see ConversationMenuItemDataSource
*/
public static ConversationMenuItemDataSource getConversationMenuItemDataSource() {
return getInstance().conversationMenuItemDataSource;
}
public interface ConversationMenuItemDataSource {
/**
* Implement this method to add new items.
* @param conversationInfo
* @return the items to be added
*/
default List<PopMenuAction> conversationShouldAddNewItemsToMoreMenu(ConversationInfo conversationInfo) {
return new ArrayList<>();
}
/**
* Implement this method to hide items in more menu.
* @param conversationInfo
* @return the items to be hidden
*/
default @ConversationMenuItem List<Integer> conversationShouldHideItemsInMoreMenu(ConversationInfo conversationInfo) {
return new ArrayList<>();
}
}
}

View File

@@ -0,0 +1,227 @@
package com.tencent.qcloud.tuikit.tuiconversation.config.minimalistui;
import static com.tencent.qcloud.tuikit.timcommon.util.TUIUtil.newDrawable;
import android.graphics.drawable.Drawable;
import androidx.annotation.IntDef;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationPopMenuItem;
import com.tencent.qcloud.tuikit.tuiconversation.config.TUIConversationConfig;
import com.tencent.qcloud.tuikit.tuiconversation.config.classicui.TUIConversationConfigClassic;
import java.util.ArrayList;
import java.util.List;
public class TUIConversationConfigMinimalist {
public static final int UNDEFINED = -1;
private TUIConversationConfigMinimalist() {}
private static final class TUIConversationConfigMinimalistHolder {
private static final TUIConversationConfigMinimalist INSTANCE = new TUIConversationConfigMinimalist();
}
private static TUIConversationConfigMinimalist getInstance() {
return TUIConversationConfigMinimalistHolder.INSTANCE;
}
public static final int HIDE = 1;
public static final int PIN = 2;
public static final int CLEAR = 3;
public static final int DELETE = 4;
@IntDef({HIDE, PIN, CLEAR, DELETE})
public @interface ConversationMenuItem {}
private Drawable listBackground;
private Drawable cellBackground;
private Drawable pinnedCellBackground;
private int cellTitleLabelFontSize = UNDEFINED;
private int cellSubtitleLabelFontSize = UNDEFINED;
private int cellTimeLabelFontSize = UNDEFINED;
private int avatarCornerRadius = UNDEFINED;
private boolean showCellUnreadCount = true;
private ConversationMenuItemDataSource conversationMenuItemDataSource;
/**
* Set the background of the conversation list
* @param listBackground
*/
public static void setListBackground(Drawable listBackground) {
getInstance().listBackground = listBackground;
}
/**
* Get the background of the conversation list
* @return
*/
public static Drawable getListBackground() {
return newDrawable(getInstance().listBackground);
}
/**
* Set the background of the conversation cell
* @param cellBackground
*/
public static void setCellBackground(Drawable cellBackground) {
getInstance().cellBackground = cellBackground;
}
/**
* Get the background of the conversation cell
* @return
*/
public static Drawable getCellBackground() {
return newDrawable(getInstance().cellBackground);
}
/**
* Set the background of the pinned conversation cell
* @param pinnedCellBackground
*/
public static void setPinnedCellBackground(Drawable pinnedCellBackground) {
getInstance().pinnedCellBackground = pinnedCellBackground;
}
/**
* Get the background of the pinned conversation cell
* @return
*/
public static Drawable getPinnedCellBackground() {
return newDrawable(getInstance().pinnedCellBackground);
}
/**
* Set the font size of the conversation cell title label
* @param cellTitleLabelFontSize
*/
public static void setCellTitleLabelFontSize(int cellTitleLabelFontSize) {
getInstance().cellTitleLabelFontSize = cellTitleLabelFontSize;
}
/**
* Get the font size of the conversation cell title label
* @return
*/
public static int getCellTitleLabelFontSize() {
return getInstance().cellTitleLabelFontSize;
}
/**
* Set the font size of the conversation cell subtitle label
* @param cellSubtitleLabelFontSize
*/
public static void setCellSubtitleLabelFontSize(int cellSubtitleLabelFontSize) {
getInstance().cellSubtitleLabelFontSize = cellSubtitleLabelFontSize;
}
/**
* Get the font size of the conversation cell subtitle label
* @return
*/
public static int getCellSubtitleLabelFontSize() {
return getInstance().cellSubtitleLabelFontSize;
}
/**
* Set the font size of the conversation cell time label
* @param cellTimeLabelFontSize
*/
public static void setCellTimeLabelFontSize(int cellTimeLabelFontSize) {
getInstance().cellTimeLabelFontSize = cellTimeLabelFontSize;
}
/**
* Get the font size of the conversation cell time label
* @return
*/
public static int getCellTimeLabelFontSize() {
return getInstance().cellTimeLabelFontSize;
}
/**
* Set the corner radius of the conversation cell avatar
* @param avatarCornerRadius
*/
public static void setAvatarCornerRadius(int avatarCornerRadius) {
getInstance().avatarCornerRadius = avatarCornerRadius;
}
/**
* Get the corner radius of the conversation cell avatar
* @return
*/
public static int getAvatarCornerRadius() {
return getInstance().avatarCornerRadius;
}
/**
* Set whether to show the user online status icon
* @param showUserOnlineStatusIcon
*/
public static void setShowUserOnlineStatusIcon(boolean showUserOnlineStatusIcon) {
TUIConversationConfig.getInstance().setShowUserStatus(showUserOnlineStatusIcon);
}
/**
* Get whether to show the user online status icon on the conversation cell
* @return
*/
public static boolean isShowUserOnlineStatusIcon() {
return TUIConversationConfig.getInstance().isShowUserStatus();
}
/**
* Set whether to show the unread count of the conversation cell
* @param showCellUnreadCount
*/
public static void setShowCellUnreadCount(boolean showCellUnreadCount) {
getInstance().showCellUnreadCount = showCellUnreadCount;
}
/**
* Get whether to show the unread count of the conversation cell
* @return
*/
public static boolean isShowCellUnreadCount() {
return getInstance().showCellUnreadCount;
}
/**
* Set the data source of the conversation long-press menu item
* @param conversationMenuItemDataSource
* @see TUIConversationConfigClassic.ConversationMenuItemDataSource
*/
public static void setConversationMenuItemDataSource(ConversationMenuItemDataSource conversationMenuItemDataSource) {
getInstance().conversationMenuItemDataSource = conversationMenuItemDataSource;
}
/**
* Get the data source of the conversation long-press menu item
* @return the data source
* @see TUIConversationConfigClassic.ConversationMenuItemDataSource
*/
public static ConversationMenuItemDataSource getConversationMenuItemDataSource() {
return getInstance().conversationMenuItemDataSource;
}
public interface ConversationMenuItemDataSource {
/**
* Implement this method to add new items.
* @param conversationInfo
* @return the items to be added
*/
default List<ConversationPopMenuItem> conversationShouldAddNewItemsToMoreMenu(ConversationInfo conversationInfo) {
return new ArrayList<>();
}
/**
* Implement this method to hide items in more menu.
* @param conversationInfo
* @return the items to be hidden
*/
default @ConversationMenuItem List<Integer> conversationShouldHideItemsInMoreMenu(ConversationInfo conversationInfo) {
return new ArrayList<>();
}
}
}

View File

@@ -0,0 +1,45 @@
package com.tencent.qcloud.tuikit.tuiconversation.interfaces;
import com.tencent.imsdk.v2.V2TIMUserStatus;
import com.tencent.qcloud.tuikit.timcommon.bean.TUIMessageBean;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import java.util.List;
public interface ConversationEventListener {
void deleteConversation(String chatId, boolean isGroup);
void clearConversationMessage(String chatId, boolean isGroup);
void clearFoldMarkAndDeleteConversation(String conversationId);
void setConversationTop(String chatId, boolean isChecked, IUIKitCallback<Void> iuiKitCallBack);
boolean isTopConversation(String chatId);
long getUnreadTotal();
void onSyncServerFinish();
void updateTotalUnreadMessageCount(long count);
void onNewConversation(List<ConversationInfo> conversationList);
void onConversationChanged(List<ConversationInfo> conversationList);
void onFriendRemarkChanged(String id, String remark);
void onUserStatusChanged(List<V2TIMUserStatus> userStatusList);
void refreshUserStatusFragmentUI();
void onReceiveMessage(String conversationID, boolean isTypingMessage);
void onMessageSendForHideConversation(String conversationID);
void onConversationDeleted(List<String> conversationIDList);
void onConversationLastMessageBeanChanged(String conversationID, TUIMessageBean messageBean);
}

View File

@@ -0,0 +1,18 @@
package com.tencent.qcloud.tuikit.tuiconversation.interfaces;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationGroupBean;
import java.util.List;
public interface ConversationGroupNotifyListener {
void notifyGroupsAdd(List<ConversationGroupBean> beans);
void notifyMarkGroupsAdd(List<ConversationGroupBean> beans);
void notifyGroupAdd(ConversationGroupBean bean);
void notifyGroupDelete(String groupName);
void notifyGroupRename(String oldName, String newName);
void notifyGroupUnreadMessageCountChanged(String groupName, long totalUnreadCount);
}

View File

@@ -0,0 +1,33 @@
package com.tencent.qcloud.tuikit.tuiconversation.interfaces;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import java.util.List;
public interface IConversationListAdapter {
/**
* Get the entry data of the adapter, which returns the ConversationInfo object or its sub-objects
*
* @param position
* @return ConversationInfo
*/
ConversationInfo getItem(int position);
void onLoadingStateChanged(boolean isLoading);
void onDataSourceChanged(List<ConversationInfo> conversationInfoList);
void onViewNeedRefresh();
void onItemRemoved(int position);
default void onItemMoved(int fromPosition, int toPosition) {}
void onItemInserted(int position);
void onItemChanged(int position);
void onItemRangeChanged(int startPosition, int count);
void onConversationChanged(List<ConversationInfo> conversationInfoList);
}

View File

@@ -0,0 +1,38 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces;
import android.view.View;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.ILayout;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
public interface IConversationLayout extends ILayout {
View getConversationList();
void setConversationTop(ConversationInfo conversation, IUIKitCallback callBack);
void deleteConversation(ConversationInfo conversation);
void clearConversationMessage(ConversationInfo conversation);
/**
* Hide normal conversation
*/
void markConversationHidden(ConversationInfo conversation);
/**
* Mark conversation read or unread
*/
void markConversationUnread(ConversationInfo conversationInfo, boolean markUnread);
/**
* Hide folded conversation item
*/
void hideFoldedItem(boolean needHide);
/**
* item
* Clear unread status of fold item
*/
void clearUnreadStatusOfFoldItem();
}

View File

@@ -0,0 +1,23 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces;
import android.view.View;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.ConversationListAdapter;
public interface IConversationListLayout {
void setBackground(int resId);
void setOnConversationAdapterListener(OnConversationAdapterListener listener);
/**
* Do not display the switch for the number of unread messages with the small red dot
*/
void disableItemUnreadDot(boolean flag);
View getListLayout();
ConversationListAdapter getAdapter();
void setAdapter(IConversationListAdapter adapter);
}

View File

@@ -0,0 +1,49 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import java.util.List;
public interface IConversationProvider {
/**
* Get a specific session data set, and ConversationContainer displays the session list based on the data set
*
* @return
*/
List<ConversationInfo> getDataSource();
/**
* Bulk add session entries
*
* @param conversations
* @return
*/
boolean addConversations(List<ConversationInfo> conversations);
/**
* Delete session entries
*
* @param conversations
* @return
*/
boolean deleteConversations(List<ConversationInfo> conversations);
/**
* Update session entries
*
* @param conversations
* @return
*/
boolean updateConversations(List<ConversationInfo> conversations);
/**
* Called when a session adapter is bound, automatically called when {@link
* com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter#setDataProvider} is called
*
* @param adapter UI
* @return
*/
void attachAdapter(IConversationListAdapter adapter);
}

View File

@@ -0,0 +1,23 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces;
import android.view.View;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import java.util.List;
public interface OnConversationAdapterListener {
void onItemClick(View view, int viewType, ConversationInfo conversationInfo);
void onItemLongClick(View view, ConversationInfo conversationInfo);
void onConversationChanged(List<ConversationInfo> dataSource);
void onMarkConversationUnread(View view, ConversationInfo conversationInfo, boolean markUnread);
void onMarkConversationHidden(View view, ConversationInfo conversationInfo);
void onClickMoreView(View view, ConversationInfo conversationInfo);
void onSwipeConversationChanged(ConversationInfo conversationInfo);
}

View File

@@ -0,0 +1,567 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.page;
import android.app.AlertDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopActionClickListener;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopMenuAction;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.timcommon.util.ScreenUtil;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.TUIConversationConstants;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationPopMenuItem;
import com.tencent.qcloud.tuikit.tuiconversation.config.minimalistui.TUIConversationConfigMinimalist;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces.OnConversationAdapterListener;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.util.TUIConversationUtils;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.ConversationLayout;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.ConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.Menu;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationPresenter;
import java.util.ArrayList;
import java.util.List;
public class TUIConversationMinimalistFragment extends Fragment {
private View mBaseView;
private ConversationLayout mConversationLayout;
private AlertDialog mBottomDialog;
private boolean isShowReadButton;
private boolean isShowReadAllButton;
private BroadcastReceiver unreadCountReceiver;
private Menu menu;
private ConversationPresenter presenter;
private ConversationListAdapter mAdapter;
private String title;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
mBaseView = inflater.inflate(R.layout.minimalistui_conversation_fragment, container, false);
initView();
return mBaseView;
}
@Override
public void onResume() {
super.onResume();
mConversationLayout.initUI();
}
private void initView() {
mConversationLayout = mBaseView.findViewById(R.id.conversation_layout);
presenter = new ConversationPresenter();
presenter.setConversationListener();
presenter.setShowType(ConversationPresenter.SHOW_TYPE_CONVERSATION_LIST_WITH_FOLD);
mConversationLayout.setPresenter(presenter);
mConversationLayout.initDefault();
if (!TextUtils.isEmpty(title)) {
mConversationLayout.setTitle(title);
}
isShowReadButton = false;
isShowReadAllButton = false;
mAdapter = mConversationLayout.getConversationList().getAdapter();
mConversationLayout.getConversationList().setOnConversationAdapterListener(new OnConversationAdapterListener() {
@Override
public void onItemClick(View view, int viewType, ConversationInfo conversationInfo) {
if (mConversationLayout.isMultiSelected()) {
if (mAdapter == null) {
refreshEditConversationDialog(0);
return;
}
List<ConversationInfo> mSelectConversations = mAdapter.getSelectedItem();
if (mSelectConversations == null) {
refreshEditConversationDialog(0);
return;
}
isShowReadButton = false;
for (ConversationInfo conversation : mSelectConversations) {
if (conversation.isMarkUnread() || conversation.getUnRead() > 0) {
isShowReadButton = true;
break;
}
}
refreshEditConversationDialog(mSelectConversations.size());
} else if (conversationInfo.isMarkFold()) {
mConversationLayout.clearUnreadStatusOfFoldItem();
startFoldedConversationActivity();
} else {
TUIConversationUtils.startChatActivity(conversationInfo);
}
}
@Override
public void onItemLongClick(View view, ConversationInfo conversationInfo) {}
@Override
public void onConversationChanged(List<ConversationInfo> dataSource) {}
@Override
public void onMarkConversationUnread(View view, ConversationInfo conversationInfo, boolean markUnread) {
mConversationLayout.markConversationUnread(conversationInfo, markUnread);
}
@Override
public void onMarkConversationHidden(View view, ConversationInfo conversationInfo) {
mConversationLayout.markConversationHidden(conversationInfo);
}
@Override
public void onClickMoreView(View view, ConversationInfo conversationInfo) {
showConversationMoreActionDialog(conversationInfo);
}
@Override
public void onSwipeConversationChanged(ConversationInfo conversationInfo) {}
});
mConversationLayout.setOnClickListener(new OnClickListener() {
@Override
public void onEditConversationStartClick() {
showEditConversationDialog();
}
@Override
public void onEditConversationEndClick() {
closeEditConversationDialog();
}
@Override
public void onStartChatClick() {
if (menu == null) {
return;
}
if (menu.isShowing()) {
menu.hide();
} else {
menu.show();
}
}
@Override
public void finishActivity() {
getActivity().finish();
}
});
initUnreadCountReceiver();
restoreConversationItemBackground();
setConversationMenu();
}
public void restoreConversationItemBackground() {
if (mConversationLayout.getConversationList().getAdapter() != null && mConversationLayout.getConversationList().getAdapter().isClick()) {
mConversationLayout.getConversationList().getAdapter().setClick(false);
mConversationLayout.getConversationList().getAdapter().notifyItemChanged(
mConversationLayout.getConversationList().getAdapter().getCurrentPosition());
}
}
public void setConversationTitle(String title) {
if (!TextUtils.isEmpty(title)) {
this.title = title;
if (mConversationLayout != null) {
mConversationLayout.setTitle(title);
}
}
}
private void initUnreadCountReceiver() {
unreadCountReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
long unreadCount = intent.getLongExtra(TUIConstants.UNREAD_COUNT_EXTRA, 0);
if (unreadCount > 0) {
isShowReadAllButton = true;
} else {
isShowReadAllButton = false;
}
}
};
IntentFilter unreadCountFilter = new IntentFilter();
unreadCountFilter.addAction(TUIConstants.CONVERSATION_UNREAD_COUNT_ACTION);
LocalBroadcastManager.getInstance(getContext()).registerReceiver(unreadCountReceiver, unreadCountFilter);
}
private void startFoldedConversationActivity() {
Intent intent = new Intent(getActivity(), TUIFoldedConversationMinimalistActivity.class);
startActivity(intent);
}
public interface OnClickListener {
void onEditConversationStartClick();
void onEditConversationEndClick();
void onStartChatClick();
void finishActivity();
}
private void showEditConversationDialog() {
if (mBottomDialog != null && mBottomDialog.isShowing()) {
return;
}
View view = LayoutInflater.from(getContext()).inflate(R.layout.minimalist_bottom_bar, null, false);
mBottomDialog = new AlertDialog.Builder(getContext()).setView(view).create();
TextView markReadView = view.findViewById(R.id.mark_read);
TextView notDisplayView = view.findViewById(R.id.not_display);
if (isShowReadAllButton) {
markReadView.setAlpha(1f);
markReadView.setEnabled(true);
markReadView.setText(getString(R.string.has_all_read));
} else {
markReadView.setAlpha(0.5f);
markReadView.setEnabled(false);
markReadView.setText(getString(R.string.mark_read));
}
TextView deleteChatView = view.findViewById(R.id.delete_chat);
notDisplayView.setAlpha(0.5f);
notDisplayView.setEnabled(false);
deleteChatView.setAlpha(0.5f);
deleteChatView.setEnabled(false);
markReadView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (markReadView.getText().equals(getString(R.string.has_all_read))) {
presenter.clearAllUnreadMessage();
} else {
if (mAdapter == null) {
resetEditConversationStatus();
return;
}
List<ConversationInfo> mSelectConversations = mAdapter.getSelectedItem();
for (ConversationInfo conversationInfo : mSelectConversations) {
mConversationLayout.markConversationUnread(conversationInfo, false);
}
}
resetEditConversationStatus();
}
});
notDisplayView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mAdapter == null) {
resetEditConversationStatus();
return;
}
List<ConversationInfo> mSelectConversations = mAdapter.getSelectedItem();
for (ConversationInfo conversationInfo : mSelectConversations) {
mConversationLayout.markConversationHidden(conversationInfo);
}
resetEditConversationStatus();
}
});
deleteChatView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mAdapter == null) {
resetEditConversationStatus();
return;
}
List<ConversationInfo> mSelectConversations = mAdapter.getSelectedItem();
for (ConversationInfo conversationInfo : mSelectConversations) {
mConversationLayout.deleteConversation(conversationInfo);
}
resetEditConversationStatus();
}
});
mBottomDialog.setCanceledOnTouchOutside(false);
mBottomDialog.show();
Window win = mBottomDialog.getWindow();
win.setGravity(Gravity.BOTTOM);
win.getDecorView().setPaddingRelative(0, 0, 0, 0);
WindowManager.LayoutParams lp = win.getAttributes();
lp.width = WindowManager.LayoutParams.MATCH_PARENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
mBottomDialog.getWindow().setBackgroundDrawableResource(R.color.conversation_bottom_bg);
win.setAttributes(lp);
win.setDimAmount(0f);
win.setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL);
win.setFlags(WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH, WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
mBottomDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
resetEditConversationStatus();
}
return false;
}
});
}
private void refreshEditConversationDialog(int selectSize) {
if (mBottomDialog == null) {
return;
}
TextView markReadView = mBottomDialog.findViewById(R.id.mark_read);
TextView notDisplayView = mBottomDialog.findViewById(R.id.not_display);
TextView deleteChatView = mBottomDialog.findViewById(R.id.delete_chat);
if (selectSize <= 0) {
deleteChatView.setAlpha(0.5f);
deleteChatView.setEnabled(false);
notDisplayView.setAlpha(0.5f);
notDisplayView.setEnabled(false);
markReadView.setAlpha(1f);
markReadView.setEnabled(true);
markReadView.setText(getString(R.string.has_all_read));
} else {
deleteChatView.setAlpha(1f);
deleteChatView.setEnabled(true);
notDisplayView.setAlpha(1f);
notDisplayView.setEnabled(true);
markReadView.setText(getString(R.string.mark_read));
if (isShowReadButton) {
markReadView.setAlpha(1f);
markReadView.setEnabled(true);
} else {
markReadView.setAlpha(0.5f);
markReadView.setEnabled(false);
}
}
}
private void resetEditConversationStatus() {
isShowReadAllButton = false;
isShowReadButton = false;
if (mBottomDialog != null) {
mBottomDialog.dismiss();
}
mConversationLayout.resetTitleBar();
}
private void closeEditConversationDialog() {
if (mBottomDialog != null) {
mBottomDialog.dismiss();
}
}
private void setConversationMenu() {
menu = new Menu(getActivity(), mConversationLayout.getCreateChatView());
PopActionClickListener popActionClickListener = new PopActionClickListener() {
@Override
public void onActionClick(int position, Object data) {
PopMenuAction action = (PopMenuAction) data;
if (TextUtils.equals(action.getActionName(), getResources().getString(R.string.start_conversation))) {
TUICore.startActivity("StartC2CChatMinimalistActivity", null);
}
if (TextUtils.equals(action.getActionName(), getResources().getString(R.string.create_group_chat))) {
Bundle bundle = new Bundle();
bundle.putInt(TUIConversationConstants.GroupType.TYPE, TUIConversationConstants.GroupType.PUBLIC);
TUICore.startActivity("StartGroupChatMinimalistActivity", bundle);
}
menu.hide();
}
};
PopMenuAction action = new PopMenuAction();
action.setActionName(getResources().getString(R.string.start_conversation));
action.setActionClickListener(popActionClickListener);
action.setIconResId(R.drawable.conversation_create_c2c);
List<PopMenuAction> menuActions = new ArrayList<>();
menuActions.add(action);
action = new PopMenuAction();
action.setActionName(getResources().getString(R.string.create_group_chat));
action.setIconResId(R.drawable.conversation_group_icon);
action.setActionClickListener(popActionClickListener);
menuActions.add(action);
menu.setMenuAction(menuActions);
}
private void showConversationMoreActionDialog(ConversationInfo conversationInfo) {
View view = LayoutInflater.from(getContext()).inflate(R.layout.minimalist_more_dialog, null, false);
LinearLayout layout = view.findViewById(R.id.layout_actions);
AlertDialog moreDialog = new AlertDialog.Builder(getContext()).setView(view).create();
List<ConversationPopMenuItem> itemList = getConversationPopMenuItems(conversationInfo, moreDialog);
for (ConversationPopMenuItem item : itemList) {
View itemView = LayoutInflater.from(getContext()).inflate(R.layout.conversation_minimalist_pop_menu_item, null, false);
TextView textView = itemView.findViewById(R.id.text);
View divider = itemView.findViewById(R.id.divider);
textView.setText(item.text);
if (item.isAlert) {
textView.setTextColor(0xFFFF584C);
}
itemView.setOnClickListener(item.onClickListener);
if (itemList.indexOf(item) == itemList.size() - 1) {
divider.setVisibility(View.GONE);
}
layout.addView(itemView);
}
TextView cancelView = view.findViewById(R.id.cancel_button);
cancelView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
moreDialog.dismiss();
}
});
moreDialog.setCanceledOnTouchOutside(false);
Window win = moreDialog.getWindow();
WindowManager.LayoutParams lp = win.getAttributes();
lp.width = lp.width - ScreenUtil.getPxByDp(16f);
lp.y = ScreenUtil.getPxByDp(34f);
moreDialog.getWindow().setBackgroundDrawableResource(com.tencent.qcloud.tuikit.timcommon.R.color.status_bar_color);
win.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
win.setAttributes(lp);
moreDialog.show();
moreDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
@Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
moreDialog.dismiss();
}
return false;
}
});
}
@NonNull
private List<ConversationPopMenuItem> getConversationPopMenuItems(ConversationInfo conversationInfo, AlertDialog moreDialog) {
List<ConversationPopMenuItem> itemList = new ArrayList<>();
ConversationPopMenuItem pinItem = new ConversationPopMenuItem();
if (conversationInfo.isTop()) {
pinItem.text = getString(R.string.quit_chat_top);
} else {
pinItem.text = getString(R.string.chat_top);
}
pinItem.onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
mConversationLayout.setConversationTop(conversationInfo, new IUIKitCallback() {
@Override
public void onSuccess(Object data) {
super.onSuccess(data);
}
@Override
public void onError(String module, int errCode, String errMsg) {
super.onError(module, errCode, errMsg);
}
});
moreDialog.dismiss();
}
};
itemList.add(pinItem);
ConversationPopMenuItem hideItem = new ConversationPopMenuItem();
hideItem.text = getString(R.string.not_display);
hideItem.onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
mConversationLayout.markConversationHidden(conversationInfo);
moreDialog.dismiss();
}
};
itemList.add(hideItem);
ConversationPopMenuItem clearHistoryItem = new ConversationPopMenuItem();
clearHistoryItem.text = getString(R.string.clear_message);
clearHistoryItem.onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
mConversationLayout.clearConversationMessage(conversationInfo);
if (conversationInfo.isMarkUnread()) {
mConversationLayout.markConversationUnread(conversationInfo, false);
}
moreDialog.dismiss();
}
};
itemList.add(clearHistoryItem);
ConversationPopMenuItem deleteItem = new ConversationPopMenuItem();
deleteItem.text = getString(R.string.chat_delete);
deleteItem.isAlert = true;
deleteItem.onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
mConversationLayout.deleteConversation(conversationInfo);
moreDialog.dismiss();
}
};
itemList.add(deleteItem);
TUIConversationConfigMinimalist.ConversationMenuItemDataSource dataSource = TUIConversationConfigMinimalist.getConversationMenuItemDataSource();
if (dataSource != null) {
List<Integer> excludeList = dataSource.conversationShouldHideItemsInMoreMenu(conversationInfo);
if (excludeList != null && !excludeList.isEmpty()) {
if (excludeList.contains(TUIConversationConfigMinimalist.PIN)) {
itemList.remove(pinItem);
}
if (excludeList.contains(TUIConversationConfigMinimalist.HIDE)) {
itemList.remove(hideItem);
}
if (excludeList.contains(TUIConversationConfigMinimalist.CLEAR)) {
itemList.remove(clearHistoryItem);
}
if (excludeList.contains(TUIConversationConfigMinimalist.DELETE)) {
itemList.remove(deleteItem);
}
}
List<ConversationPopMenuItem> conversationPopMenuItems = dataSource.conversationShouldAddNewItemsToMoreMenu(conversationInfo);
if (conversationPopMenuItems != null && !conversationPopMenuItems.isEmpty()) {
itemList.addAll(conversationPopMenuItems);
}
}
return itemList;
}
@Override
public void onDestroy() {
super.onDestroy();
if (unreadCountReceiver != null) {
LocalBroadcastManager.getInstance(getContext()).unregisterReceiver(unreadCountReceiver);
unreadCountReceiver = null;
}
if (presenter != null) {
presenter.destroy();
presenter = null;
}
}
}

View File

@@ -0,0 +1,23 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.page;
import android.os.Bundle;
import androidx.annotation.Nullable;
import com.tencent.qcloud.tuikit.timcommon.component.activities.BaseMinimalistLightActivity;
import com.tencent.qcloud.tuikit.tuiconversation.R;
public class TUIFoldedConversationMinimalistActivity extends BaseMinimalistLightActivity {
private TUIFoldedConversationMinimalistFragment mTUIFoldedConversationMinimalistFragment;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.conversation_folded_activity);
init();
}
private void init() {
mTUIFoldedConversationMinimalistFragment = new TUIFoldedConversationMinimalistFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.empty_view, mTUIFoldedConversationMinimalistFragment).commitAllowingStateLoss();
}
}

View File

@@ -0,0 +1,244 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.page;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.PopupWindow;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.tencent.qcloud.tuikit.timcommon.component.TitleBarLayout;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopActionClickListener;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopDialogAdapter;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopMenuAction;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.ITitleBarLayout;
import com.tencent.qcloud.tuikit.timcommon.util.ScreenUtil;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.ConversationUtils;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces.OnConversationAdapterListener;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.util.TUIConversationUtils;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.FoldedConversationLayout;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationFoldPresenter;
import java.util.ArrayList;
import java.util.List;
public class TUIFoldedConversationMinimalistFragment extends Fragment {
private View mBaseView;
private TitleBarLayout mTitleBarLayout;
private FoldedConversationLayout mFoldedLayout;
private PopDialogAdapter mConversationPopAdapter;
private ListView mConversationPopList;
private PopupWindow mConversationPopWindow;
private String popWindowConversationId;
private List<PopMenuAction> mConversationPopActions = new ArrayList<>();
private ConversationFoldPresenter presenter;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
mBaseView = inflater.inflate(R.layout.minimalist_folded_fragment, container, false);
initView();
return mBaseView;
}
private void initView() {
mFoldedLayout = mBaseView.findViewById(R.id.folded_conversation_layout);
mTitleBarLayout = mFoldedLayout.getTitleBar();
mTitleBarLayout.setTitle(getResources().getString(R.string.folded_group_chat), ITitleBarLayout.Position.MIDDLE);
mTitleBarLayout.setOnLeftClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().finish();
}
});
presenter = new ConversationFoldPresenter();
presenter.initListener();
mFoldedLayout.setPresenter(presenter);
mFoldedLayout.initDefault();
mFoldedLayout.getConversationList().setOnConversationAdapterListener(new OnConversationAdapterListener() {
@Override
public void onItemClick(View view, int viewType, ConversationInfo conversationInfo) {
TUIConversationUtils.startChatActivity(conversationInfo);
}
@Override
public void onItemLongClick(View view, ConversationInfo conversationInfo) {
showItemPopMenu(view, conversationInfo);
}
@Override
public void onConversationChanged(List<ConversationInfo> dataSource) {
if (dataSource == null) {
return;
}
ConversationInfo conversationInfo = dataSource.get(0);
if (conversationInfo == null) {
return;
}
if (!TextUtils.isEmpty(popWindowConversationId) && popWindowConversationId.equals(conversationInfo.getConversationId())) {
if (mConversationPopWindow != null) {
mConversationPopWindow.dismiss();
}
}
}
@Override
public void onMarkConversationUnread(View view, ConversationInfo conversationInfo, boolean markUnread) {}
@Override
public void onMarkConversationHidden(View view, ConversationInfo conversationInfo) {}
@Override
public void onClickMoreView(View view, ConversationInfo conversationInfo) {}
@Override
public void onSwipeConversationChanged(ConversationInfo conversationInfo) {
if (conversationInfo == null) {
popWindowConversationId = "";
return;
}
popWindowConversationId = conversationInfo.getConversationId();
}
});
restoreConversationItemBackground();
}
private void initPopMenuAction() {
List<PopMenuAction> conversationPopActions = new ArrayList<PopMenuAction>();
PopMenuAction action = new PopMenuAction();
action.setActionName(getResources().getString(R.string.not_display));
action.setActionClickListener(new PopActionClickListener() {
@Override
public void onActionClick(int index, Object data) {
ConversationInfo conversationInfo = (ConversationInfo) data;
mFoldedLayout.markConversationHidden(conversationInfo);
}
});
conversationPopActions.add(action);
action = new PopMenuAction();
action.setActionClickListener(new PopActionClickListener() {
@Override
public void onActionClick(int index, Object data) {
mFoldedLayout.deleteConversation((ConversationInfo) data);
}
});
action.setActionName(getResources().getString(R.string.chat_delete));
conversationPopActions.add(action);
mConversationPopActions.clear();
mConversationPopActions.addAll(conversationPopActions);
}
private void restoreConversationItemBackground() {
if (mFoldedLayout.getConversationList().getAdapter() != null && mFoldedLayout.getConversationList().getAdapter().isClick()) {
mFoldedLayout.getConversationList().getAdapter().setClick(false);
mFoldedLayout.getConversationList().getAdapter().notifyItemChanged(mFoldedLayout.getConversationList().getAdapter().getCurrentPosition());
}
}
private void addMarkUnreadPopMenuAction(boolean markUnread) {
PopMenuAction action = new PopMenuAction();
action.setActionClickListener(new PopActionClickListener() {
@Override
public void onActionClick(int index, Object data) {
mFoldedLayout.markConversationUnread((ConversationInfo) data, markUnread);
}
});
if (markUnread) {
action.setActionName(getResources().getString(R.string.mark_unread));
} else {
action.setActionName(getResources().getString(R.string.mark_read));
}
mConversationPopActions.add(0, action);
}
private void showItemPopMenu(View view, final ConversationInfo conversationInfo) {
initPopMenuAction();
if (conversationInfo.getUnRead() > 0) {
addMarkUnreadPopMenuAction(false);
} else {
if (conversationInfo.isMarkUnread()) {
addMarkUnreadPopMenuAction(false);
} else {
addMarkUnreadPopMenuAction(true);
}
}
View itemPop = LayoutInflater.from(getActivity()).inflate(R.layout.conversation_pop_menu_layout, null);
mConversationPopList = itemPop.findViewById(R.id.pop_menu_list);
mConversationPopList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
PopMenuAction action = mConversationPopActions.get(position);
if (action.getActionClickListener() != null) {
action.getActionClickListener().onActionClick(position, conversationInfo);
}
mConversationPopWindow.dismiss();
restoreConversationItemBackground();
}
});
for (int i = 0; i < mConversationPopActions.size(); i++) {
PopMenuAction action = mConversationPopActions.get(i);
if (conversationInfo.isTop()) {
if (action.getActionName().equals(getResources().getString(R.string.chat_top))) {
action.setActionName(getResources().getString(R.string.quit_chat_top));
}
} else {
if (action.getActionName().equals(getResources().getString(R.string.quit_chat_top))) {
action.setActionName(getResources().getString(R.string.chat_top));
}
}
}
mConversationPopAdapter = new PopDialogAdapter();
mConversationPopList.setAdapter(mConversationPopAdapter);
mConversationPopAdapter.setDataSource(mConversationPopActions);
mConversationPopWindow = new PopupWindow(itemPop, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT);
mConversationPopWindow.setBackgroundDrawable(new ColorDrawable());
mConversationPopWindow.setOutsideTouchable(true);
popWindowConversationId = conversationInfo.getConversationId();
int width = ConversationUtils.getListUnspecifiedWidth(mConversationPopAdapter, mConversationPopList);
mConversationPopWindow.setWidth(width);
mConversationPopWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
restoreConversationItemBackground();
popWindowConversationId = "";
}
});
int x = view.getWidth() / 2;
int y = -view.getHeight() / 3;
int popHeight = ScreenUtil.dip2px(45) * 3;
if (y + popHeight + view.getY() + view.getHeight() > mFoldedLayout.getBottom()) {
y = y - popHeight;
}
mConversationPopWindow.showAsDropDown(view, x, y, Gravity.TOP | Gravity.START);
}
@Override
public void onDestroy() {
super.onDestroy();
if (presenter != null) {
presenter.destroy();
presenter = null;
}
}
}

View File

@@ -0,0 +1,39 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.page;
import android.content.Intent;
import android.os.Bundle;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.TUIConversationLog;
public class TUIForwardSelectMinimalistActivity extends AppCompatActivity {
private static final String TAG = TUIForwardSelectMinimalistActivity.class.getSimpleName();
private TUIForwardSelectMinimalistFragment forwardSelectMinimalistFragment;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.conversation_forward_activity_layout);
init();
}
@Override
protected void onNewIntent(Intent intent) {
TUIConversationLog.i(TAG, "onNewIntent");
super.onNewIntent(intent);
}
@Override
protected void onResume() {
TUIConversationLog.i(TAG, "onResume");
super.onResume();
}
private void init() {
forwardSelectMinimalistFragment = new TUIForwardSelectMinimalistFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.empty_view, forwardSelectMinimalistFragment).commitAllowingStateLoss();
}
}

View File

@@ -0,0 +1,131 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.page;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.TUIConversationConstants;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces.OnConversationAdapterListener;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.ConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.ForwardSelectLayout;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationPresenter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class TUIForwardSelectMinimalistFragment extends Fragment {
private static final String TAG = TUIForwardSelectMinimalistFragment.class.getSimpleName();
private View mBaseView;
private ForwardSelectLayout mForwardLayout;
private TextView conversationNamesTv;
private List<ConversationInfo> mDataSource = new ArrayList<>();
private View forwardListLayout;
private TextView mSureView;
private ConversationPresenter presenter;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
mBaseView = inflater.inflate(R.layout.minimalist_forward_fragment, container, false);
return mBaseView;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
mForwardLayout = view.findViewById(R.id.forward_conversation_layout);
conversationNamesTv = view.findViewById(R.id.conversation_name_tv);
forwardListLayout = view.findViewById(R.id.forward_list_layout);
presenter = new ConversationPresenter();
mForwardLayout.setPresenter(presenter);
mForwardLayout.initDefault();
mForwardLayout.getConversationList().setOnConversationAdapterListener(new OnConversationAdapterListener() {
@Override
public void onItemClick(View view, int viewType, ConversationInfo conversationInfo) {
refreshSelectConversations();
}
@Override
public void onItemLongClick(View view, ConversationInfo conversationInfo) {}
@Override
public void onConversationChanged(List<ConversationInfo> dataSource) {}
@Override
public void onMarkConversationUnread(View view, ConversationInfo conversationInfo, boolean markUnread) {}
@Override
public void onMarkConversationHidden(View view, ConversationInfo conversationInfo) {}
@Override
public void onClickMoreView(View view, ConversationInfo conversationInfo) {}
@Override
public void onSwipeConversationChanged(ConversationInfo conversationInfo) {}
});
mSureView = view.findViewById(R.id.btn_msg_ok);
mSureView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (getActivity() != null) {
HashMap<String, Boolean> conversationMap = new HashMap<>();
if (mDataSource != null && !mDataSource.isEmpty()) {
for (int i = 0; i < mDataSource.size(); i++) {
conversationMap.put(mDataSource.get(i).getId(), mDataSource.get(i).isGroup());
}
}
Intent intent = new Intent();
intent.putExtra(TUIConversationConstants.FORWARD_SELECT_CONVERSATION_KEY, conversationMap);
getActivity().setResult(TUIConversationConstants.FORWARD_SELECT_ACTIVTY_CODE, intent);
getActivity().finish();
}
}
});
refreshSelectConversations();
}
private void refreshSelectConversations() {
ConversationListAdapter adapter = mForwardLayout.getConversationList().getAdapter();
if (adapter != null) {
mDataSource = adapter.getSelectedItem();
} else {
mDataSource = null;
}
conversationNamesTv.setText(getSelectedNames());
if (mDataSource == null || mDataSource.isEmpty()) {
mSureView.setVisibility(View.GONE);
forwardListLayout.setVisibility(View.GONE);
} else {
forwardListLayout.setVisibility(View.VISIBLE);
mSureView.setVisibility(View.VISIBLE);
mSureView.setText(getString(R.string.conversation_forward) + "(" + mDataSource.size() + ")");
}
}
private String getSelectedNames() {
if (mDataSource == null || mDataSource.isEmpty()) {
return "";
}
StringBuffer stringBuffer = new StringBuffer();
for (ConversationInfo conversationInfo : mDataSource) {
stringBuffer.append(conversationInfo.getShowName());
stringBuffer.append(",");
}
return stringBuffer.substring(0, stringBuffer.length() - 1);
}
}

View File

@@ -0,0 +1,33 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.util;
import android.os.Bundle;
import com.tencent.imsdk.v2.V2TIMConversation;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import java.io.Serializable;
public class TUIConversationUtils {
public static void startChatActivity(ConversationInfo conversationInfo) {
Bundle param = new Bundle();
param.putInt(TUIConstants.TUIChat.CHAT_TYPE, conversationInfo.isGroup() ? V2TIMConversation.V2TIM_GROUP : V2TIMConversation.V2TIM_C2C);
param.putString(TUIConstants.TUIChat.CHAT_ID, conversationInfo.getId());
param.putString(TUIConstants.TUIChat.CHAT_NAME, conversationInfo.getTitle());
if (conversationInfo.getDraft() != null) {
param.putString(TUIConstants.TUIChat.DRAFT_TEXT, conversationInfo.getDraft().getDraftText());
param.putLong(TUIConstants.TUIChat.DRAFT_TIME, conversationInfo.getDraft().getDraftTime());
}
param.putBoolean(TUIConstants.TUIChat.IS_TOP_CHAT, conversationInfo.isTop());
param.putString(TUIConstants.TUIChat.FACE_URL, conversationInfo.getIconPath());
if (conversationInfo.isGroup()) {
param.putString(TUIConstants.TUIChat.GROUP_TYPE, conversationInfo.getGroupType());
param.putSerializable(TUIConstants.TUIChat.FACE_URL_LIST, (Serializable) conversationInfo.getIconUrlList());
param.putSerializable(TUIConstants.TUIChat.AT_INFO_LIST, (Serializable) conversationInfo.getGroupAtInfoList());
}
if (conversationInfo.isGroup()) {
TUICore.startActivity("TUIGroupChatMinimalistActivity", param);
} else {
TUICore.startActivity("TUIC2CChatMinimalistActivity", param);
}
}
}

View File

@@ -0,0 +1,23 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget;
import android.view.View;
import androidx.recyclerview.widget.RecyclerView;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
public abstract class ConversationBaseHolder extends RecyclerView.ViewHolder {
protected View rootView;
protected ConversationListAdapter mAdapter;
public ConversationBaseHolder(View itemView) {
super(itemView);
rootView = itemView;
}
public void setAdapter(RecyclerView.Adapter adapter) {
mAdapter = (ConversationListAdapter) adapter;
}
public abstract void layoutViews(ConversationInfo conversationInfo, int position);
}

View File

@@ -0,0 +1,327 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.text.Html;
import android.view.View;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.tencent.imsdk.v2.V2TIMMessage;
import com.tencent.imsdk.v2.V2TIMUserStatus;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuikit.timcommon.bean.TUIMessageBean;
import com.tencent.qcloud.tuikit.timcommon.component.UnreadCountTextView;
import com.tencent.qcloud.tuikit.timcommon.component.face.FaceManager;
import com.tencent.qcloud.tuikit.timcommon.component.swipe.SwipeLayout;
import com.tencent.qcloud.tuikit.timcommon.util.DateTimeUtil;
import com.tencent.qcloud.tuikit.timcommon.util.ScreenUtil;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.bean.DraftInfo;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.TUIConversationLog;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.TUIConversationUtils;
import com.tencent.qcloud.tuikit.tuiconversation.config.TUIConversationConfig;
import com.tencent.qcloud.tuikit.tuiconversation.config.minimalistui.TUIConversationConfigMinimalist;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationPresenter;
import java.util.Date;
import java.util.HashMap;
public class ConversationCommonHolder extends ConversationBaseHolder {
public ConversationIconView conversationIconView;
protected LinearLayout leftItemLayout;
protected TextView titleText;
protected TextView messageText;
protected TextView timelineText;
protected UnreadCountTextView unreadText;
protected UnreadCountTextView conversationNotDisturbUnread;
protected ImageView disturbView;
protected CheckBox multiSelectCheckBox;
protected RelativeLayout messageStatusLayout;
public ImageView messageSending;
public ImageView messageFailed;
private boolean isForwardMode = false;
protected View userStatusView;
protected TextView atAllTv;
protected TextView atMeTv;
protected TextView draftTv;
protected TextView riskTv;
private boolean showFoldedStyle = true;
protected TextView foldGroupNameTv;
protected TextView foldGroupNameDivider;
protected SwipeLayout swipeLayout;
protected RelativeLayout markReadView;
protected RelativeLayout moreView;
protected TextView markReadTextView;
protected TextView notDisplayView;
protected ImageView markReadIconView;
private ConversationInfo currentConversation;
public ConversationCommonHolder(View itemView) {
super(itemView);
leftItemLayout = rootView.findViewById(R.id.item_left);
conversationIconView = rootView.findViewById(R.id.conversation_icon);
titleText = rootView.findViewById(R.id.conversation_title);
messageText = rootView.findViewById(R.id.conversation_last_msg);
timelineText = rootView.findViewById(R.id.conversation_time);
unreadText = rootView.findViewById(R.id.conversation_unread);
conversationNotDisturbUnread = rootView.findViewById(R.id.conversation_not_disturb_unread);
atMeTv = rootView.findViewById(R.id.conversation_at_me);
atAllTv = rootView.findViewById(R.id.conversation_at_all);
draftTv = rootView.findViewById(R.id.conversation_draft);
riskTv = rootView.findViewById(R.id.conversation_risk);
foldGroupNameTv = rootView.findViewById(R.id.fold_group_name);
foldGroupNameDivider = rootView.findViewById(R.id.fold_group_name_divider);
disturbView = rootView.findViewById(R.id.not_disturb);
multiSelectCheckBox = rootView.findViewById(R.id.select_checkbox);
messageStatusLayout = rootView.findViewById(R.id.message_status_layout);
messageFailed = itemView.findViewById(R.id.message_status_failed);
messageSending = itemView.findViewById(R.id.message_status_sending);
userStatusView = itemView.findViewById(R.id.user_status);
swipeLayout = itemView.findViewById(R.id.swipe);
markReadView = itemView.findViewById(R.id.mark_read);
moreView = itemView.findViewById(R.id.more_view);
markReadTextView = itemView.findViewById(R.id.mark_read_text);
notDisplayView = itemView.findViewById(R.id.not_display);
markReadIconView = itemView.findViewById(R.id.mark_read_image);
}
public void setForwardMode(boolean forwardMode) {
isForwardMode = forwardMode;
}
public void setShowFoldedStyle(boolean showFoldedStyle) {
this.showFoldedStyle = showFoldedStyle;
}
public void layoutViews(ConversationInfo conversation, int position) {
currentConversation = conversation;
initTitleAndTime(conversation);
setLastMessageAndStatus(conversation);
conversationIconView.setRadius(ScreenUtil.dip2px(40));
if (!mAdapter.hasItemUnreadDot()) {
conversationNotDisturbUnread.setVisibility(View.GONE);
unreadText.setVisibility(View.GONE);
}
conversationIconView.setShowFoldedStyle(showFoldedStyle);
conversationIconView.setConversation(conversation);
if (conversation.isShowDisturbIcon() && !isForwardMode) {
if (showFoldedStyle && conversation.isMarkFold()) {
disturbView.setVisibility(View.GONE);
} else {
disturbView.setVisibility(View.VISIBLE);
}
} else {
disturbView.setVisibility(View.GONE);
}
if (isForwardMode) {
messageText.setVisibility(View.GONE);
timelineText.setVisibility(View.GONE);
unreadText.setVisibility(View.GONE);
messageStatusLayout.setVisibility(View.GONE);
messageFailed.setVisibility(View.GONE);
messageSending.setVisibility(View.GONE);
atAllTv.setVisibility(View.GONE);
atMeTv.setVisibility(View.GONE);
draftTv.setVisibility(View.GONE);
riskTv.setVisibility(View.GONE);
}
if (!conversation.isGroup() && TUIConversationConfigMinimalist.isShowUserOnlineStatusIcon()) {
if (conversation.getStatusType() == V2TIMUserStatus.V2TIM_USER_STATUS_ONLINE) {
userStatusView.setVisibility(View.VISIBLE);
} else {
userStatusView.setVisibility(View.GONE);
}
} else {
userStatusView.setVisibility(View.GONE);
}
applyCustomConfig();
}
private void applyCustomConfig() {
if (currentConversation.isTop() && !isForwardMode) {
Drawable pinnedCellBackground = TUIConversationConfigMinimalist.getPinnedCellBackground();
if (pinnedCellBackground != null) {
leftItemLayout.setBackground(pinnedCellBackground);
} else {
leftItemLayout.setBackgroundColor(rootView.getResources().getColor(R.color.conversation_item_top_color));
}
} else {
Drawable cellBackground = TUIConversationConfigMinimalist.getCellBackground();
if (cellBackground != null) {
leftItemLayout.setBackground(cellBackground);
} else {
leftItemLayout.setBackgroundColor(Color.WHITE);
}
}
if (!TUIConversationConfigMinimalist.isShowCellUnreadCount()) {
unreadText.setVisibility(View.GONE);
conversationNotDisturbUnread.setVisibility(View.GONE);
}
if (!TUIConversationConfigMinimalist.isShowUserOnlineStatusIcon()) {
userStatusView.setVisibility(View.GONE);
}
if (TUIConversationConfigMinimalist.getCellTitleLabelFontSize() != TUIConversationConfigMinimalist.UNDEFINED) {
titleText.setTextSize(TUIConversationConfigMinimalist.getCellTitleLabelFontSize());
}
if (TUIConversationConfigMinimalist.getCellSubtitleLabelFontSize() != TUIConversationConfigMinimalist.UNDEFINED) {
messageText.setTextSize(TUIConversationConfigMinimalist.getCellSubtitleLabelFontSize());
}
if (TUIConversationConfigMinimalist.getCellTimeLabelFontSize() != TUIConversationConfigMinimalist.UNDEFINED) {
timelineText.setTextSize(TUIConversationConfigMinimalist.getCellTimeLabelFontSize());
}
if (TUIConversationConfigMinimalist.getAvatarCornerRadius() != TUIConversationConfigMinimalist.UNDEFINED) {
conversationIconView.setRadius(TUIConversationConfigMinimalist.getAvatarCornerRadius());
}
}
private void setLastMessageAndStatus(ConversationInfo conversation) {
DraftInfo draftInfo = conversation.getDraft();
String draftText = "";
if (draftInfo != null) {
Gson gson = new Gson();
HashMap draftJsonMap;
draftText = draftInfo.getDraftText();
try {
draftJsonMap = gson.fromJson(draftInfo.getDraftText(), HashMap.class);
if (draftJsonMap != null) {
draftText = (String) draftJsonMap.get("content");
}
} catch (JsonSyntaxException e) {
TUIConversationLog.e("ConversationCommonHolder", " getDraftJsonMap error ");
}
}
atAllTv.setVisibility(View.GONE);
atMeTv.setVisibility(View.GONE);
draftTv.setVisibility(View.GONE);
riskTv.setVisibility(View.GONE);
if (draftInfo != null) {
messageText.setText(FaceManager.emojiJudge(draftText));
timelineText.setText(DateTimeUtil.getTimeFormatText(new Date(draftInfo.getDraftTime() * 1000)));
} else {
if (TUIConversationUtils.hasRiskContent(conversation.getLastMessage())) {
riskTv.setVisibility(View.VISIBLE);
} else {
TUIMessageBean lasTUIMessageBean = conversation.getLastTUIMessageBean();
if (lasTUIMessageBean != null) {
String displayString = ConversationPresenter.getMessageDisplayString(lasTUIMessageBean);
messageText.setText(displayString);
messageText.setTextColor(rootView.getResources().getColor(R.color.list_bottom_text_bg));
}
if (conversation.getLastMessage() != null) {
timelineText.setText(DateTimeUtil.getTimeFormatText(new Date(conversation.getLastMessageTime() * 1000)));
}
}
}
if (conversation.isShowDisturbIcon()) {
unreadText.setVisibility(View.GONE);
if ((showFoldedStyle && conversation.isMarkFold())) {
if (conversation.isMarkLocalUnread()) {
conversationNotDisturbUnread.setVisibility(View.VISIBLE);
} else {
conversationNotDisturbUnread.setVisibility(View.GONE);
}
} else {
if (conversation.getUnRead() == 0) {
if (conversation.isMarkUnread()) {
conversationNotDisturbUnread.setVisibility(View.VISIBLE);
} else {
conversationNotDisturbUnread.setVisibility(View.GONE);
}
} else {
conversationNotDisturbUnread.setVisibility(View.VISIBLE);
if (messageText.getText() != null) {
String text = messageText.getText().toString();
messageText.setText("[" + conversation.getUnRead() + " " + rootView.getContext().getString(R.string.message_num) + "] " + text);
}
}
}
} else if (conversation.getUnRead() > 0) {
conversationNotDisturbUnread.setVisibility(View.GONE);
unreadText.setVisibility(View.VISIBLE);
if (conversation.getUnRead() > 99) {
unreadText.setText("99+");
} else {
unreadText.setText("" + conversation.getUnRead());
}
} else {
conversationNotDisturbUnread.setVisibility(View.GONE);
if (conversation.isMarkUnread()) {
unreadText.setVisibility(View.VISIBLE);
unreadText.setText("1");
} else {
unreadText.setVisibility(View.GONE);
}
}
if (conversation.getAtType() == ConversationInfo.AT_TYPE_AT_ME) {
atMeTv.setVisibility(View.VISIBLE);
} else if (conversation.getAtType() == ConversationInfo.AT_TYPE_AT_ALL) {
atAllTv.setVisibility(View.VISIBLE);
} else if (conversation.getAtType() == ConversationInfo.AT_TYPE_AT_ALL_AND_ME) {
atAllTv.setVisibility(View.VISIBLE);
atMeTv.setVisibility(View.VISIBLE);
}
if (draftInfo != null) {
draftTv.setVisibility(View.VISIBLE);
messageStatusLayout.setVisibility(View.GONE);
messageFailed.setVisibility(View.GONE);
messageSending.setVisibility(View.GONE);
} else {
V2TIMMessage lastMessage = conversation.getLastMessage();
if (lastMessage != null) {
int status = lastMessage.getStatus();
if (status == V2TIMMessage.V2TIM_MSG_STATUS_SEND_FAIL) {
messageStatusLayout.setVisibility(View.VISIBLE);
messageFailed.setVisibility(View.VISIBLE);
messageSending.setVisibility(View.GONE);
} else if (status == V2TIMMessage.V2TIM_MSG_STATUS_SENDING) {
messageStatusLayout.setVisibility(View.VISIBLE);
messageFailed.setVisibility(View.GONE);
messageSending.setVisibility(View.VISIBLE);
} else {
messageStatusLayout.setVisibility(View.GONE);
messageFailed.setVisibility(View.GONE);
messageSending.setVisibility(View.GONE);
}
} else {
messageStatusLayout.setVisibility(View.GONE);
messageFailed.setVisibility(View.GONE);
messageSending.setVisibility(View.GONE);
}
}
}
private void initTitleAndTime(ConversationInfo conversation) {
if (showFoldedStyle && conversation.isMarkFold()) {
titleText.setText(R.string.folded_group_chat);
timelineText.setVisibility(View.GONE);
foldGroupNameTv.setVisibility(View.VISIBLE);
foldGroupNameDivider.setVisibility(View.VISIBLE);
foldGroupNameTv.setText(conversation.getTitle());
} else {
titleText.setText(conversation.getTitle());
foldGroupNameTv.setVisibility(View.GONE);
foldGroupNameDivider.setVisibility(View.GONE);
}
messageText.setText("");
timelineText.setText("");
}
}

View File

@@ -0,0 +1,54 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget;
import android.graphics.Color;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
public class ConversationCustomHolder extends ConversationBaseHolder {
protected LinearLayout leftItemLayout;
protected TextView titleText;
protected TextView messageText;
protected TextView timelineText;
protected TextView unreadText;
protected ConversationIconView conversationIconView;
public ConversationCustomHolder(View itemView) {
super(itemView);
leftItemLayout = rootView.findViewById(R.id.item_left);
conversationIconView = rootView.findViewById(R.id.conversation_icon);
titleText = rootView.findViewById(R.id.conversation_title);
messageText = rootView.findViewById(R.id.conversation_last_msg);
timelineText = rootView.findViewById(R.id.conversation_time);
unreadText = rootView.findViewById(R.id.conversation_unread);
}
@Override
public void layoutViews(ConversationInfo conversation, int position) {
if (conversation.isTop()) {
leftItemLayout.setBackgroundColor(rootView.getResources().getColor(R.color.conversation_item_top_color));
} else {
leftItemLayout.setBackgroundColor(Color.WHITE);
}
conversationIconView.setConversation(conversation);
titleText.setText(conversation.getTitle());
messageText.setText("");
timelineText.setText("");
if (conversation.getUnRead() > 0) {
unreadText.setVisibility(View.VISIBLE);
if (conversation.getUnRead() > 99) {
unreadText.setText("99+");
} else {
unreadText.setText("" + conversation.getUnRead());
}
} else {
unreadText.setVisibility(View.GONE);
}
}
}

View File

@@ -0,0 +1,166 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import com.tencent.qcloud.tuicore.TUIConfig;
import com.tencent.qcloud.tuikit.timcommon.component.gatherimage.SynthesizedImageView;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.timcommon.util.ImageUtil;
import com.tencent.qcloud.tuikit.timcommon.util.TUIUtil;
import com.tencent.qcloud.tuikit.timcommon.util.ThreadUtils;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationIconPresenter;
import java.util.ArrayList;
import java.util.List;
public class ConversationIconView extends RelativeLayout {
private ImageView mIconView;
private boolean showFoldedStyle = false;
private ConversationIconPresenter presenter;
public ConversationIconView(Context context) {
super(context);
init();
}
public ConversationIconView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ConversationIconView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
inflate(getContext(), com.tencent.qcloud.tuikit.timcommon.R.layout.common_profile_icon_view, this);
mIconView = findViewById(com.tencent.qcloud.tuikit.timcommon.R.id.profile_icon);
((SynthesizedImageView) mIconView).defaultImage(TUIConfig.getDefaultAvatarImage());
presenter = new ConversationIconPresenter();
}
public void setShowFoldedStyle(boolean showFoldedStyle) {
this.showFoldedStyle = showFoldedStyle;
}
/**
* url
*
* @param iconUrls url,9
*/
public void setIconUrls(final List<Object> iconUrls, final String conversationId) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
if (mIconView instanceof SynthesizedImageView) {
((SynthesizedImageView) (mIconView)).displayImage(iconUrls).load(conversationId);
}
}
});
}
public void setConversation(ConversationInfo conversationInfo) {
if (showFoldedStyle && conversationInfo.isMarkFold()) {
mIconView.setImageResource(R.drawable.conversation_ic_fold);
} else if (mIconView instanceof SynthesizedImageView) {
((SynthesizedImageView) (mIconView)).setImageId(conversationInfo.getConversationId());
if (conversationInfo.isGroup()) {
fillConversationUrlForGroup(conversationInfo);
} else {
setIconUrls(conversationInfo.getIconUrlList(), conversationInfo.getConversationId());
}
}
}
private void fillConversationUrlForGroup(final ConversationInfo info) {
List<Object> iconUrlList = info.getIconUrlList();
if (iconUrlList == null || iconUrlList.size() == 0) {
if (!TUIConfig.isEnableGroupGridAvatar()) {
List<Object> faceList = new ArrayList<>();
faceList.add(TUIConfig.getDefaultGroupAvatarImage());
setIconUrls(faceList, info.getConversationId());
return;
}
ThreadUtils.execute(new Runnable() {
@Override
public void run() {
final String savedIcon = ImageUtil.getGroupConversationAvatar(info.getConversationId());
if (TextUtils.isEmpty(savedIcon)) {
fillFaceUrlList(info.getId(), info);
} else {
List<Object> list = new ArrayList<>();
list.add(savedIcon);
info.setIconUrlList(list);
setIconUrls(list, info.getConversationId());
}
}
});
} else {
if (!TUIConfig.isEnableGroupGridAvatar() && iconUrlList.size() > 1) {
List<Object> faceList = new ArrayList<>();
faceList.add(TUIConfig.getDefaultGroupAvatarImage());
setIconUrls(faceList, info.getConversationId());
} else {
setIconUrls(iconUrlList, info.getConversationId());
}
}
}
private void fillFaceUrlList(final String groupID, final ConversationInfo info) {
ThreadUtils.runOnUiThread(new Runnable() {
@Override
public void run() {
clearImage();
presenter.getGroupMemberIconList(groupID, new IUIKitCallback<List<Object>>() {
@Override
public void onSuccess(List<Object> data) {
info.setIconUrlList(data);
setIconUrls(data, info.getConversationId());
}
@Override
public void onError(String module, int errCode, String errMsg) {
if (mIconView instanceof SynthesizedImageView) {
((SynthesizedImageView) (mIconView)).defaultImage(TUIUtil.getDefaultGroupIconResIDByGroupType(getContext(), info.getGroupType()));
}
setIconUrls(null, info.getConversationId());
}
});
}
});
}
public void setRadius(int radius) {
if (mIconView instanceof SynthesizedImageView) {
((SynthesizedImageView) (mIconView)).setRadius(radius);
}
}
public void setDefaultImageResId(int resId) {
BitmapDrawable bd = (BitmapDrawable) getContext().getResources().getDrawable(resId);
mIconView.setImageBitmap(bd.getBitmap());
}
public void setBitmapResId(int resId) {
BitmapDrawable bd = (BitmapDrawable) getContext().getResources().getDrawable(resId);
Bitmap bitmap = ImageUtil.toRoundBitmap(bd.getBitmap());
mIconView.setImageBitmap(bitmap);
}
public void clearImage() {
if (mIconView instanceof SynthesizedImageView) {
((SynthesizedImageView) mIconView).clear();
}
}
}

View File

@@ -0,0 +1,277 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.tencent.qcloud.tuicore.TUIConfig;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuikit.timcommon.component.TitleBarLayout;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.timcommon.component.swipe.Attributes;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.config.minimalistui.TUIConversationConfigMinimalist;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces.IConversationLayout;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.page.TUIConversationMinimalistFragment;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationPresenter;
import java.util.ArrayList;
import java.util.List;
public class ConversationLayout extends RelativeLayout implements IConversationLayout {
private ConversationListLayout mConversationList;
private ViewGroup headerContainer;
private ConversationPresenter presenter;
private ImageView createChatView;
private TextView conversationEditView;
private TextView conversationEditDoneView;
private TUIConversationMinimalistFragment.OnClickListener mClickListener = null;
private boolean isMultiSelected = false;
private List<ConversationInfo> mSelectConversations = new ArrayList<>();
private ImageView homeView;
private TextView titleView;
private TextView rtCubeTitleView;
public ConversationLayout(Context context) {
super(context);
init();
}
public ConversationLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ConversationLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void setPresenter(ConversationPresenter presenter) {
this.presenter = presenter;
if (mConversationList != null) {
mConversationList.setPresenter(presenter);
}
}
private void init() {
inflate(getContext(), R.layout.minimalistui_conversation_layout, this);
mConversationList = findViewById(R.id.conversation_list);
headerContainer = findViewById(R.id.search_layout);
conversationEditView = findViewById(R.id.edit_button);
createChatView = findViewById(R.id.create_new_button);
conversationEditDoneView = findViewById(R.id.edit_done);
mSelectConversations.clear();
homeView = findViewById(R.id.home_rtcube);
titleView = findViewById(R.id.title);
rtCubeTitleView = findViewById(R.id.title_rtcube);
conversationEditView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (mClickListener != null) {
mClickListener.onEditConversationStartClick();
}
conversationEditView.setVisibility(GONE);
conversationEditDoneView.setVisibility(VISIBLE);
createChatView.setVisibility(GONE);
conversationMutiSelectStart();
}
});
createChatView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (mClickListener != null) {
mClickListener.onStartChatClick();
}
}
});
conversationEditDoneView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
if (mClickListener != null) {
mClickListener.onEditConversationEndClick();
}
conversationEditView.setVisibility(VISIBLE);
conversationEditDoneView.setVisibility(GONE);
createChatView.setVisibility(VISIBLE);
conversationMutiSelectEnd();
}
});
applyCustomConfig();
}
private void applyCustomConfig() {
Drawable listBackground = TUIConversationConfigMinimalist.getListBackground();
if (listBackground != null) {
mConversationList.setBackground(listBackground);
}
}
public void initUI() {
if (TUIConfig.getTUIHostType() != TUIConfig.TUI_HOST_TYPE_RTCUBE) {
homeView.setVisibility(GONE);
titleView.setVisibility(VISIBLE);
rtCubeTitleView.setVisibility(GONE);
} else {
homeView.setVisibility(VISIBLE);
titleView.setVisibility(GONE);
rtCubeTitleView.setVisibility(VISIBLE);
homeView.setBackgroundResource(com.tencent.qcloud.tuikit.timcommon.R.drawable.common_title_bar_home_icon);
homeView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Bundle bundle = new Bundle();
bundle.putString(TUIConstants.TIMAppKit.BACK_TO_RTCUBE_DEMO_TYPE_KEY, TUIConstants.TIMAppKit.BACK_TO_RTCUBE_DEMO_TYPE_IM);
TUICore.startActivity("TRTCMainActivity", bundle);
if (mClickListener != null) {
mClickListener.finishActivity();
}
}
});
}
}
public ImageView getCreateChatView() {
return createChatView;
}
public void resetTitleBar() {
conversationEditView.setVisibility(VISIBLE);
conversationEditDoneView.setVisibility(GONE);
createChatView.setVisibility(VISIBLE);
conversationMutiSelectEnd();
}
public void setOnClickListener(TUIConversationMinimalistFragment.OnClickListener listener) {
mClickListener = listener;
}
public boolean isMultiSelected() {
return isMultiSelected;
}
public void setTitle(String title) {
titleView.setText(title);
}
private void conversationMutiSelectStart() {
ConversationListAdapter adapter = mConversationList.getAdapter();
if (adapter != null) {
adapter.setShowMultiSelectCheckBox(true);
adapter.notifyDataSetChanged();
adapter.closeAllSwipeItems();
adapter.switchAllSwipeEnable(false);
}
isMultiSelected = true;
mSelectConversations.clear();
}
private void conversationMutiSelectEnd() {
ConversationListAdapter adapter = mConversationList.getAdapter();
if (adapter != null) {
adapter.setShowMultiSelectCheckBox(false);
adapter.notifyDataSetChanged();
adapter.closeAllSwipeItems();
adapter.switchAllSwipeEnable(true);
}
isMultiSelected = false;
mSelectConversations.clear();
}
public void initDefault() {
final ConversationListAdapter adapter = new ConversationListAdapter();
if (presenter != null) {
initHeaderView();
adapter.setShowFoldedStyle(true);
}
mConversationList.setLayoutManager(new LinearLayoutManager(getContext()));
adapter.setMode(Attributes.Mode.Single);
mConversationList.setAdapter((IConversationListAdapter) adapter);
if (presenter != null) {
presenter.setAdapter(adapter);
}
mConversationList.loadConversation();
mConversationList.loadMarkedConversation();
}
public void initHeaderView() {
headerContainer.setVisibility(VISIBLE);
TUICore.raiseExtension(TUIConstants.TUIConversation.Extension.ConversationListHeader.MINIMALIST_EXTENSION_ID, headerContainer, null);
}
@Override
public void setParentLayout(Object parent) {}
@Override
public ConversationListLayout getConversationList() {
return mConversationList;
}
@Override
public void setConversationTop(ConversationInfo conversation, IUIKitCallback callBack) {
if (presenter != null) {
presenter.setConversationTop(conversation, callBack);
}
}
@Override
public void deleteConversation(ConversationInfo conversation) {
if (presenter != null) {
presenter.deleteConversation(conversation);
}
}
@Override
public void clearConversationMessage(ConversationInfo conversation) {
if (presenter != null) {
presenter.clearConversationMessage(conversation);
}
}
@Override
public void markConversationHidden(ConversationInfo conversation) {
if (presenter != null) {
presenter.markConversationHidden(conversation, true);
}
}
@Override
public void markConversationUnread(ConversationInfo conversationInfo, boolean markUnread) {
if (presenter != null) {
presenter.markConversationUnreadAndCleanUnreadCount(conversationInfo, markUnread);
}
}
@Override
public void hideFoldedItem(boolean needHide) {
if (presenter != null) {
presenter.hideFoldItem(needHide);
}
}
@Override
public void clearUnreadStatusOfFoldItem() {
if (presenter != null) {
presenter.setUnreadStatusOfFoldItem(false);
}
}
@Override
public TitleBarLayout getTitleBar() {
return null;
}
}

View File

@@ -0,0 +1,559 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget;
import android.graphics.Color;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.tencent.qcloud.tuikit.timcommon.component.swipe.RecyclerSwipeAdapter;
import com.tencent.qcloud.tuikit.timcommon.component.swipe.SimpleSwipeListener;
import com.tencent.qcloud.tuikit.timcommon.component.swipe.SwipeLayout;
import com.tencent.qcloud.tuikit.timcommon.util.ScreenUtil;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.TUIConversationService;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces.OnConversationAdapterListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class ConversationListAdapter extends RecyclerSwipeAdapter<RecyclerView.ViewHolder> implements IConversationListAdapter {
public static final int ITEM_TYPE_HEADER_HIDE = 101;
public static final int ITEM_TYPE_FOOTER_LOADING = -99;
public static final int HEADER_COUNT = 1;
public static final int FOOTER_COUNT = 1;
public static final int SELECT_COUNT = 1;
public static final int SELECT_LABEL_COUNT = 1;
private boolean mHasShowUnreadDot = true;
protected List<ConversationInfo> mDataSource = new ArrayList<>();
private OnConversationAdapterListener mOnConversationAdapterListener;
private final HashMap<String, Boolean> mSelectedPositions = new HashMap<>();
private boolean isShowMultiSelectCheckBox = false;
private boolean isForwardFragment = false;
private boolean mIsLoading = false;
private boolean isClick = false;
private int currentPosition = -1;
private boolean showFoldedStyle = true;
public ConversationListAdapter() {}
public int getCurrentPosition() {
return currentPosition;
}
public boolean isClick() {
return isClick;
}
public void setClick(boolean click) {
isClick = click;
}
public void setCurrentPosition(int currentPosition, boolean isClick) {
this.currentPosition = currentPosition;
this.isClick = isClick;
}
public void setShowMultiSelectCheckBox(boolean show) {
isShowMultiSelectCheckBox = show;
if (!isShowMultiSelectCheckBox) {
mSelectedPositions.clear();
}
}
public void setForwardFragment(boolean forwardFragment) {
isForwardFragment = forwardFragment;
}
public void setShowFoldedStyle(boolean showFoldedStyle) {
this.showFoldedStyle = showFoldedStyle;
}
public void setItemChecked(String conversationId, boolean isChecked) {
mSelectedPositions.put(conversationId, isChecked);
}
private boolean isItemChecked(String id) {
if (mSelectedPositions.size() <= 0) {
return false;
}
if (mSelectedPositions.containsKey(id)) {
return mSelectedPositions.get(id);
} else {
return false;
}
}
public List<ConversationInfo> getSelectedItem() {
if (mSelectedPositions.size() == 0) {
return null;
}
List<ConversationInfo> selectList = new ArrayList<>();
for (int i = 0; i < getItemCount() - 1; i++) {
ConversationInfo conversationInfo = getItem(i);
if (conversationInfo == null) {
continue;
}
if (isItemChecked(conversationInfo.getConversationId())) {
selectList.add(conversationInfo);
}
}
return selectList;
}
public void setOnConversationAdapterListener(OnConversationAdapterListener listener) {
this.mOnConversationAdapterListener = listener;
}
@Override
public void onDataSourceChanged(List<ConversationInfo> dataSource) {
this.mDataSource = dataSource;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
ConversationBaseHolder holder = null;
View view;
if (viewType == ITEM_TYPE_HEADER_HIDE) {
return new HeaderViewHolder(new View(parent.getContext()));
} else if (viewType == ConversationInfo.TYPE_CUSTOM) {
view = inflater.inflate(R.layout.conversation_custom_adapter, parent, false);
holder = new ConversationCustomHolder(view);
} else if (viewType == ITEM_TYPE_FOOTER_LOADING) {
view = inflater.inflate(R.layout.conversation_loading_progress_bar, parent, false);
return new FooterViewHolder(view);
} else if (viewType == ConversationInfo.TYPE_RECENT_LABEL) {
view = inflater.inflate(R.layout.conversation_minimalist_forward_label_adapter, parent, false);
return new ForwardLabelHolder(view);
} else {
if (isForwardFragment) {
view = inflater.inflate(R.layout.minimalistui_conversation_forward_list_item_layout, parent, false);
} else {
view = inflater.inflate(R.layout.minimalistui_conversation_list_item_layout, parent, false);
}
holder = new ConversationCommonHolder(view);
((ConversationCommonHolder) holder).setForwardMode(isForwardFragment);
((ConversationCommonHolder) holder).setShowFoldedStyle(showFoldedStyle);
}
holder.setAdapter(this);
return holder;
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, final int position) {
final ConversationInfo conversationInfo = getItem(position);
ConversationBaseHolder baseHolder = null;
if (conversationInfo != null) {
baseHolder = (ConversationBaseHolder) holder;
}
switch (getItemViewType(position)) {
case ConversationInfo.TYPE_CUSTOM:
case ConversationInfo.TYPE_RECENT_LABEL:
break;
case ITEM_TYPE_FOOTER_LOADING: {
if (holder instanceof FooterViewHolder) {
((ConversationBaseHolder) holder).layoutViews(null, position);
}
break;
}
default: {
if (baseHolder instanceof ConversationCommonHolder) {
ConversationCommonHolder viewHolder = (ConversationCommonHolder) baseHolder;
viewHolder.swipeLayout.setShowMode(SwipeLayout.ShowMode.LayDown);
if (conversationInfo.isMarkFold()) {
viewHolder.swipeLayout.setOnDoubleClickListener(new SwipeLayout.DoubleClickListener() {
@Override
public void onDoubleClick(SwipeLayout layout, boolean surface) {}
@Override
public void onClick() {
if (mOnConversationAdapterListener != null) {
mOnConversationAdapterListener.onItemClick(viewHolder.itemView, getItemViewType(position), conversationInfo);
}
}
});
viewHolder.markReadView.setVisibility(View.GONE);
viewHolder.moreView.setVisibility(View.GONE);
viewHolder.notDisplayView.setVisibility(View.VISIBLE);
viewHolder.notDisplayView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mOnConversationAdapterListener != null) {
mOnConversationAdapterListener.onMarkConversationHidden(view, conversationInfo);
}
mItemManger.closeAllSwipeItems();
}
});
mItemManger.bind(viewHolder.itemView, position);
} else {
viewHolder.notDisplayView.setVisibility(View.GONE);
viewHolder.markReadView.setVisibility(View.VISIBLE);
viewHolder.moreView.setVisibility(View.VISIBLE);
viewHolder.swipeLayout.addSwipeListener(new SimpleSwipeListener() {
@Override
public void onOpen(SwipeLayout layout) {
if (mOnConversationAdapterListener != null) {
mOnConversationAdapterListener.onSwipeConversationChanged(conversationInfo);
}
}
@Override
public void onClose(SwipeLayout layout) {
if (mOnConversationAdapterListener != null) {
mOnConversationAdapterListener.onSwipeConversationChanged(null);
}
}
@Override
public void onStartOpen(SwipeLayout layout) {
int unReadNum = conversationInfo.getUnRead();
boolean isMarkUnread = conversationInfo.isMarkUnread();
if (unReadNum > 0) {
viewHolder.markReadTextView.setText(R.string.mark_read);
viewHolder.markReadView.setBackgroundColor(viewHolder.itemView.getResources().getColor(R.color.conversation_mark_swipe_bg));
viewHolder.markReadIconView.setBackgroundResource(R.drawable.conversation_minimalist_message_status_send_all_read);
} else {
if (isMarkUnread) {
viewHolder.markReadTextView.setText(R.string.mark_read);
viewHolder.markReadView.setBackgroundColor(
viewHolder.itemView.getResources().getColor(R.color.conversation_mark_swipe_bg));
viewHolder.markReadIconView.setBackgroundResource(R.drawable.conversation_minimalist_message_status_send_all_read);
} else {
viewHolder.markReadTextView.setText(R.string.mark_unread);
viewHolder.markReadView.setBackgroundColor(
viewHolder.itemView.getResources().getColor(R.color.conversation_mark_swipe_dark_bg));
viewHolder.markReadIconView.setBackgroundResource(R.drawable.conversation_minimalist_message_status_send_no_read);
}
}
}
});
viewHolder.swipeLayout.setOnDoubleClickListener(new SwipeLayout.DoubleClickListener() {
@Override
public void onDoubleClick(SwipeLayout layout, boolean surface) {}
@Override
public void onClick() {
if (mOnConversationAdapterListener != null) {
mOnConversationAdapterListener.onItemClick(viewHolder.itemView, getItemViewType(position), conversationInfo);
}
}
});
viewHolder.markReadView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mOnConversationAdapterListener != null) {
boolean markRead =
TUIConversationService.getAppContext().getString(R.string.mark_read).equals(viewHolder.markReadTextView.getText());
mOnConversationAdapterListener.onMarkConversationUnread(view, conversationInfo, !markRead);
}
mItemManger.closeAllSwipeItems();
}
});
viewHolder.moreView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (mOnConversationAdapterListener != null) {
mOnConversationAdapterListener.onClickMoreView(view, conversationInfo);
}
mItemManger.closeAllSwipeItems();
}
});
mItemManger.bind(viewHolder.itemView, position);
}
} else {
setOnClickListener(holder, getItemViewType(position), conversationInfo);
}
}
}
if (baseHolder != null) {
baseHolder.layoutViews(conversationInfo, position);
setCheckBoxStatus(conversationInfo, position, baseHolder);
}
if (getCurrentPosition() == position && isClick()) {
baseHolder.itemView.setBackgroundResource(R.color.conversation_item_clicked_color);
} else {
if (conversationInfo == null) {
return;
}
if (conversationInfo.isTop() && !isForwardFragment) {
baseHolder.itemView.setBackgroundColor(baseHolder.rootView.getResources().getColor(R.color.conversation_item_top_color));
} else {
baseHolder.itemView.setBackgroundColor(Color.WHITE);
}
}
}
private void setOnClickListener(RecyclerView.ViewHolder holder, int viewType, ConversationInfo conversationInfo) {
if (holder instanceof HeaderViewHolder) {
return;
}
if (mOnConversationAdapterListener != null) {
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mOnConversationAdapterListener.onItemClick(view, viewType, conversationInfo);
}
});
holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
mOnConversationAdapterListener.onItemLongClick(view, conversationInfo);
int position = getIndexInAdapter(conversationInfo);
if (position != -1) {
setCurrentPosition(position, true);
notifyItemChanged(position);
}
return true;
}
});
}
}
private void setCheckBoxStatus(final ConversationInfo conversationInfo, int position, ConversationBaseHolder baseHolder) {
if (!(baseHolder instanceof ConversationCommonHolder) || ((ConversationCommonHolder) baseHolder).multiSelectCheckBox == null) {
return;
}
int viewType = getItemViewType(position);
String conversationId = conversationInfo.getConversationId();
ConversationCommonHolder commonHolder = (ConversationCommonHolder) baseHolder;
if (!isShowMultiSelectCheckBox || conversationInfo.isMarkFold()) {
commonHolder.multiSelectCheckBox.setVisibility(View.GONE);
baseHolder.itemView.setOnClickListener(null);
} else {
commonHolder.multiSelectCheckBox.setVisibility(View.VISIBLE);
commonHolder.multiSelectCheckBox.setChecked(isItemChecked(conversationId));
commonHolder.multiSelectCheckBox.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setItemChecked(conversationId, !isItemChecked(conversationId));
if (mOnConversationAdapterListener != null) {
mOnConversationAdapterListener.onItemClick(v, viewType, conversationInfo);
}
}
});
baseHolder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
setItemChecked(conversationId, !isItemChecked(conversationId));
int currentPosition = getIndexInAdapter(conversationInfo);
if (currentPosition != -1) {
notifyItemChanged(currentPosition);
}
if (mOnConversationAdapterListener != null) {
mOnConversationAdapterListener.onItemClick(v, viewType, conversationInfo);
}
}
});
}
}
public int getIndexInAdapter(ConversationInfo conversationInfo) {
int position = -1;
if (mDataSource != null) {
int indexInData = mDataSource.indexOf(conversationInfo);
if (indexInData != -1) {
position = getItemIndexInAdapter(indexInData);
}
}
return position;
}
@Override
public void onViewRecycled(@NonNull RecyclerView.ViewHolder holder) {
if (holder instanceof ConversationCommonHolder) {
((ConversationCommonHolder) holder).conversationIconView.clearImage();
}
}
public ConversationInfo getItem(int position) {
if (mDataSource.isEmpty() || position == getItemCount() - 1) {
return null;
}
int dataPosition;
if (isForwardFragment) {
dataPosition = position - SELECT_LABEL_COUNT;
} else {
dataPosition = position - HEADER_COUNT;
}
if (dataPosition < mDataSource.size() && dataPosition >= 0) {
return mDataSource.get(dataPosition);
}
return null;
}
@Override
public int getItemCount() {
int listSize = mDataSource.size();
if (isForwardFragment) {
return listSize + SELECT_LABEL_COUNT + FOOTER_COUNT;
}
return listSize + HEADER_COUNT + FOOTER_COUNT;
}
@Override
public int getItemViewType(int position) {
if (isForwardFragment) {
if (position == 0) {
return ConversationInfo.TYPE_RECENT_LABEL;
}
} else {
if (position == 0) {
return ITEM_TYPE_HEADER_HIDE;
}
}
if (position == getItemCount() - 1) {
return ITEM_TYPE_FOOTER_LOADING;
} else if (mDataSource != null) {
ConversationInfo conversationInfo = getItem(position);
if (conversationInfo != null) {
return conversationInfo.getType();
}
}
return ConversationInfo.TYPE_COMMON;
}
private int getItemIndexInAdapter(int index) {
int itemIndex;
if (isForwardFragment) {
itemIndex = index + SELECT_LABEL_COUNT;
} else {
itemIndex = index + HEADER_COUNT;
}
return itemIndex;
}
@Override
public void onItemRemoved(int position) {
int itemIndex = getItemIndexInAdapter(position);
notifyItemRemoved(itemIndex);
}
@Override
public void onItemInserted(int position) {
int itemIndex = getItemIndexInAdapter(position);
notifyItemInserted(itemIndex);
}
@Override
public void onItemChanged(int position) {
int itemIndex = getItemIndexInAdapter(position);
notifyItemChanged(itemIndex);
}
@Override
public void onItemMoved(int fromPosition, int toPosition) {
int fromIndex = getItemIndexInAdapter(fromPosition);
int toIndex = getItemIndexInAdapter(toPosition);
notifyItemMoved(fromIndex, toIndex);
}
@Override
public void onItemRangeChanged(int startPosition, int count) {
int itemStartIndex = getItemIndexInAdapter(startPosition);
notifyItemRangeChanged(itemStartIndex, count);
}
@Override
public void onConversationChanged(List<ConversationInfo> conversationInfoList) {
if (mOnConversationAdapterListener != null) {
mOnConversationAdapterListener.onConversationChanged(conversationInfoList);
}
}
public void disableItemUnreadDot(boolean flag) {
mHasShowUnreadDot = !flag;
}
public boolean hasItemUnreadDot() {
return mHasShowUnreadDot;
}
@Override
public void onLoadingStateChanged(boolean isLoading) {
this.mIsLoading = isLoading;
notifyItemChanged(getItemCount() - 1);
}
@Override
public void onViewNeedRefresh() {
notifyDataSetChanged();
}
@Override
public int getSwipeLayoutResourceId(int position) {
return R.id.swipe;
}
// header
static class HeaderViewHolder extends RecyclerView.ViewHolder {
public HeaderViewHolder(@NonNull View itemView) {
super(itemView);
}
}
// footer
class FooterViewHolder extends ConversationBaseHolder {
public FooterViewHolder(@NonNull View itemView) {
super(itemView);
}
@Override
public void layoutViews(ConversationInfo conversationInfo, int position) {
RecyclerView.LayoutParams param = (RecyclerView.LayoutParams) rootView.getLayoutParams();
if (mIsLoading) {
param.height = LinearLayout.LayoutParams.WRAP_CONTENT;
param.width = LinearLayout.LayoutParams.MATCH_PARENT;
rootView.setVisibility(View.VISIBLE);
} else {
param.height = 0;
param.width = 0;
rootView.setVisibility(View.GONE);
}
rootView.setLayoutParams(param);
}
}
static class ForwardLabelHolder extends ConversationBaseHolder {
public ForwardLabelHolder(View itemView) {
super(itemView);
}
@Override
public void layoutViews(ConversationInfo conversationInfo, int position) {
}
}
}

View File

@@ -0,0 +1,125 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget;
import android.content.Context;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import com.tencent.qcloud.tuikit.timcommon.component.CustomLinearLayoutManager;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces.IConversationListLayout;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces.OnConversationAdapterListener;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationPresenter;
public class ConversationListLayout extends RecyclerView implements IConversationListLayout {
private ConversationListAdapter mAdapter;
private ConversationPresenter presenter;
private boolean isFolded = false;
public ConversationListLayout(Context context) {
super(context);
init();
}
public ConversationListLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public ConversationListLayout(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void setPresenter(ConversationPresenter presenter) {
this.presenter = presenter;
}
public void init() {
setLayoutFrozen(false);
setItemViewCacheSize(0);
setHasFixedSize(true);
setFocusableInTouchMode(false);
CustomLinearLayoutManager linearLayoutManager = new CustomLinearLayoutManager(getContext());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
setLayoutManager(linearLayoutManager);
SimpleItemAnimator animator = (SimpleItemAnimator) getItemAnimator();
if (animator != null) {
animator.setSupportsChangeAnimations(false);
}
}
@Override
public void setBackground(int resId) {
setBackgroundColor(resId);
}
@Override
public void disableItemUnreadDot(boolean flag) {
mAdapter.disableItemUnreadDot(flag);
}
@Override
public ConversationListLayout getListLayout() {
return this;
}
@Override
public ConversationListAdapter getAdapter() {
return mAdapter;
}
@Override
public void setAdapter(IConversationListAdapter adapter) {
if (adapter instanceof ConversationListAdapter) {
super.setAdapter((ConversationListAdapter) adapter);
mAdapter = (ConversationListAdapter) adapter;
}
}
@Override
public void setOnConversationAdapterListener(OnConversationAdapterListener listener) {
mAdapter.setOnConversationAdapterListener(listener);
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
if (state == RecyclerView.SCROLL_STATE_IDLE) {
LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
if (layoutManager == null) {
return;
}
int lastPosition = layoutManager.findLastCompletelyVisibleItemPosition();
if (mAdapter != null) {
if (lastPosition == mAdapter.getItemCount() - 1 && !isLoadCompleted()) {
mAdapter.onLoadingStateChanged(true);
if (presenter != null) {
presenter.loadMoreConversation();
}
}
}
}
}
public void loadConversation() {
if (presenter != null) {
presenter.loadMoreConversation();
}
}
public void loadMarkedConversation() {
if (presenter != null) {
presenter.loadMarkedConversation();
}
}
boolean isLoadCompleted() {
if (presenter != null) {
return presenter.isLoadFinished();
}
return false;
}
}

View File

@@ -0,0 +1,102 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.RelativeLayout;
import com.tencent.qcloud.tuikit.timcommon.component.TitleBarLayout;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces.IConversationLayout;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationFoldPresenter;
public class FoldedConversationLayout extends RelativeLayout implements IConversationLayout {
private TitleBarLayout titleBarLayout;
private FoldedConversationListLayout conversationListLayout;
private ConversationFoldPresenter presenter;
public FoldedConversationLayout(Context context) {
super(context);
init();
}
public FoldedConversationLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public FoldedConversationLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void setPresenter(ConversationFoldPresenter presenter) {
this.presenter = presenter;
if (conversationListLayout != null) {
conversationListLayout.setPresenter(presenter);
}
}
private void init() {
inflate(getContext(), R.layout.minimalist_folded_layout, this);
titleBarLayout = findViewById(R.id.conversation_title);
conversationListLayout = findViewById(R.id.folded_conversation_list);
}
public void initDefault() {
final ConversationListAdapter adapter = new ConversationListAdapter();
conversationListLayout.setAdapter((IConversationListAdapter) adapter);
adapter.setShowFoldedStyle(false);
if (presenter != null) {
presenter.setAdapter(adapter);
}
conversationListLayout.loadConversation();
}
@Override
public FoldedConversationListLayout getConversationList() {
return conversationListLayout;
}
@Override
public void setConversationTop(ConversationInfo conversation, IUIKitCallback callBack) {}
@Override
public void deleteConversation(ConversationInfo conversation) {
if (presenter != null) {
presenter.deleteConversation(conversation);
}
}
@Override
public void clearConversationMessage(ConversationInfo conversation) {}
@Override
public void markConversationHidden(ConversationInfo conversation) {
if (presenter != null) {
presenter.markConversationHidden(conversation, true);
}
}
@Override
public void markConversationUnread(ConversationInfo conversationInfo, boolean markUnread) {
if (presenter != null) {
presenter.markConversationUnread(conversationInfo, markUnread);
}
}
@Override
public void hideFoldedItem(boolean needHide) {}
@Override
public void clearUnreadStatusOfFoldItem() {}
@Override
public TitleBarLayout getTitleBar() {
return titleBarLayout;
}
@Override
public void setParentLayout(Object parent) {}
}

View File

@@ -0,0 +1,91 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget;
import android.content.Context;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.SimpleItemAnimator;
import com.tencent.qcloud.tuikit.timcommon.component.CustomLinearLayoutManager;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces.IConversationListLayout;
import com.tencent.qcloud.tuikit.tuiconversation.minimalistui.interfaces.OnConversationAdapterListener;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationFoldPresenter;
public class FoldedConversationListLayout extends RecyclerView implements IConversationListLayout {
private ConversationListAdapter mAdapter;
private ConversationFoldPresenter presenter;
private boolean isFolded = false;
public FoldedConversationListLayout(Context context) {
super(context);
init();
}
public FoldedConversationListLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init();
}
public FoldedConversationListLayout(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public void setPresenter(ConversationFoldPresenter presenter) {
this.presenter = presenter;
}
public void init() {
setLayoutFrozen(false);
setItemViewCacheSize(0);
setHasFixedSize(true);
setFocusableInTouchMode(false);
CustomLinearLayoutManager linearLayoutManager = new CustomLinearLayoutManager(getContext());
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
setLayoutManager(linearLayoutManager);
SimpleItemAnimator animator = (SimpleItemAnimator) getItemAnimator();
if (animator != null) {
animator.setSupportsChangeAnimations(false);
}
}
@Override
public void setBackground(int resId) {
setBackgroundColor(resId);
}
@Override
public void disableItemUnreadDot(boolean flag) {
mAdapter.disableItemUnreadDot(flag);
}
@Override
public FoldedConversationListLayout getListLayout() {
return this;
}
@Override
public ConversationListAdapter getAdapter() {
return mAdapter;
}
@Override
public void setAdapter(IConversationListAdapter adapter) {
if (adapter instanceof ConversationListAdapter) {
super.setAdapter((ConversationListAdapter) adapter);
mAdapter = (ConversationListAdapter) adapter;
}
}
@Override
public void setOnConversationAdapterListener(OnConversationAdapterListener listener) {
mAdapter.setOnConversationAdapterListener(listener);
}
public void loadConversation() {
if (presenter != null) {
presenter.loadConversation();
}
}
}

View File

@@ -0,0 +1,67 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget;
import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.tencent.qcloud.tuikit.timcommon.util.ScreenUtil;
import com.tencent.qcloud.tuikit.tuiconversation.R;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.presenter.ConversationPresenter;
public class ForwardSelectLayout extends RelativeLayout {
private ConversationListLayout conversationList;
private ConversationPresenter presenter;
private TextView cancelButton;
public ForwardSelectLayout(Context context) {
super(context);
init();
}
public ForwardSelectLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ForwardSelectLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void setPresenter(ConversationPresenter presenter) {
this.presenter = presenter;
if (conversationList != null) {
conversationList.setPresenter(presenter);
}
}
private void init() {
inflate(getContext(), R.layout.minimalist_forward_layout, this);
conversationList = findViewById(R.id.conversation_list);
cancelButton = findViewById(R.id.cancel_button);
cancelButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
((Activity) getContext()).finish();
}
});
}
public void initDefault() {
final ConversationListAdapter adapter = new ConversationListAdapter();
adapter.setForwardFragment(true);
adapter.setShowMultiSelectCheckBox(true);
adapter.setSwipeEnabled(false);
conversationList.setAdapter((IConversationListAdapter) adapter);
presenter.setAdapter(adapter);
presenter.loadMoreConversation();
}
public ConversationListLayout getConversationList() {
return conversationList;
}
}

View File

@@ -0,0 +1,162 @@
package com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget;
import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.PopupWindow;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.tencent.qcloud.tuikit.timcommon.R;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopMenuAction;
import com.tencent.qcloud.tuikit.timcommon.component.action.PopMenuAdapter;
import com.tencent.qcloud.tuikit.timcommon.util.ScreenUtil;
import java.util.ArrayList;
import java.util.List;
public class Menu {
private static final int SHADOW_WIDTH = 10;
private static final int Y_OFFSET = 4;
private ListView mMenuList;
private PopMenuAdapter mMenuAdapter;
private PopupWindow mMenuWindow;
private List<PopMenuAction> mActions = new ArrayList<>();
private Activity mActivity;
private View mAttachView;
public Menu(Activity activity, View attach) {
mActivity = activity;
mAttachView = attach;
}
public void setMenuAction(List<PopMenuAction> menuActions) {
mActions.clear();
mActions.addAll(menuActions);
}
public boolean isShowing() {
if (mMenuWindow == null) {
return false;
}
return mMenuWindow.isShowing();
}
public void hide() {
mMenuWindow.dismiss();
}
public void show() {
if (mActions == null || mActions.size() == 0) {
return;
}
mMenuWindow = new PopupWindow(mActivity);
mMenuWindow.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
mMenuWindow.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
mMenuWindow.setBackgroundDrawable(new ColorDrawable());
mMenuAdapter = new PopMenuAdapter();
mMenuAdapter.setDataSource(mActions);
View menuView = LayoutInflater.from(mActivity).inflate(R.layout.core_pop_menu, null);
menuView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mMenuWindow.setContentView(menuView);
mMenuList = menuView.findViewById(R.id.menu_pop_list);
mMenuList.setAdapter(mMenuAdapter);
mMenuList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
PopMenuAction action = (PopMenuAction) mMenuAdapter.getItem(position);
if (action != null && action.getActionClickListener() != null) {
action.getActionClickListener().onActionClick(position, mActions.get(position));
}
}
});
int paddingLeftRight = ScreenUtil.dip2px(15.0f);
int paddingTopBottom = ScreenUtil.dip2px(12.0f);
int itemWidth = mActivity.getResources().getDimensionPixelSize(R.dimen.core_pop_menu_item_width);
int itemHeight = mActivity.getResources().getDimensionPixelSize(R.dimen.core_pop_menu_item_height);
mMenuWindow.getContentView().measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
int[] location = new int[2];
mAttachView.getLocationOnScreen(location);
int rowCount = mActions.size();
int indicatorHeight = mActivity.getResources().getDimensionPixelOffset(R.dimen.core_pop_menu_indicator_height);
int popWidth = itemWidth + paddingLeftRight * 2 - SHADOW_WIDTH;
int popHeight = itemHeight * rowCount + paddingTopBottom * 2 - SHADOW_WIDTH;
float anchorWidth = mAttachView.getWidth();
float indicatorX = anchorWidth / 2 + indicatorHeight;
int screenWidth = ScreenUtil.getScreenWidth(mActivity);
int x = location[0] - indicatorHeight;
int y;
float xOffset = anchorWidth / 2;
// If it is on the right, the x-coordinate of the small arrow and the x-position of the pop-up window will change
if (location[0] * 2 + anchorWidth > screenWidth) {
indicatorX = popWidth - anchorWidth / 2 - xOffset;
x = (int) (location[0] + anchorWidth - popWidth + xOffset);
}
float anchorHeight = mAttachView.getHeight();
y = (int) (location[1] + anchorHeight) + Y_OFFSET;
popHeight = popHeight - indicatorHeight;
Drawable backgroundDrawable = getBackgroundDrawable(popWidth, popHeight, indicatorX, indicatorHeight, 16);
menuView.setBackground(backgroundDrawable);
mMenuWindow.setFocusable(true);
mMenuWindow.setTouchable(true);
mMenuWindow.setOutsideTouchable(true);
mMenuWindow.showAtLocation(mAttachView, Gravity.NO_GRAVITY, x, y);
}
/**
* Draw a popup background with small triangles
*/
public Drawable getBackgroundDrawable(final float widthPixel, final float heightPixel, float indicatorX, float indicatorHeight, float radius) {
int borderWidth = SHADOW_WIDTH;
Path path = new Path();
Drawable drawable = new Drawable() {
@Override
public void draw(@NonNull Canvas canvas) {
Paint paint = new Paint();
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL);
paint.setShadowLayer(borderWidth, 0, 0, 0xFFAAAAAA);
path.addRoundRect(new RectF(borderWidth, indicatorHeight + borderWidth, widthPixel - borderWidth, heightPixel + indicatorHeight - borderWidth),
radius, radius, Path.Direction.CW);
path.moveTo(indicatorX - indicatorHeight, indicatorHeight + borderWidth);
path.lineTo(indicatorX, borderWidth);
path.lineTo(indicatorX + indicatorHeight, indicatorHeight + borderWidth);
path.close();
canvas.drawPath(path, paint);
}
@Override
public void setAlpha(int alpha) {}
@Override
public void setColorFilter(@Nullable ColorFilter colorFilter) {}
@Override
public int getOpacity() {
return PixelFormat.TRANSLUCENT;
}
};
return drawable;
}
}

View File

@@ -0,0 +1,543 @@
package com.tencent.qcloud.tuikit.tuiconversation.model;
import android.text.TextUtils;
import com.tencent.imsdk.BaseConstants;
import com.tencent.imsdk.v2.V2TIMCallback;
import com.tencent.imsdk.v2.V2TIMConversation;
import com.tencent.imsdk.v2.V2TIMConversationListFilter;
import com.tencent.imsdk.v2.V2TIMConversationOperationResult;
import com.tencent.imsdk.v2.V2TIMConversationResult;
import com.tencent.imsdk.v2.V2TIMGroupMemberFullInfo;
import com.tencent.imsdk.v2.V2TIMGroupMemberInfoResult;
import com.tencent.imsdk.v2.V2TIMManager;
import com.tencent.imsdk.v2.V2TIMUserStatus;
import com.tencent.imsdk.v2.V2TIMValueCallback;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.interfaces.TUICallback;
import com.tencent.qcloud.tuicore.util.ErrorMessageConverter;
import com.tencent.qcloud.tuicore.util.ToastUtil;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuiconversation.BuildConfig;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationUserStatusBean;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.ConversationUtils;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.TUIConversationLog;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.TUIConversationUtils;
import com.tencent.qcloud.tuikit.tuiconversation.config.TUIConversationConfig;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class ConversationProvider {
private static final String TAG = ConversationProvider.class.getSimpleName();
protected boolean isFinished = false;
protected long nextLoadSeq = 0L;
private List<ConversationInfo> markConversationInfoList = new ArrayList<>();
private HashMap<String, V2TIMConversation> markUnreadMap = new HashMap<>();
public void loadConversation(long startSeq, int loadCount, final IUIKitCallback<List<ConversationInfo>> callBack) {
TUIConversationLog.i(TAG, "loadConversation startSeq " + startSeq + " loadCount " + loadCount);
V2TIMManager.getConversationManager().getConversationList(startSeq, loadCount, new V2TIMValueCallback<V2TIMConversationResult>() {
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(
TAG, "loadConversation getConversationList error, code = " + code + ", desc = " + ErrorMessageConverter.convertIMError(code, desc));
TUIConversationUtils.callbackOnError(callBack, TAG, code, desc);
}
@Override
public void onSuccess(V2TIMConversationResult v2TIMConversationResult) {
List<V2TIMConversation> v2TIMConversationList = v2TIMConversationResult.getConversationList();
List<ConversationInfo> conversationInfoList = ConversationUtils.convertV2TIMConversationList(v2TIMConversationList);
TUIConversationLog.i(TAG,
"loadConversation getConversationList success size " + conversationInfoList.size() + " nextSeq " + v2TIMConversationResult.getNextSeq()
+ " isFinished " + v2TIMConversationResult.isFinished());
if (!conversationInfoList.isEmpty()) {
TUIConversationLog.i(TAG,
"loadConversation getConversationList success first " + conversationInfoList.get(0) + " last "
+ conversationInfoList.get(conversationInfoList.size() - 1));
}
isFinished = v2TIMConversationResult.isFinished();
nextLoadSeq = v2TIMConversationResult.getNextSeq();
TUIConversationUtils.callbackOnSuccess(callBack, conversationInfoList);
}
});
}
public void loadMoreConversation(int loadCount, IUIKitCallback<List<ConversationInfo>> callBack) {
if (isFinished) {
return;
}
loadConversation(nextLoadSeq, loadCount, callBack);
}
public boolean isLoadFinished() {
return isFinished;
}
public void getConversation(String conversationID, IUIKitCallback<ConversationInfo> callback) {
V2TIMManager.getConversationManager().getConversation(conversationID, new V2TIMValueCallback<V2TIMConversation>() {
@Override
public void onSuccess(V2TIMConversation v2TIMConversation) {
ConversationInfo conversationInfo = ConversationUtils.convertV2TIMConversation(v2TIMConversation);
TUIConversationUtils.callbackOnSuccess(callback, conversationInfo);
}
@Override
public void onError(int code, String desc) {
TUIConversationLog.v(TAG, "getConversation error, code = " + code + ", desc = " + ErrorMessageConverter.convertIMError(code, desc));
TUIConversationUtils.callbackOnError(callback, TAG, code, desc);
}
});
}
public void getTotalUnreadMessageCount(IUIKitCallback<Long> callBack) {
V2TIMManager.getConversationManager().getTotalUnreadMessageCount(new V2TIMValueCallback<Long>() {
@Override
public void onSuccess(Long count) {
TUIConversationUtils.callbackOnSuccess(callBack, count);
}
@Override
public void onError(int code, String desc) {}
});
}
public void setConversationTop(String conversationId, boolean isTop, IUIKitCallback<Void> callBack) {
V2TIMManager.getConversationManager().pinConversation(conversationId, isTop, new V2TIMCallback() {
@Override
public void onSuccess() {
TUIConversationUtils.callbackOnSuccess(callBack, null);
}
@Override
public void onError(int code, String desc) {
TUIConversationUtils.callbackOnError(callBack, TAG, code, desc);
}
});
}
public void markConversationFold(String conversationID, boolean isFold, IUIKitCallback<Void> callback) {
List<String> conversationIDList = new ArrayList<>();
conversationIDList.add(conversationID);
V2TIMManager.getConversationManager().markConversation(
conversationIDList, V2TIMConversation.V2TIM_CONVERSATION_MARK_TYPE_FOLD, isFold, new V2TIMValueCallback<List<V2TIMConversationOperationResult>>() {
@Override
public void onSuccess(List<V2TIMConversationOperationResult> v2TIMConversationOperationResults) {
if (v2TIMConversationOperationResults.size() == 0) {
return;
}
V2TIMConversationOperationResult result = v2TIMConversationOperationResults.get(0);
if (result.getResultCode() == BaseConstants.ERR_SUCC) {
TUIConversationUtils.callbackOnSuccess(callback, null);
} else {
TUIConversationUtils.callbackOnError(callback, TAG, result.getResultCode(), result.getResultInfo());
}
}
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(TAG, "markConversationFold error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
TUIConversationUtils.callbackOnError(callback, TAG, code, desc);
}
});
}
public void markConversationHidden(String conversationID, boolean isHidden, IUIKitCallback<Void> callback) {
List<String> conversationIDList = new ArrayList<>();
if (!TextUtils.isEmpty(conversationID)) {
conversationIDList.add(conversationID);
}
V2TIMManager.getConversationManager().markConversation(conversationIDList, V2TIMConversation.V2TIM_CONVERSATION_MARK_TYPE_HIDE, isHidden,
new V2TIMValueCallback<List<V2TIMConversationOperationResult>>() {
@Override
public void onSuccess(List<V2TIMConversationOperationResult> v2TIMConversationOperationResults) {
if (v2TIMConversationOperationResults.size() == 0) {
return;
}
V2TIMConversationOperationResult result = v2TIMConversationOperationResults.get(0);
if (result.getResultCode() == BaseConstants.ERR_SUCC) {
TUIConversationUtils.callbackOnSuccess(callback, null);
} else {
TUIConversationUtils.callbackOnError(callback, TAG, result.getResultCode(), result.getResultInfo());
}
}
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(TAG, "markConversationHidden error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
TUIConversationUtils.callbackOnError(callback, TAG, code, desc);
}
});
}
public void markConversationRead(String conversationID, TUICallback callback) {
V2TIMManager.getConversationManager().markConversation(Collections.singletonList(conversationID),
V2TIMConversation.V2TIM_CONVERSATION_MARK_TYPE_UNREAD, false, new V2TIMValueCallback<List<V2TIMConversationOperationResult>>() {
@Override
public void onSuccess(List<V2TIMConversationOperationResult> v2TIMConversationOperationResults) {
if (v2TIMConversationOperationResults.isEmpty()) {
return;
}
V2TIMConversationOperationResult result = v2TIMConversationOperationResults.get(0);
if (result.getResultCode() == BaseConstants.ERR_SUCC) {
TUICallback.onSuccess(callback);
} else {
TUICallback.onError(callback, result.getResultCode(), result.getResultInfo());
}
}
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(TAG, "markConversationRead error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
TUICallback.onError(callback, code, desc);
}
});
}
public void cleanConversationUnreadCount(String conversationID, TUICallback callback) {
V2TIMManager.getConversationManager().cleanConversationUnreadMessageCount(conversationID, 0, 0, new V2TIMCallback() {
@Override
public void onSuccess() {
TUICallback.onSuccess(callback);
TUIConversationLog.i(TAG, "cleanConversationUnreadCount success");
}
@Override
public void onError(int code, String desc) {
TUICallback.onError(callback, code, desc);
TUIConversationLog.e(
TAG, "cleanConversationUnreadCount error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
}
});
}
public void markConversationUnread(String conversationID, TUICallback callback) {
V2TIMManager.getConversationManager().markConversation(Collections.singletonList(conversationID),
V2TIMConversation.V2TIM_CONVERSATION_MARK_TYPE_UNREAD, true, new V2TIMValueCallback<List<V2TIMConversationOperationResult>>() {
@Override
public void onSuccess(List<V2TIMConversationOperationResult> v2TIMConversationOperationResults) {
if (v2TIMConversationOperationResults.isEmpty()) {
return;
}
V2TIMConversationOperationResult result = v2TIMConversationOperationResults.get(0);
if (result.getResultCode() == BaseConstants.ERR_SUCC) {
TUICallback.onSuccess(callback);
} else {
TUICallback.onError(callback, result.getResultCode(), result.getResultInfo());
}
}
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(TAG, "markConversationUnread error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
TUICallback.onError(callback, code, desc);
}
});
}
public void markConversationUnread(ConversationInfo conversationInfo, boolean markUnread, IUIKitCallback<Void> callback) {
List<String> conversationIDList = new ArrayList<>();
if (!TextUtils.isEmpty(conversationInfo.getConversationId())) {
conversationIDList.add(conversationInfo.getConversationId());
}
if (!markUnread && conversationInfo.getUnRead() > 0) {
V2TIMManager.getConversationManager().cleanConversationUnreadMessageCount(conversationInfo.getConversationId(), 0, 0, new V2TIMCallback() {
@Override
public void onSuccess() {
TUIConversationLog.i(TAG, "markConversationUnread->cleanConversationUnreadMessageCount success");
}
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(
TAG, "cleanConversationUnreadMessageCount error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
}
});
}
if (markUnread != conversationInfo.isMarkUnread()) {
V2TIMManager.getConversationManager().markConversation(conversationIDList, V2TIMConversation.V2TIM_CONVERSATION_MARK_TYPE_UNREAD, markUnread,
new V2TIMValueCallback<List<V2TIMConversationOperationResult>>() {
@Override
public void onSuccess(List<V2TIMConversationOperationResult> v2TIMConversationOperationResults) {
if (v2TIMConversationOperationResults.size() == 0) {
return;
}
V2TIMConversationOperationResult result = v2TIMConversationOperationResults.get(0);
if (result.getResultCode() == BaseConstants.ERR_SUCC) {
TUIConversationUtils.callbackOnSuccess(callback, null);
} else {
TUIConversationUtils.callbackOnError(callback, TAG, result.getResultCode(), result.getResultInfo());
}
}
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(TAG, "markConversationUnread error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
TUIConversationUtils.callbackOnError(callback, TAG, code, desc);
}
});
}
}
public void deleteConversation(String conversationId, IUIKitCallback<Void> callBack) {
V2TIMManager.getConversationManager().deleteConversation(conversationId, new V2TIMCallback() {
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(TAG, "deleteConversation error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
TUIConversationUtils.callbackOnError(callBack, TAG, code, desc);
}
@Override
public void onSuccess() {
TUIConversationLog.i(TAG, "deleteConversation success");
TUIConversationUtils.callbackOnSuccess(callBack, null);
}
});
}
public void clearHistoryMessage(String userId, boolean isGroup, IUIKitCallback<Void> callBack) {
if (isGroup) {
V2TIMManager.getMessageManager().clearGroupHistoryMessage(userId, new V2TIMCallback() {
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(TAG, "clearConversationMessage error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
TUIConversationUtils.callbackOnError(callBack, TAG, code, desc);
}
@Override
public void onSuccess() {
TUIConversationLog.i(TAG, "clearConversationMessage success");
TUIConversationUtils.callbackOnSuccess(callBack, null);
}
});
} else {
V2TIMManager.getMessageManager().clearC2CHistoryMessage(userId, new V2TIMCallback() {
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(TAG, "clearConversationMessage error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
TUIConversationUtils.callbackOnError(callBack, TAG, code, desc);
}
@Override
public void onSuccess() {
TUIConversationLog.i(TAG, "clearConversationMessage success");
TUIConversationUtils.callbackOnSuccess(callBack, null);
}
});
}
}
public void getGroupMemberIconList(String groupId, int iconCount, IUIKitCallback<List<Object>> callback) {
V2TIMManager.getGroupManager().getGroupMemberList(
groupId, V2TIMGroupMemberFullInfo.V2TIM_GROUP_MEMBER_FILTER_ALL, 0, new V2TIMValueCallback<V2TIMGroupMemberInfoResult>() {
@Override
public void onError(int code, String desc) {
TUIConversationUtils.callbackOnError(callback, code, desc);
TUIConversationLog.e("ConversationIconView",
"getGroupMemberList failed! groupID:" + groupId + "|code:" + code + "|desc: " + ErrorMessageConverter.convertIMError(code, desc));
}
@Override
public void onSuccess(V2TIMGroupMemberInfoResult v2TIMGroupMemberInfoResult) {
List<V2TIMGroupMemberFullInfo> v2TIMGroupMemberFullInfoList = v2TIMGroupMemberInfoResult.getMemberInfoList();
int faceSize = Math.min(v2TIMGroupMemberFullInfoList.size(), iconCount);
final List<Object> urlList = new ArrayList<>();
for (int i = 0; i < faceSize; i++) {
V2TIMGroupMemberFullInfo v2TIMGroupMemberFullInfo = v2TIMGroupMemberFullInfoList.get(i);
urlList.add(v2TIMGroupMemberFullInfo.getFaceUrl());
}
TUIConversationUtils.callbackOnSuccess(callback, urlList);
}
});
}
public void loadConversationUserStatus(List<ConversationInfo> dataSource, IUIKitCallback<Map<String, ConversationUserStatusBean>> callback) {
if (dataSource == null || dataSource.size() == 0) {
TUIConversationLog.d(TAG, "loadConversationUserStatus datasource is null");
return;
}
List<String> userList = new ArrayList<>();
for (ConversationInfo itemBean : dataSource) {
if (itemBean.isGroup()) {
continue;
}
userList.add(itemBean.getId());
}
if (userList.isEmpty()) {
TUIConversationLog.d(TAG, "loadConversationUserStatus userList is empty");
return;
}
V2TIMManager.getInstance().getUserStatus(userList, new V2TIMValueCallback<List<V2TIMUserStatus>>() {
@Override
public void onSuccess(List<V2TIMUserStatus> v2TIMUserStatuses) {
TUIConversationLog.i(TAG, "getUserStatus success");
Map<String, ConversationUserStatusBean> userStatusBeanMap = new HashMap<>();
for (V2TIMUserStatus item : v2TIMUserStatuses) {
ConversationUserStatusBean conversationUserStatusBean = new ConversationUserStatusBean();
conversationUserStatusBean.setV2TIMUserStatus(item);
userStatusBeanMap.put(item.getUserID(), conversationUserStatusBean);
}
TUIConversationUtils.callbackOnSuccess(callback, userStatusBeanMap);
}
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(TAG, "getUserStatus error code = " + code + ",des = " + desc);
TUIConversationUtils.callbackOnError(callback, code, desc);
if (code == TUIConstants.BuyingFeature.ERR_SDK_INTERFACE_NOT_SUPPORT && TUIConversationConfig.getInstance().isShowUserStatus()
&& BuildConfig.DEBUG) {
ToastUtil.toastLongMessage(desc);
}
}
});
}
public void subscribeConversationUserStatus(List<String> userIdList, IUIKitCallback<Void> callback) {
if (userIdList == null || userIdList.size() == 0) {
TUIConversationLog.e(TAG, "subscribeConversationUserStatus userId is null");
TUIConversationUtils.callbackOnError(callback, BaseConstants.ERR_INVALID_PARAMETERS, "userid list is null");
return;
}
V2TIMManager.getInstance().subscribeUserStatus(userIdList, new V2TIMCallback() {
@Override
public void onSuccess() {
TUIConversationUtils.callbackOnSuccess(callback, null);
}
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(TAG, "subscribeConversationUserStatus error code = " + code + ",des = " + desc);
TUIConversationUtils.callbackOnError(callback, code, desc);
}
});
}
public void getMarkConversationList(
final V2TIMConversationListFilter filter, long nextSeq, int count, boolean fromStart, IUIKitCallback<List<ConversationInfo>> callback) {
if (fromStart) {
markConversationInfoList.clear();
}
V2TIMManager.getConversationManager().getConversationListByFilter(filter, nextSeq, count, new V2TIMValueCallback<V2TIMConversationResult>() {
@Override
public void onSuccess(V2TIMConversationResult v2TIMConversationResult) {
List<V2TIMConversation> conversationList = v2TIMConversationResult.getConversationList();
List<ConversationInfo> conversationInfoList = ConversationUtils.convertV2TIMConversationList(conversationList);
markConversationInfoList.addAll(conversationInfoList);
if (!v2TIMConversationResult.isFinished()) {
getMarkConversationList(filter, v2TIMConversationResult.getNextSeq(), count, false, callback);
} else {
if (callback != null) {
callback.onSuccess(markConversationInfoList);
}
}
}
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(TAG, "getMarkConversationList error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
}
});
}
public void clearAllUnreadMessage(IUIKitCallback<Void> callback) {
V2TIMManager.getConversationManager().cleanConversationUnreadMessageCount("", 0, 0, new V2TIMCallback() {
@Override
public void onSuccess() {
TUIConversationLog.i(TAG, "clearAllUnreadMessage success");
TUIConversationUtils.callbackOnSuccess(callback, null);
}
@Override
public void onError(int code, String desc) {
TUIConversationLog.i(TAG, "clearAllUnreadMessage error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
TUIConversationUtils.callbackOnError(callback, code, desc);
}
});
V2TIMConversationListFilter filter = new V2TIMConversationListFilter();
filter.setMarkType(V2TIMConversation.V2TIM_CONVERSATION_MARK_TYPE_UNREAD);
getMarkUnreadConversationList(filter, 0, 100, true, new V2TIMValueCallback<HashMap<String, V2TIMConversation>>() {
@Override
public void onSuccess(HashMap<String, V2TIMConversation> stringV2TIMConversationHashMap) {
if (stringV2TIMConversationHashMap.size() == 0) {
return;
}
List<String> unreadConversationIDList = new ArrayList<>();
Iterator<Map.Entry<String, V2TIMConversation>> iterator = markUnreadMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, V2TIMConversation> entry = iterator.next();
unreadConversationIDList.add(entry.getKey());
}
V2TIMManager.getConversationManager().markConversation(unreadConversationIDList, V2TIMConversation.V2TIM_CONVERSATION_MARK_TYPE_UNREAD, false,
new V2TIMValueCallback<List<V2TIMConversationOperationResult>>() {
@Override
public void onSuccess(List<V2TIMConversationOperationResult> v2TIMConversationOperationResults) {
for (V2TIMConversationOperationResult result : v2TIMConversationOperationResults) {
if (result.getResultCode() == BaseConstants.ERR_SUCC) {
V2TIMConversation v2TIMConversation = markUnreadMap.get(result.getConversationID());
if (!v2TIMConversation.getMarkList().contains(V2TIMConversation.V2TIM_CONVERSATION_MARK_TYPE_HIDE)) {
markUnreadMap.remove(result.getConversationID());
}
}
}
TUIConversationUtils.callbackOnSuccess(callback, null);
}
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(TAG,
"triggerClearAllUnreadMessage->markConversation error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
TUIConversationUtils.callbackOnError(callback, code, desc);
}
});
}
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(TAG,
"triggerClearAllUnreadMessage->getMarkUnreadConversationList error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
}
});
}
private void getMarkUnreadConversationList(
V2TIMConversationListFilter filter, long nextSeq, int count, boolean fromStart, V2TIMValueCallback<HashMap<String, V2TIMConversation>> callback) {
if (fromStart) {
markUnreadMap.clear();
}
V2TIMManager.getConversationManager().getConversationListByFilter(filter, nextSeq, count, new V2TIMValueCallback<V2TIMConversationResult>() {
@Override
public void onSuccess(V2TIMConversationResult v2TIMConversationResult) {
List<V2TIMConversation> conversationList = v2TIMConversationResult.getConversationList();
for (V2TIMConversation conversation : conversationList) {
markUnreadMap.put(conversation.getConversationID(), conversation);
}
if (!v2TIMConversationResult.isFinished()) {
getMarkUnreadConversationList(filter, v2TIMConversationResult.getNextSeq(), count, false, callback);
} else {
if (callback != null) {
callback.onSuccess(markUnreadMap);
}
}
}
@Override
public void onError(int code, String desc) {
TUIConversationLog.e(TAG, "getMarkUnreadConversationList error:" + code + ", desc:" + ErrorMessageConverter.convertIMError(code, desc));
}
});
}
}

View File

@@ -0,0 +1,506 @@
package com.tencent.qcloud.tuikit.tuiconversation.presenter;
import android.text.TextUtils;
import com.tencent.imsdk.v2.V2TIMConversation;
import com.tencent.imsdk.v2.V2TIMConversationListFilter;
import com.tencent.imsdk.v2.V2TIMMessage;
import com.tencent.imsdk.v2.V2TIMUserStatus;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuikit.timcommon.bean.TUIMessageBean;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuiconversation.TUIConversationService;
import com.tencent.qcloud.tuikit.tuiconversation.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.ConversationUtils;
import com.tencent.qcloud.tuikit.tuiconversation.commonutil.TUIConversationLog;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.ConversationEventListener;
import com.tencent.qcloud.tuikit.tuiconversation.interfaces.IConversationListAdapter;
import com.tencent.qcloud.tuikit.tuiconversation.model.ConversationProvider;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
public class ConversationFoldPresenter {
private static final String TAG = ConversationFoldPresenter.class.getSimpleName();
private static final int GET_CONVERSATION_COUNT = 100;
ConversationEventListener conversationEventForMarkObserver;
private final ConversationProvider provider;
private IConversationListAdapter adapter;
private final List<ConversationInfo> loadedConversationInfoList = new ArrayList<>();
public ConversationFoldPresenter() {
provider = new ConversationProvider();
}
public void setAdapter(IConversationListAdapter adapter) {
this.adapter = adapter;
}
public void initListener() {
conversationEventForMarkObserver = new ConversationEventListener() {
@Override
public void deleteConversation(String chatId, boolean isGroup) {
ConversationFoldPresenter.this.deleteConversationFromUI(chatId, isGroup);
}
@Override
public void clearConversationMessage(String chatId, boolean isGroup) {}
@Override
public void clearFoldMarkAndDeleteConversation(String conversationId) {
ConversationFoldPresenter.this.deleteConversationFromUI(conversationId);
}
@Override
public void setConversationTop(String chatId, boolean isChecked, IUIKitCallback<Void> iuiKitCallBack) {}
@Override
public boolean isTopConversation(String chatId) {
return false;
}
@Override
public long getUnreadTotal() {
return 0;
}
@Override
public void onSyncServerFinish() {}
@Override
public void updateTotalUnreadMessageCount(long count) {}
@Override
public void onNewConversation(List<ConversationInfo> conversationList) {
ConversationFoldPresenter.this.onNewConversation(conversationList);
}
@Override
public void onConversationChanged(List<ConversationInfo> conversationList) {
ConversationFoldPresenter.this.onConversationChanged(conversationList);
}
@Override
public void onFriendRemarkChanged(String id, String remark) {}
@Override
public void onUserStatusChanged(List<V2TIMUserStatus> userStatusList) {}
@Override
public void refreshUserStatusFragmentUI() {}
@Override
public void onReceiveMessage(String conversationID, boolean isTypingMessage) {
processNewMessage(conversationID, isTypingMessage);
}
@Override
public void onMessageSendForHideConversation(String conversationID) {}
@Override
public void onConversationDeleted(List<String> conversationIDList) {
ConversationFoldPresenter.this.onConversationDeleted(conversationIDList);
}
@Override
public void onConversationLastMessageBeanChanged(String conversationID, TUIMessageBean messageBean) {
ConversationFoldPresenter.this.onConversationLastMessageBeanChanged(conversationID, messageBean);
}
};
TUIConversationService.getInstance().addConversationEventListener(conversationEventForMarkObserver);
}
public void destroy() {
TUIConversationService.getInstance().removeConversationEventListener(conversationEventForMarkObserver);
this.conversationEventForMarkObserver = null;
}
public void loadConversation() {
TUIConversationLog.i(TAG, "loadConversation");
V2TIMConversationListFilter filter = new V2TIMConversationListFilter();
long markType = V2TIMConversation.V2TIM_CONVERSATION_MARK_TYPE_FOLD;
filter.setMarkType(markType);
provider.getMarkConversationList(filter, 0, GET_CONVERSATION_COUNT, true, new IUIKitCallback<List<ConversationInfo>>() {
@Override
public void onSuccess(List<ConversationInfo> conversationInfoList) {
if (conversationInfoList.size() == 0) {
return;
}
Collections.sort(conversationInfoList);
List<ConversationInfo> loadList = new ArrayList<>();
for (ConversationInfo conversationInfo : conversationInfoList) {
if (!conversationInfo.isMarkHidden()) {
loadList.add(conversationInfo);
}
}
onLoadConversationCompleted(loadList);
}
@Override
public void onError(String module, int errCode, String errMsg) {
TUIConversationLog.e(TAG, "loadConversation error:" + errCode + ", " + errMsg);
if (adapter != null) {
adapter.onLoadingStateChanged(false);
}
}
});
}
private void onLoadConversationCompleted(List<ConversationInfo> conversationInfoList) {
onNewConversation(conversationInfoList);
if (adapter != null) {
adapter.onLoadingStateChanged(false);
}
}
public void onNewConversation(List<ConversationInfo> conversationInfoList) {
TUIConversationLog.i(TAG, "onNewConversation conversations:" + conversationInfoList);
if (conversationInfoList.size() == 0) {
return;
}
getLastMessageBean(conversationInfoList);
ArrayList<ConversationInfo> processedInfoList = processFoldedAndHiddenConversation(conversationInfoList);
List<ConversationInfo> exists = new ArrayList<>();
Iterator<ConversationInfo> iterator = processedInfoList.iterator();
while (iterator.hasNext()) {
ConversationInfo update = iterator.next();
for (int i = 0; i < loadedConversationInfoList.size(); i++) {
ConversationInfo cacheInfo = loadedConversationInfoList.get(i);
if (cacheInfo.getConversationId().equals(update.getConversationId())) {
loadedConversationInfoList.set(i, update);
iterator.remove();
exists.add(update);
break;
}
}
}
Collections.sort(processedInfoList);
loadedConversationInfoList.addAll(processedInfoList);
if (adapter != null) {
Collections.sort(loadedConversationInfoList);
adapter.onDataSourceChanged(loadedConversationInfoList);
for (ConversationInfo info : processedInfoList) {
int index = loadedConversationInfoList.indexOf(info);
if (index != -1) {
adapter.onItemInserted(index);
}
}
for (ConversationInfo info : exists) {
int index = loadedConversationInfoList.indexOf(info);
if (index != -1) {
adapter.onItemChanged(index);
}
}
}
}
public void onConversationChanged(List<ConversationInfo> conversationInfoList) {
TUIConversationLog.i(TAG, "onConversationChanged conversations:" + conversationInfoList);
getLastMessageBean(conversationInfoList);
ArrayList<ConversationInfo> addInfoList = new ArrayList<>();
ArrayList<ConversationInfo> infoList = processFoldedAndHiddenConversation(conversationInfoList);
ArrayList<ConversationInfo> changedInfoList = new ArrayList<>();
for (ConversationInfo conversationInfo : infoList) {
if (!ConversationUtils.isIgnored(conversationInfo)) {
boolean exists = false;
for (ConversationInfo loadedInfo : loadedConversationInfoList) {
if (TextUtils.equals(conversationInfo.getConversationId(), loadedInfo.getConversationId())) {
exists = true;
break;
}
}
if (exists) {
TUIConversationLog.i(TAG, "onConversationChanged conversationInfo " + conversationInfo);
changedInfoList.add(conversationInfo);
} else {
addInfoList.add(conversationInfo);
}
}
}
if (!addInfoList.isEmpty()) {
onNewConversation(addInfoList);
}
if (changedInfoList.size() == 0) {
return;
}
refreshChangedInfo(loadedConversationInfoList, changedInfoList);
}
private void refreshChangedInfo(List<ConversationInfo> uiSourceInfoList, List<ConversationInfo> changedInfoList) {
Collections.sort(changedInfoList);
HashMap<ConversationInfo, Integer> indexMap = new HashMap<>();
for (int j = 0; j < changedInfoList.size(); j++) {
ConversationInfo update = changedInfoList.get(j);
for (int i = 0; i < uiSourceInfoList.size(); i++) {
ConversationInfo cacheInfo = uiSourceInfoList.get(i);
if (cacheInfo.getConversationId().equals(update.getConversationId())) {
if (update.getStatusType() == V2TIMUserStatus.V2TIM_USER_STATUS_UNKNOWN) {
update.setStatusType(cacheInfo.getStatusType());
}
uiSourceInfoList.set(i, update);
indexMap.put(update, i);
break;
}
}
}
if (adapter != null) {
Collections.sort(uiSourceInfoList);
adapter.onDataSourceChanged(uiSourceInfoList);
int minRefreshIndex = Integer.MAX_VALUE;
int maxRefreshIndex = Integer.MIN_VALUE;
for (ConversationInfo info : changedInfoList) {
Integer oldIndexObj = indexMap.get(info);
if (oldIndexObj == null) {
continue;
}
int oldIndex = oldIndexObj;
int newIndex = uiSourceInfoList.indexOf(info);
if (newIndex != -1) {
minRefreshIndex = Math.min(minRefreshIndex, Math.min(oldIndex, newIndex));
maxRefreshIndex = Math.max(maxRefreshIndex, Math.max(oldIndex, newIndex));
}
}
int count;
if (minRefreshIndex == maxRefreshIndex) {
count = 1;
} else {
count = maxRefreshIndex - minRefreshIndex + 1;
}
if (count > 0 && maxRefreshIndex >= minRefreshIndex) {
adapter.onItemRangeChanged(minRefreshIndex, count);
}
}
}
private ArrayList<ConversationInfo> processFoldedAndHiddenConversation(List<ConversationInfo> infoList) {
ArrayList<ConversationInfo> changedInfoList = new ArrayList<>();
for (ConversationInfo conversationInfo : infoList) {
int uiIndex = -1;
for (int i = 0; i < loadedConversationInfoList.size(); i++) {
ConversationInfo loadedInfo = loadedConversationInfoList.get(i);
if (TextUtils.equals(conversationInfo.getConversationId(), loadedInfo.getConversationId())) {
uiIndex = i;
break;
}
}
if (uiIndex >= 0) {
if (!conversationInfo.isMarkFold() || conversationInfo.isMarkHidden()) {
loadedConversationInfoList.remove(uiIndex);
if (adapter != null) {
adapter.onItemRemoved(uiIndex);
}
} else if (conversationInfo.isMarkFold()) {
changedInfoList.add(conversationInfo);
}
} else {
if (conversationInfo.isMarkFold() && !conversationInfo.isMarkHidden()) {
changedInfoList.add(conversationInfo);
}
}
}
return changedInfoList;
}
private void processNewMessage(String conversationID, boolean isTypingMessage) {
if (TextUtils.isEmpty(conversationID)) {
return;
}
if (isTypingMessage) {
return;
}
ConversationInfo cacheInfo = null;
for (ConversationInfo conversationInfo : loadedConversationInfoList) {
if (TextUtils.equals(conversationID, conversationInfo.getConversationId())) {
cacheInfo = conversationInfo;
break;
}
}
if (cacheInfo != null) {
if (cacheInfo.isMarkUnread()) {
markConversationUnread(cacheInfo, false);
}
} else {
provider.getConversation(conversationID, new IUIKitCallback<ConversationInfo>() {
@Override
public void onSuccess(ConversationInfo conversationInfo) {
if (conversationInfo.isMarkHidden()) {
markConversationHidden(conversationInfo, false);
}
if (conversationInfo.isMarkUnread()) {
markConversationUnread(conversationInfo, false);
}
}
@Override
public void onError(String module, int errCode, String errMsg) {}
});
}
}
public void deleteConversation(ConversationInfo conversation) {
HashMap<String, Object> param = new HashMap<>();
param.put(TUIConstants.TUIConversation.CONVERSATION_ID, conversation.getConversationId());
TUICore.callService(TUIConstants.TUIConversation.SERVICE_NAME, TUIConstants.TUIConversation.METHOD_DELETE_CONVERSATION, param);
}
public void markConversationHidden(ConversationInfo conversationInfo, boolean isHidden) {
if (conversationInfo == null || TextUtils.isEmpty(conversationInfo.getConversationId())) {
TUIConversationLog.e(TAG, "markConversationHidden error: invalid conversationInfo");
return;
}
provider.markConversationHidden(conversationInfo.getConversationId(), isHidden, new IUIKitCallback<Void>() {
@Override
public void onSuccess(Void data) {
conversationInfo.setMarkHidden(isHidden);
TUIConversationLog.i(TAG, "markConversationHidden success, conversationID:" + conversationInfo.getConversationId() + ", isHidden:" + isHidden);
}
@Override
public void onError(String module, int errCode, String errMsg) {
TUIConversationLog.e(
TAG, "markConversationHidden error, conversationID:" + conversationInfo.getConversationId() + ", code:" + errCode + "|msg:" + errMsg);
}
});
}
public void markConversationUnread(ConversationInfo conversationInfo, boolean markUnread) {
if (conversationInfo == null || TextUtils.isEmpty(conversationInfo.getConversationId())) {
TUIConversationLog.e(TAG, "markConversationUnread error: invalid conversationInfo");
return;
}
provider.markConversationUnread(conversationInfo, markUnread, new IUIKitCallback<Void>() {
@Override
public void onSuccess(Void data) {
conversationInfo.setMarkUnread(markUnread);
TUIConversationLog.i(TAG, "markConversationRead success, conversationID:" + conversationInfo.getConversationId());
}
@Override
public void onError(String module, int errCode, String errMsg) {
TUIConversationLog.e(
TAG, "markConversationRead error, conversationID:" + conversationInfo.getConversationId() + ", code:" + errCode + "|msg:" + errMsg);
}
});
}
public void deleteConversationFromUI(String id, boolean isGroup) {
if (!isGroup) {
return;
}
for (int i = 0; i < loadedConversationInfoList.size(); i++) {
ConversationInfo info = loadedConversationInfoList.get(i);
if (TextUtils.equals(info.getId(), id)) {
boolean isRemove = loadedConversationInfoList.remove(info);
if (adapter != null && isRemove) {
adapter.onItemRemoved(i);
}
break;
}
}
}
public void deleteConversationFromUI(String conversationId) {
if (TextUtils.isEmpty(conversationId)) {
return;
}
for (int i = 0; i < loadedConversationInfoList.size(); i++) {
ConversationInfo info = loadedConversationInfoList.get(i);
if (TextUtils.equals(info.getConversationId(), conversationId)) {
boolean isRemove = loadedConversationInfoList.remove(info);
if (adapter != null && isRemove) {
adapter.onItemRemoved(i);
}
break;
}
}
}
public void onConversationDeleted(List<String> conversationIdList) {
if (conversationIdList == null || conversationIdList.isEmpty()) {
return;
}
for (String conversationId : conversationIdList) {
deleteConversationFromUI(conversationId);
}
}
private void getLastMessageBean(List<ConversationInfo> conversationInfoList) {
if (conversationInfoList == null || conversationInfoList.isEmpty()) {
return;
}
Map<String, TUIMessageBean> messageBeanMap = new HashMap<>();
for (ConversationInfo conversationInfo : conversationInfoList) {
if (conversationInfo.getLastMessage() != null && conversationInfo.getLastTUIMessageBean() == null) {
HashMap<String, Object> param = new HashMap<>();
param.put(TUIConstants.TUIChat.Method.GetTUIMessageBean.V2TIM_MESSAGE, conversationInfo.getLastMessage());
Object messageBeanObj = TUICore.callService(
TUIConstants.TUIChat.SERVICE_NAME, TUIConstants.TUIChat.Method.GetTUIMessageBean.METHOD_NAME, param);
if (messageBeanObj instanceof TUIMessageBean) {
TUIMessageBean messageBean = (TUIMessageBean) messageBeanObj;
if (messageBean.needAsyncGetDisplayString()) {
messageBeanMap.put(conversationInfo.getConversationId(), messageBean);
continue;
}
conversationInfo.setLastTUIMessageBean(messageBean);
}
}
}
HashMap<String, Object> param = new HashMap<>();
param.put(TUIConstants.TUIChat.Method.GetMessagesDisplayString.MESSAGE_MAP, messageBeanMap);
TUICore.callService(TUIConstants.TUIChat.SERVICE_NAME, TUIConstants.TUIChat.Method.GetMessagesDisplayString.METHOD_NAME, param);
}
private void onConversationLastMessageBeanChanged(String conversationID, TUIMessageBean messageBean) {
ConversationInfo changedInfo = null;
for (ConversationInfo conversationInfo : loadedConversationInfoList) {
if (TextUtils.equals(conversationInfo.getConversationId(), conversationID)) {
if (conversationInfo.getLastMessage() != null) {
String msgID = conversationInfo.getLastMessage().getMsgID();
if (TextUtils.equals(msgID, messageBean.getId())) {
conversationInfo.setLastTUIMessageBean(messageBean);
changedInfo = conversationInfo;
break;
}
}
}
}
if (changedInfo == null) {
return;
}
List<ConversationInfo> changedInfoList = new ArrayList<>();
changedInfoList.add(changedInfo);
if (adapter != null) {
adapter.onConversationChanged(changedInfoList);
}
refreshChangedInfo(loadedConversationInfoList, changedInfoList);
}
}

View File

@@ -0,0 +1,18 @@
package com.tencent.qcloud.tuikit.tuiconversation.presenter;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuiconversation.model.ConversationProvider;
import java.util.List;
public class ConversationIconPresenter {
private final ConversationProvider provider;
public ConversationIconPresenter() {
provider = new ConversationProvider();
}
public void getGroupMemberIconList(String groupId, IUIKitCallback<List<Object>> callback) {
provider.getGroupMemberIconList(groupId, 9, callback);
}
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="conversation_tab_selected_light">#147AFF</color>
</resources>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="TUIConversationLightTheme" parent="TUIBaseLightTheme">
<item name="conversation_tab_selected">@color/conversation_tab_selected_light</item>
</style>
</resources>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="conversation_tab_selected_lively">#FF3B30</color>
</resources>

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="TUIConversationLivelyTheme" parent="TUIBaseLivelyTheme">
<item name="conversation_tab_selected">@color/conversation_tab_selected_lively</item>
</style>
</resources>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FFFFFFFF" />
<corners android:radius="20dp" android:bottomLeftRadius="0dp" android:bottomRightRadius="0dp"/>
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 698 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 784 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 B

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#1F767680"/>
<corners android:radius="10dp"/>
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 644 B

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/item_left"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:paddingTop="4dp"
android:paddingStart="16dp">
<TextView
android:id="@+id/forward_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:gravity="center_vertical"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/black"
android:text="@string/forward_list_label"
android:textStyle="bold"
android:textSize="14sp" />
</RelativeLayout>

View File

@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="56dp"
android:gravity="center"
android:textColor="#147AFF"
android:textSize="17sp" />
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="@color/white" />
</LinearLayout>

View File

@@ -0,0 +1,64 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/bottom_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/conversation_bottom_bg"
android:orientation="vertical"
android:visibility="visible"
tools:visibility="visible">
<TextView
android:id="@+id/divide_line"
android:layout_width="match_parent"
android:layout_marginTop="1dp"
android:layout_height="1dp"
android:background="@color/dialog_line_bg" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/conversation_bottom_bg"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:paddingStart="38.4dp"
android:paddingEnd="38.4dp"
android:layout_marginTop="1.36dp"
android:layout_marginBottom="46.08dp"
android:orientation="horizontal" >
<TextView
android:id="@+id/not_display"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:layout_marginTop="5.76dp"
android:text="@string/not_display"
android:textColor="#147AFF"
android:textSize="14sp" />
<TextView
android:id="@+id/mark_read"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_marginTop="5.76dp"
android:layout_weight="1"
android:text="@string/mark_read"
android:textColor="#147AFF"
android:textSize="14sp" />
<TextView
android:id="@+id/delete_chat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_weight="1"
android:layout_marginTop="5.76dp"
android:text="@string/chat_delete"
android:textColor="#147AFF"
android:textSize="14sp" />
</LinearLayout>
</RelativeLayout>

View File

@@ -0,0 +1,259 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/timcommon_transparent"
android:gravity="center_vertical"
android:clipChildren="false"
android:clipToPadding="false"
android:orientation="horizontal">
<RelativeLayout
android:gravity="center_vertical"
android:background="@color/timcommon_transparent"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.ConversationIconView
android:id="@+id/conversation_icon"
android:layout_width="40dp"
android:layout_height="40dp"
tools:background="@android:drawable/ic_menu_gallery"/>
<View
android:id="@+id/user_status"
android:layout_width="10dp"
android:layout_height="10dp"
android:layout_alignBottom="@id/conversation_icon"
android:layout_alignEnd="@id/conversation_icon"
android:visibility="visible"
android:background="@drawable/conversation_minimalist_online_icon" />
<com.tencent.qcloud.tuikit.timcommon.component.UnreadCountTextView
android:id="@+id/conversation_not_disturb_unread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:includeFontPadding="false"
android:layout_alignTop="@id/conversation_icon"
android:layout_alignEnd="@id/conversation_icon"
android:layout_marginEnd="-8dp"
android:layout_marginTop="-8dp"
android:textColor="#FFFFFF"
android:textSize="11sp"
app:paint_color="#FF584C"
tools:text=""
tools:visibility="visible"/>
</RelativeLayout>
<RelativeLayout
android:gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_weight="1"
android:background="@color/timcommon_transparent"
android:layout_width="0dp"
android:layout_height="wrap_content">
<TextView
android:id="@+id/conversation_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxWidth="180dp"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:ellipsize="end"
android:gravity="top|start"
android:singleLine="true"
android:textColor="@color/black_font_color"
android:textStyle="bold"
android:textSize="14sp"
tools:text="Daniel"/>
<TextView
android:id="@+id/fold_group_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/conversation_title"
android:textSize="12sp"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#FF666666"
tools:text="FoldGroup"/>
<TextView
android:id="@+id/fold_group_name_divider"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/conversation_title"
android:layout_toEndOf="@id/fold_group_name"
android:textSize="12sp"
android:textColor="#FF666666"
android:layout_marginEnd="4dp"
android:text=":"/>
<TextView
android:id="@+id/conversation_risk"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/conversation_list_text_margin_bottom"
android:layout_below="@id/conversation_title"
android:layout_toEndOf="@id/fold_group_name_divider"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/read_dot_bg"
android:textSize="12sp"
android:visibility="gone"
android:layout_marginEnd="4dp"
android:text="@string/conversation_risk_message_extra"
tools:visibility="visible" />
<TextView
android:id="@+id/conversation_at_all"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/conversation_title"
android:layout_toEndOf="@id/conversation_risk"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/read_dot_bg"
android:textSize="12sp"
android:visibility="gone"
android:layout_marginEnd="4dp"
android:text="@string/ui_at_all"
tools:visibility="visible"/>
<TextView
android:id="@+id/conversation_at_me"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/conversation_title"
android:layout_toEndOf="@id/conversation_at_all"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/read_dot_bg"
android:textSize="12sp"
android:visibility="gone"
android:layout_marginEnd="4dp"
android:text="@string/ui_at_me"
tools:visibility="visible" />
<TextView
android:id="@+id/conversation_draft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/conversation_title"
android:layout_toEndOf="@id/conversation_at_me"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/read_dot_bg"
android:textSize="12sp"
android:visibility="gone"
android:layout_marginEnd="4dp"
android:text="@string/drafts"
tools:visibility="visible" />
<TextView
android:id="@+id/conversation_last_msg"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="start"
android:layout_gravity="start"
android:textAlignment="viewStart"
android:layout_below="@id/conversation_title"
android:layout_toEndOf="@id/conversation_draft"
android:layout_toStartOf="@id/message_status_layout"
android:layout_marginEnd="29dp"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#FF666666"
android:textSize="12sp"
tools:text="Hello" />
<RelativeLayout
android:id="@+id/message_status_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toStartOf="@id/conversation_time"
android:layout_alignBottom="@id/conversation_time"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:visibility="gone"
android:layout_marginEnd="2dp"
tools:visibility="visible">
<ImageView
android:id="@+id/message_status_sending"
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_gravity="center_vertical"
android:background="@drawable/conversation_ic_sending_status"
android:visibility="gone"
tools:visibility="visible"/>
<ImageView
android:id="@+id/message_status_failed"
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_gravity="center_vertical"
android:scaleType="fitCenter"
android:src="@drawable/conversation_ic_send_failed"
android:visibility="gone"/>
</RelativeLayout>
<TextView
android:id="@+id/conversation_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/conversation_title"
android:layout_alignParentEnd="true"
android:textColor="#FF666666"
android:textSize="12sp"
android:lineHeight="14.32sp"
tools:text="12:00"/>
<LinearLayout
android:orientation="horizontal"
android:gravity="center_vertical"
android:layout_alignParentEnd="true"
android:layout_marginBottom="3dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/not_disturb"
android:layout_width="16dp"
android:layout_height="16dp"
android:includeFontPadding="false"
android:background="@drawable/conversation_minimalist_not_disturb_icon"
android:visibility="gone"
tools:visibility="visible"/>
<com.tencent.qcloud.tuikit.timcommon.component.UnreadCountTextView
android:id="@+id/conversation_unread"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/conversation_time"
android:layout_marginStart="8dp"
android:gravity="center"
android:includeFontPadding="false"
android:textColor="#FFFFFF"
android:textSize="11sp"
app:paint_color="#FF584C"
android:layout_alignParentEnd="true"
tools:text="2"
tools:visibility="visible"/>
</LinearLayout>
</RelativeLayout>
</LinearLayout>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/conversation_page_bg">
<com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.FoldedConversationLayout
android:id="@+id/folded_conversation_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>

View File

@@ -0,0 +1,16 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.tencent.qcloud.tuikit.timcommon.component.MinimalistTitleBar
android:id="@+id/conversation_title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.FoldedConversationListLayout
android:id="@+id/folded_conversation_list"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/btn_margin_bottom"
android:clickable="true">
<com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.ConversationIconView
android:id="@+id/conversation_user_icon_view"
android:layout_width="41dp"
android:layout_height="41dp"
app:default_image="?attr/core_default_user_icon"
android:visibility="gone"/>
</LinearLayout>

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.ForwardSelectLayout
android:id="@+id/forward_conversation_layout"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dp" />
<androidx.cardview.widget.CardView
android:id="@+id/forward_list_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardBackgroundColor="@color/white"
app:cardElevation="16dp"
app:contentPaddingBottom="40dp"
app:contentPaddingLeft="16dp"
app:contentPaddingRight="16dp"
app:contentPaddingTop="14dp">
<LinearLayout
android:id="@+id/forward_select_list_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:orientation="horizontal">
<HorizontalScrollView
android:layout_weight="1"
android:layout_marginEnd="16dp"
android:layout_width="0dp"
android:layout_height="wrap_content">
<TextView
android:id="@+id/conversation_name_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:textColor="@color/black"/>
</HorizontalScrollView>
<TextView
android:id="@+id/btn_msg_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/conversation_forward"
android:textColor="#0365F9"
android:textSize="14sp"
android:visibility="visible" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>

View File

@@ -0,0 +1,58 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#99000000"
android:focusable="true"
android:focusableInTouchMode="true"
android:orientation="vertical"
android:paddingTop="40dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/conversation_forward_selected_page_border"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="16dp"
android:paddingTop="22dp"
android:paddingEnd="16dp"
android:paddingBottom="12dp">
<TextView
android:id="@+id/cancel_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.33"
android:text="@string/cancel"
android:textColor="#0365F9"
android:textSize="16sp" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.33"
android:gravity="center_horizontal"
android:textColor="@color/black"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_width="0dp"
android:layout_height="8dp"
android:layout_weight="0.33" />
</LinearLayout>
<com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.ConversationListLayout
android:id="@+id/conversation_list"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
</FrameLayout>

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:gravity="center_vertical"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:lineHeight="41dp"
android:text="@string/conversation_minimalist_chat"
android:textColor="@color/black_font_color"
android:textSize="34sp"
android:textStyle="bold" />
<ImageView
android:id="@+id/home_rtcube"
android:layout_width="40dp"
android:layout_height="32dp"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:background="?attr/core_title_bar_back_icon"
android:visibility="gone"
tools:visibility="visible"
android:clickable="false" />
<TextView
android:id="@+id/edit_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:textColor="@color/font_blue"
android:textStyle="bold"
android:text="@string/conversation_title_edit"
android:layout_toStartOf="@+id/create_new_button" />
<ImageView
android:id="@+id/create_new_button"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginStart="25dp"
android:background="@drawable/conversation_minimalist_edit_icon" />
<TextView
android:id="@+id/edit_done"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/conversation_minimalist_done"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:textColor="@color/font_blue"
android:textSize="16sp"
android:visibility="gone"
tools:visibility="visible"/>
</RelativeLayout>
<TextView
android:id="@+id/title_rtcube"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:lineHeight="41dp"
android:visibility="gone"
android:text="@string/conversation_minimalist_chat"
android:textColor="@color/black_font_color"
android:textSize="34sp"
android:textStyle="bold" />
</LinearLayout>

View File

@@ -0,0 +1,37 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/more_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="34dp"
android:background="@color/transparent"
android:gravity="center"
android:orientation="vertical"
android:visibility="visible"
tools:visibility="visible">
<LinearLayout
android:id="@+id/layout_actions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:alpha="0.95"
android:background="@drawable/common_dialog_react_bg"
android:orientation="vertical">
</LinearLayout>
<TextView
android:id="@+id/cancel_button"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_below="@+id/layout_actions"
android:layout_marginTop="12dp"
android:background="@drawable/common_dialog_react_bg"
android:gravity="center"
android:text="@string/cancel"
android:textColor="#147AFF"
android:textSize="17sp" />
</RelativeLayout>

View File

@@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<com.tencent.qcloud.tuikit.timcommon.component.swipe.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/swipe"
android:layout_width="match_parent"
android:layout_height="64dp"
android:background="#FFFFFF"
app:clickToClose="false">
<RelativeLayout
android:id="@+id/bottom_wrapper_2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:tag="Bottom4">
<RelativeLayout
android:id="@+id/more_view"
android:layout_width="70dp"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:background="@color/black"
android:gravity="center">
<ImageView
android:id="@+id/more_image"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="@drawable/conversation_minimalist_more_icon" />
<TextView
android:id="@+id/more_text"
android:layout_width="70dp"
android:layout_height="match_parent"
android:layout_below="@+id/more_image"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:text="@string/more_text"
android:textColor="@color/white"
android:textSize="12sp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/mark_read"
android:layout_width="70dp"
android:layout_height="match_parent"
android:layout_toEndOf="@id/more_view"
android:background="@color/conversation_mark_swipe_bg"
android:gravity="center">
<ImageView
android:id="@+id/mark_read_image"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" />
<TextView
android:id="@+id/mark_read_text"
android:layout_width="70dp"
android:layout_height="match_parent"
android:layout_below="@+id/mark_read_image"
android:layout_centerInParent="true"
android:background="@color/transparent"
android:gravity="center"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:text="@string/mark_read"
android:textColor="@color/white"
android:textSize="12sp" />
</RelativeLayout>
<TextView
android:id="@+id/not_display"
android:layout_width="70dp"
android:layout_height="match_parent"
android:background="@color/conversation_mark_swipe_bg"
android:gravity="center"
android:layout_toEndOf="@id/mark_read"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:text="@string/not_display"
android:textColor="@color/white"
android:textSize="12sp"
android:visibility="gone" />
</RelativeLayout>
<LinearLayout
android:id="@+id/item_left"
android:layout_width="match_parent"
android:layout_height="64dp"
android:background="#FFFFFF"
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="16dp"
android:paddingEnd="42dp">
<include
layout="@layout/minimalist_conversation_list_item_sub_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:tag="Hover" />
<CheckBox
android:id="@+id/select_checkbox"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentStart="true"
android:layout_gravity="center_vertical"
android:background="@drawable/conversation_checkbox_selector"
android:button="@null"
android:visibility="gone"
tools:visibility="visible"/>
</LinearLayout>
</com.tencent.qcloud.tuikit.timcommon.component.swipe.SwipeLayout>

View File

@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/conversation_page_bg">
<com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.ConversationLayout
android:id="@+id/conversation_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<include layout="@layout/minimalist_bottom_bar"
android:layout_marginBottom="@dimen/page_margin"
android:layout_height="wrap_content"
android:layout_width="match_parent" />
</LinearLayout>

View File

@@ -0,0 +1,46 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include
layout="@layout/minimalist_header_view_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="9dp"
android:layout_marginEnd="16dp" />
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.AppBarLayout
android:background="@color/transparent"
app:elevation="0dp"
app:layout_insetEdge="none"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:id="@+id/search_layout"
android:layout_width="match_parent"
android:layout_height="32dp"
android:layout_marginStart="16dp"
android:layout_marginTop="9dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="15dp"
android:visibility="gone"
app:layout_scrollFlags="scroll|exitUntilCollapsed" />
</com.google.android.material.appbar.AppBarLayout>
<com.tencent.qcloud.tuikit.tuiconversation.minimalistui.widget.ConversationListLayout
android:id="@+id/conversation_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</LinearLayout>

View File

@@ -0,0 +1,134 @@
<?xml version="1.0" encoding="utf-8"?>
<com.tencent.qcloud.tuikit.timcommon.component.swipe.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/swipe"
android:layout_width="match_parent"
android:layout_height="64dp"
app:clickToClose="false">
<RelativeLayout
android:id="@+id/bottom_wrapper_2"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:tag="Bottom4">
<RelativeLayout
android:id="@+id/more_view"
android:layout_width="70dp"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:background="@color/black"
android:gravity="center">
<ImageView
android:id="@+id/more_image"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="@drawable/conversation_minimalist_more_icon" />
<TextView
android:id="@+id/more_text"
android:layout_width="70dp"
android:layout_height="match_parent"
android:layout_below="@+id/more_image"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:autoSizeMinTextSize="8sp"
android:autoSizeMaxTextSize="12sp"
android:autoSizeTextType="uniform"
android:text="@string/more_text"
android:textColor="@color/white"
android:textSize="12sp" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/mark_read"
android:layout_width="70dp"
android:layout_height="match_parent"
android:layout_toEndOf="@id/more_view"
android:background="@color/conversation_mark_swipe_bg"
android:gravity="center">
<ImageView
android:id="@+id/mark_read_image"
android:layout_width="18dp"
android:layout_height="18dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true" />
<TextView
android:id="@+id/mark_read_text"
android:layout_width="70dp"
android:layout_height="match_parent"
android:layout_below="@+id/mark_read_image"
android:layout_centerInParent="true"
android:background="@color/transparent"
android:gravity="center"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:autoSizeMinTextSize="8sp"
android:autoSizeMaxTextSize="12sp"
android:autoSizeTextType="uniform"
android:text="@string/mark_read"
android:textColor="@color/white"
android:textSize="12sp" />
</RelativeLayout>
<TextView
android:id="@+id/not_display"
android:layout_width="70dp"
android:layout_height="match_parent"
android:background="@color/conversation_mark_swipe_bg"
android:gravity="center"
android:layout_toEndOf="@id/mark_read"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:text="@string/not_display"
android:textColor="@color/white"
android:autoSizeMinTextSize="8sp"
android:autoSizeMaxTextSize="12sp"
android:autoSizeTextType="uniform"
android:textSize="12sp"
android:visibility="gone" />
</RelativeLayout>
<LinearLayout
android:id="@+id/item_left"
android:layout_width="match_parent"
android:layout_height="64dp"
android:background="@color/timcommon_transparent"
android:clipChildren="false"
android:clipToPadding="false"
android:gravity="center_vertical"
android:orientation="horizontal"
android:paddingStart="16dp"
android:paddingEnd="16dp">
<CheckBox
android:id="@+id/select_checkbox"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentStart="true"
android:layout_gravity="center_vertical"
android:layout_marginEnd="6.23dp"
android:background="@drawable/conversation_checkbox_selector"
android:button="@null"
android:visibility="gone"
tools:visibility="visible"/>
<include
layout="@layout/minimalist_conversation_list_item_sub_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:tag="Hover" />
</LinearLayout>
</com.tencent.qcloud.tuikit.timcommon.component.swipe.SwipeLayout>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="conversation_minimalist_chat">الدردشة</string>
<string name="conversation_minimalist_chat_disconnected">فصل</string>
<string name="conversation_minimalist_chat_connecting">ربط...</string>
<string name="conversation_minimalist_chat_loading">جمع...</string>
<string name="conversation_minimalist_search">البحث</string>
<string name="conversation_minimalist_done">تم</string>
<string name="has_all_read">تمت القراءة بالكامل</string>
<string name="start_conversation">بدء محادثة</string>
<string name="create_group_chat">إنشاء محادثة جماعية</string>
<string name="more_text">المزيد</string>
<string name="clear_message">مسح سجل المحادثة</string>
</resources>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="conversation_minimalist_chat">聊天</string>
<string name="conversation_minimalist_chat_disconnected">聊天(未連接)</string>
<string name="conversation_minimalist_chat_connecting">連接中...</string>
<string name="conversation_minimalist_chat_loading">收取中...</string>
<string name="conversation_minimalist_search">搜索</string>
<string name="conversation_minimalist_done">完成</string>
<string name="has_all_read">全部已讀</string>
<string name="start_conversation">發起會話</string>
<string name="create_group_chat">創建群聊</string>
<string name="more_text">更多</string>
<string name="clear_message">清除聊天記錄</string>
</resources>

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="conversation_minimalist_chat">聊天</string>
<string name="conversation_minimalist_chat_disconnected">聊天(未连接)</string>
<string name="conversation_minimalist_chat_connecting">连接中...</string>
<string name="conversation_minimalist_chat_loading">收取中...</string>
<string name="conversation_minimalist_search">搜索</string>
<string name="conversation_minimalist_done">完成</string>
<string name="has_all_read">全部已读</string>
<string name="start_conversation">发起会话</string>
<string name="create_group_chat">创建群聊</string>
<string name="more_text">更多</string>
<string name="clear_message">清除聊天记录</string>
</resources>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MinimalistHeaderView">
<attr name="header_title" format="string" />
</declare-styleable>
</resources>

View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="conversation_delete_swipe_bg">#F24D4C</color>
<color name="conversation_mark_swipe_bg">#147AFF</color>
<color name="conversation_mark_swipe_dark_bg">#666666</color>
<color name="conversation_hide_swipe_bg">#F29340</color>
<color name="conversation_bottom_bg">#F9F9F9</color>
</resources>

Some files were not shown because too many files have changed in this diff Show More