初始代码

This commit is contained in:
2025-09-03 18:52:07 +08:00
parent 2d21a47e87
commit 6e3e30efa5
3249 changed files with 239147 additions and 0 deletions
View File
@@ -0,0 +1,44 @@
plugins {
id 'com.android.library'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
namespace "com.tencent.qcloud.tuikit.tuisearch"
defaultConfig {
minSdkVersion 19
targetSdkVersion 30
versionCode 1
versionName "1.0"
}
buildFeatures {
buildConfig = false
}
buildTypes {
release {
minifyEnabled false
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
sourceSets {
main {
res.srcDirs += "src/main/res-minimalistui"
}
}
}
dependencies {
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'
annotationProcessor 'com.google.auto.service:auto-service:1.1.1'
api project(':timcommon')
}
@@ -0,0 +1,40 @@
<?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.tuisearch.classicui.page.SearchMainActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.tencent.qcloud.tuikit.tuisearch.classicui.page.SearchMoreListActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.tencent.qcloud.tuikit.tuisearch.classicui.page.SearchMoreMsgListActivity"
android:screenOrientation="portrait" />
<!-- **************** Classic UI Activity End **************** -->
<!-- **************** Minimalist UI Activity Start **************** -->
<activity
android:name="com.tencent.qcloud.tuikit.tuisearch.minimalistui.page.SearchMainMinimalistActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.tencent.qcloud.tuikit.tuisearch.minimalistui.page.SearchMoreListMinimalistActivity"
android:screenOrientation="portrait" />
<activity
android:name="com.tencent.qcloud.tuikit.tuisearch.minimalistui.page.SearchMoreMsgListMinimalistActivity"
android:screenOrientation="portrait" />
<!-- **************** Minimalist UI Activity End **************** -->
</application>
</manifest>
@@ -0,0 +1,18 @@
package com.tencent.qcloud.tuikit.tuisearch;
public class TUISearchConstants {
public static final String SEARCH_LIST_TYPE = "search_list_type";
public static final String SEARCH_KEY_WORDS = "search_key_words";
public static final String SEARCH_DATA_BEAN = "search_data_bean";
public static final int CONVERSATION_TYPE = 1;
public static final int CONTACT_TYPE = 2;
public static final int GROUP_TYPE = 3;
public static final int JSON_VERSION_4 = 4;
public static int version = JSON_VERSION_4;
public static String covert2HTMLString(String original) {
return "\"<font color=\"#5B6B92\">" + original + "</font>\"";
}
}
@@ -0,0 +1,180 @@
package com.tencent.qcloud.tuikit.tuisearch.bean;
import com.google.gson.Gson;
import com.google.gson.annotations.SerializedName;
import com.tencent.imsdk.v2.V2TIMManager;
import com.tencent.imsdk.v2.V2TIMMessage;
import com.tencent.imsdk.v2.V2TIMSignalingInfo;
import com.tencent.qcloud.tuikit.tuisearch.TUISearchConstants;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchLog;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
public class CallModel implements Cloneable, Serializable {
private static final String TAG = CallModel.class.getSimpleName();
/**
*
* system error
*/
public static final int VIDEO_CALL_ACTION_ERROR = -1;
/**
*
* unknown signaling
*/
public static final int VIDEO_CALL_ACTION_UNKNOWN = 0;
/**
*
* calling
*/
public static final int VIDEO_CALL_ACTION_DIALING = 1;
/**
*
* initiator cancellation
*/
public static final int VIDEO_CALL_ACTION_SPONSOR_CANCEL = 2;
/**
*
* reject the call
*/
public static final int VIDEO_CALL_ACTION_REJECT = 3;
/**
*
* no one heard
*/
public static final int VIDEO_CALL_ACTION_SPONSOR_TIMEOUT = 4;
/**
*
* hang up
*/
public static final int VIDEO_CALL_ACTION_HANGUP = 5;
/**
* phone busy
*/
public static final int VIDEO_CALL_ACTION_LINE_BUSY = 6;
/**
* answer the phone
*/
public static final int VIDEO_CALL_ACTION_ACCEPT = 7;
public static String SIGNALING_EXTRA_VALUE_BUSINESS_ID = "av_call";
public static String SIGNALING_EXTRA_KEY_BUSINESS_ID = "businessID";
public static String SIGNALING_EXTRA_KEY_CALL_TYPE = "call_type";
public static String SIGNALING_EXTRA_KEY_ROOM_ID = "room_id";
public static String SIGNALING_EXTRA_KEY_LINE_BUSY = "line_busy";
public static String SIGNALING_EXTRA_KEY_CALL_END = "call_end";
public static String SIGNALING_EXTRA_KEY_VERSION = "version";
@SerializedName("businessID") public String bussinessID;
@SerializedName("version") public int version = 0;
/**
* call ID
*/
@SerializedName("call_id") public String callId;
/**
* room ID
*/
@SerializedName("room_id") public int roomId = 0;
/**
* group ID
*/
@SerializedName("group_id") public String groupId = "";
/**
* signaling action
*/
@SerializedName("action") public int action = VIDEO_CALL_ACTION_UNKNOWN;
/**
* call type
* 0-unkown
* 1-audio call
* 2-video call
*/
@SerializedName("call_type") public int callType = 0;
/**
* Inviting list
*/
@SerializedName("invited_list") public List<String> invitedList;
@SerializedName("duration") public int duration = 0;
@SerializedName("code") public int code = 0;
public long timestamp;
public String sender;
public int timeout;
public String data;
public static CallModel convert2VideoCallData(V2TIMMessage msg) {
V2TIMSignalingInfo signalingInfo = V2TIMManager.getSignalingManager().getSignalingInfo(msg);
if (signalingInfo == null) {
return null;
}
CallModel callModel = new CallModel();
try {
Map extraMap = new Gson().fromJson(signalingInfo.getData(), Map.class);
if (extraMap != null && extraMap.containsKey(CallModel.SIGNALING_EXTRA_KEY_VERSION)
&& ((Double) extraMap.get(CallModel.SIGNALING_EXTRA_KEY_VERSION)).intValue() > TUISearchConstants.version) {
callModel.action = CallModel.VIDEO_CALL_ACTION_UNKNOWN;
return callModel;
}
callModel.data = signalingInfo.getData();
if (extraMap != null) {
callModel.bussinessID = (String) extraMap.get(CallModel.SIGNALING_EXTRA_KEY_BUSINESS_ID);
}
if (signalingInfo.getActionType() == V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_INVITE && extraMap != null) {
callModel.groupId = signalingInfo.getGroupID();
callModel.timestamp = msg.getTimestamp();
callModel.version = ((Double) extraMap.get(CallModel.SIGNALING_EXTRA_KEY_VERSION)).intValue();
if (extraMap.containsKey(CallModel.SIGNALING_EXTRA_KEY_CALL_END)) {
callModel.action = CallModel.VIDEO_CALL_ACTION_HANGUP;
callModel.duration = ((Double) extraMap.get(CallModel.SIGNALING_EXTRA_KEY_CALL_END)).intValue();
} else {
callModel.action = CallModel.VIDEO_CALL_ACTION_DIALING;
callModel.callId = signalingInfo.getInviteID();
callModel.sender = signalingInfo.getInviter();
callModel.invitedList = signalingInfo.getInviteeList();
callModel.callType = ((Double) extraMap.get(CallModel.SIGNALING_EXTRA_KEY_CALL_TYPE)).intValue();
callModel.roomId = ((Double) extraMap.get(CallModel.SIGNALING_EXTRA_KEY_ROOM_ID)).intValue();
}
} else if (signalingInfo.getActionType() == V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_CANCEL_INVITE) {
callModel.action = CallModel.VIDEO_CALL_ACTION_SPONSOR_CANCEL;
callModel.groupId = signalingInfo.getGroupID();
callModel.callId = signalingInfo.getInviteID();
callModel.version = ((Double) extraMap.get(CallModel.SIGNALING_EXTRA_KEY_VERSION)).intValue();
} else if (signalingInfo.getActionType() == V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_REJECT_INVITE && extraMap != null) {
callModel.groupId = signalingInfo.getGroupID();
callModel.callId = signalingInfo.getInviteID();
callModel.invitedList = signalingInfo.getInviteeList();
callModel.version = ((Double) extraMap.get(CallModel.SIGNALING_EXTRA_KEY_VERSION)).intValue();
if (extraMap.containsKey(CallModel.SIGNALING_EXTRA_KEY_LINE_BUSY)) {
callModel.action = CallModel.VIDEO_CALL_ACTION_LINE_BUSY;
} else {
callModel.action = CallModel.VIDEO_CALL_ACTION_REJECT;
}
} else if (signalingInfo.getActionType() == V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_INVITE_TIMEOUT) {
callModel.action = CallModel.VIDEO_CALL_ACTION_SPONSOR_TIMEOUT;
callModel.groupId = signalingInfo.getGroupID();
callModel.callId = signalingInfo.getInviteID();
callModel.invitedList = signalingInfo.getInviteeList();
} else if (signalingInfo.getActionType() == V2TIMSignalingInfo.SIGNALING_ACTION_TYPE_ACCEPT_INVITE) {
callModel.action = CallModel.VIDEO_CALL_ACTION_ACCEPT;
callModel.groupId = signalingInfo.getGroupID();
callModel.callId = signalingInfo.getInviteID();
callModel.invitedList = signalingInfo.getInviteeList();
callModel.version = ((Double) extraMap.get(CallModel.SIGNALING_EXTRA_KEY_VERSION)).intValue();
}
} catch (Exception e) {
TUISearchLog.e(TAG, "convert2VideoCallData exception:" + e);
}
return callModel;
}
}
@@ -0,0 +1,112 @@
package com.tencent.qcloud.tuikit.tuisearch.bean;
import com.tencent.imsdk.v2.V2TIMConversation;
import com.tencent.imsdk.v2.V2TIMGroupAtInfo;
import java.io.Serializable;
import java.util.List;
public class ChatInfo implements Serializable {
public static final int TYPE_C2C = V2TIMConversation.V2TIM_C2C;
public static final int TYPE_GROUP = V2TIMConversation.V2TIM_GROUP;
public static final int TYPE_INVALID = V2TIMConversation.CONVERSATION_TYPE_INVALID;
private String chatName;
private int type = V2TIMConversation.V2TIM_C2C;
private String id;
private String groupType;
private MessageInfo locateMessage;
private DraftInfo draft;
private boolean isTopChat;
public ChatInfo() {}
/**
* Get the title of the chat, usually the name of the other party for a single chat, and the group name for a group chat
*
* @return
*/
public String getChatName() {
return chatName;
}
/**
* Set the title of the chat, usually the name of the other party for a single chat, and the group name for a group chat
*
* @param chatName
*/
public void setChatName(String chatName) {
this.chatName = chatName;
}
/**
* Get the chat type, C2C is a single chat, Group is a group chat
*
* @return
*/
public int getType() {
return type;
}
/**
* Set the chat type, C2C is a single chat, Group is a group chat
*
* @param type
*/
public void setType(int type) {
this.type = type;
}
/**
* get chat id
*
* @return
*/
public String getId() {
return id;
}
/**
* set chat id
*
* @param id
*/
public void setId(String id) {
this.id = id;
}
/**
* get group type
*/
public String getGroupType() {
return groupType;
}
/**
* set group type
*/
public void setGroupType(String groupType) {
this.groupType = groupType;
}
/**
* Is it a pinned conversation
*
* @return
*/
public boolean isTopChat() {
return isTopChat;
}
public void setLocateMessage(MessageInfo locateMessage) {
this.locateMessage = locateMessage;
}
public MessageInfo getLocateMessage() {
return locateMessage;
}
public DraftInfo getDraft() {
return this.draft;
}
}
@@ -0,0 +1,214 @@
package com.tencent.qcloud.tuikit.tuisearch.bean;
import androidx.annotation.NonNull;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
public class ConversationInfo implements Serializable, Comparable<ConversationInfo> {
/**
* conversation type
*/
private int type;
/**
* unread message number
*/
private int unRead;
/**
* conversation ID
*/
private String conversationId;
/**
* ID, C2C is UserID, Group is group ID
*/
private String id;
/**
* conversation avatar url
*/
private List<Object> iconUrlList = new ArrayList<>();
public List<Object> getIconUrlList() {
return iconUrlList;
}
public void setIconUrlList(List<Object> iconUrlList) {
this.iconUrlList = iconUrlList;
}
private String title;
private String iconPath;
private boolean isGroup;
private boolean top;
private long lastMessageTime;
private MessageInfo lastMessage;
/**
* "@" 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;
}
/**
* Get the time of the last message, in seconds
*/
public long getLastMessageTime() {
return lastMessageTime;
}
/**
* Set the time to 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 MessageInfo getLastMessage() {
return lastMessage;
}
public void setLastMessage(MessageInfo 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;
}
@Override
public int compareTo(@NonNull ConversationInfo other) {
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 + '}';
}
}
@@ -0,0 +1,30 @@
package com.tencent.qcloud.tuikit.tuisearch.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 + '}';
}
}
@@ -0,0 +1,116 @@
package com.tencent.qcloud.tuikit.tuisearch.bean;
import com.tencent.imsdk.group.GroupMemberInfo;
import com.tencent.imsdk.v2.V2TIMConversation;
import com.tencent.imsdk.v2.V2TIMGroupInfoResult;
import com.tencent.imsdk.v2.V2TIMManager;
import com.tencent.imsdk.v2.V2TIMMessage;
import java.util.ArrayList;
import java.util.List;
public class GroupInfo extends ChatInfo {
private String groupType;
private int memberCount;
private String groupName;
private String notice;
private List<GroupMemberInfo> memberDetails = new ArrayList<>();
private String owner;
private boolean messageReceiveOption;
private String faceUrl;
public GroupInfo() {
setType(V2TIMConversation.V2TIM_GROUP);
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
/**
* Get group announcements
*
* @return
*/
public String getNotice() {
return notice;
}
/**
* Set group announcements
*
* @param signature
*/
public void setNotice(String signature) {
this.notice = signature;
}
/**
* Get the group type, Public/Private/ChatRoom
*
* @return
*/
public String getGroupType() {
return groupType;
}
/**
* Set the group type
*
* @param groupType
*/
public void setGroupType(String groupType) {
this.groupType = groupType;
}
/**
* Get the number of members that have joined the group
*
* @return
*/
public int getMemberCount() {
if (memberDetails != null) {
return memberDetails.size();
}
return memberCount;
}
/**
* Set the number of members that have joined the group
*
* @param memberCount
*/
public void setMemberCount(int memberCount) {
this.memberCount = memberCount;
}
/**
* Returns whether it is the owner of the group
*
* @return
*/
public boolean isOwner() {
return V2TIMManager.getInstance().getLoginUser().equals(owner);
}
/**
* Set whether it is the owner of the group
*
* @param owner
*/
public void setOwner(String owner) {
this.owner = owner;
}
public String getFaceUrl() {
return faceUrl;
}
public void setFaceUrl(String faceUrl) {
this.faceUrl = faceUrl;
}
}
@@ -0,0 +1,350 @@
package com.tencent.qcloud.tuikit.tuisearch.bean;
import android.net.Uri;
import android.text.TextUtils;
import com.tencent.imsdk.v2.V2TIMCallback;
import com.tencent.imsdk.v2.V2TIMManager;
import com.tencent.imsdk.v2.V2TIMMessage;
import com.tencent.qcloud.tuikit.tuisearch.util.MessageInfoUtil;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchLog;
import java.io.Serializable;
import java.util.UUID;
public class MessageInfo implements Serializable {
private static final String TAG = "MessageInfo";
public static final int MSG_TYPE_MIME = 0x1;
public static final int MSG_TYPE_TEXT = 0x00;
public static final int MSG_TYPE_IMAGE = 0x20;
public static final int MSG_TYPE_AUDIO = 0x30;
public static final int MSG_TYPE_VIDEO = 0x40;
public static final int MSG_TYPE_FILE = 0x50;
public static final int MSG_TYPE_LOCATION = 0x60;
public static final int MSG_TYPE_CUSTOM_FACE = 0x70;
public static final int MSG_TYPE_CUSTOM = 0x80;
public static final int MSG_TYPE_MERGE = 0x81;
public static final int MSG_TYPE_TIPS = 0x100;
public static final int MSG_TYPE_GROUP_CREATE = 0x101;
public static final int MSG_TYPE_GROUP_DELETE = 0x102;
public static final int MSG_TYPE_GROUP_JOIN = 0x103;
public static final int MSG_TYPE_GROUP_QUITE = 0x104;
public static final int MSG_TYPE_GROUP_KICK = 0x105;
public static final int MSG_TYPE_GROUP_MODIFY_NAME = 0x106;
public static final int MSG_TYPE_GROUP_MODIFY_NOTICE = 0x107;
public static final int MSG_STATUS_READ = 0x111;
public static final int MSG_STATUS_DELETE = 0x112;
public static final int MSG_STATUS_REVOKE = 0x113;
public static final int MSG_STATUS_NORMAL = 0;
public static final int MSG_STATUS_SENDING = 1;
public static final int MSG_STATUS_SEND_SUCCESS = 2;
public static final int MSG_STATUS_SEND_FAIL = 3;
public static final int MSG_STATUS_DOWNLOADING = 4;
public static final int MSG_STATUS_UN_DOWNLOAD = 5;
public static final int MSG_STATUS_DOWNLOADED = 6;
private String id = UUID.randomUUID().toString();
private long uniqueId = 0;
private String fromUser;
private String groupNameCard;
private int msgType;
private int status = MSG_STATUS_NORMAL;
private boolean self;
private boolean read;
private boolean group;
private String dataUri;
private String dataPath;
private Object extra;
private long msgTime;
private int imgWidth;
private int imgHeight;
private boolean peerRead;
private boolean isIgnoreShow = false;
private V2TIMMessage timMessage;
private String nameCard;
private String friendRemark;
private String nickName;
private String faceUrl;
private String userId;
private String groupId;
private int downloadStatus;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
/**
* Get message sender ID
*
* @return
*/
public String getFromUser() {
return fromUser;
}
/**
* Set message sender ID
*
* @param fromUser
*/
public void setFromUser(String fromUser) {
this.fromUser = fromUser;
}
/**
* Get Group NameCard
*
* @return
*/
public String getGroupNameCard() {
return groupNameCard;
}
/**
* Set Group NameCard
*
* @param groupNameCard
*/
public void setGroupNameCard(String groupNameCard) {
this.groupNameCard = groupNameCard;
}
/**
* Get message type
*
* @return
*/
public int getMsgType() {
return msgType;
}
/**
* Set message type
*
* @param msgType
*/
public void setMsgType(int msgType) {
this.msgType = msgType;
}
/**
* Get Message Status
*
* @return
*/
public int getStatus() {
return status;
}
/**
* Set Message Status
*
* @param status
*/
public void setStatus(int status) {
this.status = status;
}
public int getDownloadStatus() {
return downloadStatus;
}
public void setDownloadStatus(int downloadStatus) {
this.downloadStatus = downloadStatus;
}
/**
* Get whether the message was sent for yourself
*
* @return
*/
public boolean isSelf() {
return self;
}
/**
* Set whether the message was sent for yourself
*
* @param self
*/
public void setSelf(boolean self) {
this.self = self;
}
/**
* Get whether the message is a group message
*
* @return
*/
public boolean isGroup() {
return group;
}
/**
* Set whether the message is a group message
*
* @param group
*/
public void setGroup(boolean group) {
this.group = group;
}
/**
* Set the data source of the multimedia message
*
* @param dataUri
*/
public void setDataUri(Uri dataUri) {
if (dataUri != null) {
this.dataUri = dataUri.toString();
}
}
/**
* Set the save path of multimedia messages
*
* @param dataPath
*/
public void setDataPath(String dataPath) {
this.dataPath = dataPath;
}
public V2TIMMessage getTimMessage() {
return timMessage;
}
public void setTimMessage(V2TIMMessage timMessage) {
this.timMessage = timMessage;
}
/**
* Text description for non-text messages in the conversation list
*
* @return
*/
public Object getExtra() {
return extra;
}
/**
* Set text description for non-text messages in the conversation list
*
* @param extra
*/
public void setExtra(Object extra) {
this.extra = extra;
}
public int getImgWidth() {
return imgWidth;
}
public void setImgWidth(int imgWidth) {
this.imgWidth = imgWidth;
}
public int getImgHeight() {
return imgHeight;
}
public void setImgHeight(int imgHeight) {
this.imgHeight = imgHeight;
}
public long getMsgTime() {
return msgTime;
}
public void setMsgTime(long msgTime) {
this.msgTime = msgTime;
}
public boolean isPeerRead() {
return peerRead;
}
public void setPeerRead(boolean peerRead) {
this.peerRead = peerRead;
}
public void setIgnoreShow(boolean ignoreShow) {
isIgnoreShow = ignoreShow;
}
public boolean getIsIgnoreShow() {
return isIgnoreShow;
}
public String getNameCard() {
return nameCard;
}
public void setNameCard(String nameCard) {
this.nameCard = nameCard;
}
public String getFriendRemark() {
return friendRemark;
}
public void setFriendRemark(String friendRemark) {
this.friendRemark = friendRemark;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getFaceUrl() {
return faceUrl;
}
public void setFaceUrl(String faceUrl) {
this.faceUrl = faceUrl;
}
public String getUserId() {
return userId;
}
public String getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId = groupId;
}
public void setUserId(String userId) {
this.userId = userId;
}
public int getElemType() {
if (timMessage != null) {
return timMessage.getElemType();
} else {
return V2TIMMessage.V2TIM_ELEM_TYPE_NONE;
}
}
public int getMessageInfoElemType() {
return MessageInfoUtil.convertTIMElemType2MessageInfoType(getElemType());
}
public byte[] getCustomElemData() {
if (timMessage != null) {
return timMessage.getCustomElem().getData();
} else {
return new byte[0];
}
}
}
@@ -0,0 +1,166 @@
package com.tencent.qcloud.tuikit.tuisearch.bean;
import com.tencent.imsdk.message.MessageOfflinePushInfo;
import java.io.Serializable;
public class OfflinePushInfo implements Serializable {
public static final String IOS_OFFLINE_PUSH_NO_SOUND = "push.no_sound";
public static final String IOS_OFFLINE_PUSH_DEFAULT_SOUND = "default";
private String title;
private String description;
private byte[] extension;
private String soundFilePath;
private int pushFlag;
private int badgeMode;
private int notifyMode;
private String oppoChannelID;
private int vivoClassification = 1;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public byte[] getExtension() {
return extension;
}
public void setExtension(byte[] extension) {
this.extension = extension;
}
public String getSoundFilePath() {
return soundFilePath;
}
public void setSoundFilePath(String soundFilePath) {
this.soundFilePath = soundFilePath;
}
public int getPushFlag() {
return pushFlag;
}
public void setPushFlag(int pushFlag) {
this.pushFlag = pushFlag;
}
public int getBadgeMode() {
return badgeMode;
}
public void setBadgeMode(int badgeMode) {
this.badgeMode = badgeMode;
}
public int getNotifyMode() {
return notifyMode;
}
public void setNotifyMode(int notifyMode) {
this.notifyMode = notifyMode;
}
public String getOppoChannelID() {
return oppoChannelID;
}
public void setOppoChannelID(String oppoChannelID) {
this.oppoChannelID = oppoChannelID;
}
public int getVivoClassification() {
return vivoClassification;
}
public void setVivoClassification(int vivoClassification) {
this.vivoClassification = vivoClassification;
}
/**
* Whether to disable push (push enabled by default)
*
* @param disable true: disable; false: enable
*/
public void disablePush(boolean disable) {
if (disable) {
setPushFlag(MessageOfflinePushInfo.OFFLINE_PUSH_FLAG_NO_PUSH);
} else {
setPushFlag(MessageOfflinePushInfo.OFFLINE_PUSH_FLAG_DEFAULT);
}
}
/**
*
* Get the offline push disablement status
*
* @return Disabled. true: disabled; false: enabled
*/
public boolean isDisablePush() {
if (getPushFlag() == MessageOfflinePushInfo.OFFLINE_PUSH_FLAG_NO_PUSH) {
return true;
} else {
return false;
}
}
/**
* Offline push sound setting (valid only for iOS)
* When sound is IOS_OFFLINE_PUSH_NO_SOUND, no sound is played when a message is received.
* When sound is IOS_OFFLINE_PUSH_DEFAULT_SOUND, the system alert sound is played when a message is received.
* To customize iOSSound, link the audio file to the Xcode project and set iOSSound to the audio filename (with the extension name).
*
* @param sound iOS Sound path
*/
public void setIOSSound(String sound) {
setSoundFilePath(sound);
}
/**
* Whether to ignore the badge count for offline push (valid only for iOS)
* If this parameter is set to true, the unread message count on the app badge will not increase when the message is received by the iOS device.
*
* @param ignoreIOSBadge iOS Status of the unread message count on the app badge. true: ignore; false: enable
*/
public void setIgnoreIOSBadge(boolean ignoreIOSBadge) {
if (ignoreIOSBadge) {
setBadgeMode(MessageOfflinePushInfo.OFFLINE_APNS_BADGE_MODE_IGNORE);
} else {
setBadgeMode(MessageOfflinePushInfo.OFFLINE_APNS_BADGE_MODE_DEFAULT);
}
}
public boolean isIgnoreIOSBadge() {
return badgeMode == MessageOfflinePushInfo.OFFLINE_APNS_BADGE_MODE_IGNORE;
}
/**
* Offline push channel ID for OPPO phones that run Android 8.0 or later
*
* @param channelID OPPO phone channel ID
*/
public void setAndroidOPPOChannelID(String channelID) {
setOppoChannelID(channelID);
}
/**
* Offline push setting for vivo phones
*
* @param classification Offline push message classification for vivo phones. 0: operation message; 1: system message. The default value is 1.
*/
public void setAndroidVIVOClassification(int classification) {
setVivoClassification(classification);
}
}
@@ -0,0 +1,208 @@
package com.tencent.qcloud.tuikit.tuisearch.bean;
import android.os.Parcel;
import android.os.Parcelable;
import com.tencent.imsdk.v2.V2TIMMessage;
public class SearchDataBean implements Parcelable {
private String title;
private String subTitle;
private String subTitleLabel = "";
private String iconPath;
private int type;
private int isSubTextMatch;
private String userID;
private String nickName;
private String remark;
private String groupID;
private String groupName;
private String groupType;
private boolean isGroup;
private String conversationID;
private V2TIMMessage locateTimMessage;
public SearchDataBean() {}
protected SearchDataBean(Parcel in) {
title = in.readString();
subTitle = in.readString();
iconPath = in.readString();
type = in.readInt();
isSubTextMatch = in.readInt();
userID = in.readString();
nickName = in.readString();
remark = in.readString();
groupID = in.readString();
groupName = in.readString();
groupType = in.readString();
isGroup = in.readByte() != 0;
conversationID = in.readString();
locateTimMessage = (V2TIMMessage) in.readSerializable();
}
public static final Creator<SearchDataBean> CREATOR = new Creator<SearchDataBean>() {
@Override
public SearchDataBean createFromParcel(Parcel in) {
return new SearchDataBean(in);
}
@Override
public SearchDataBean[] newArray(int size) {
return new SearchDataBean[size];
}
};
public String getSubTitle() {
return this.subTitle;
}
public void setSubTitle(String subTitle) {
this.subTitle = subTitle;
}
public void setSubTitleLabel(String subTitleLabel) {
this.subTitleLabel = subTitleLabel;
}
public String getSubTitleLabel() {
return subTitleLabel;
}
public String getIconPath() {
return this.iconPath;
}
public void setIconPath(String iconPath) {
this.iconPath = iconPath;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public void setUserID(String userID) {
this.userID = userID;
}
public String getUserID() {
return userID;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickname) {
this.nickName = nickname;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public boolean isGroup() {
return isGroup;
}
public void setGroup(boolean group) {
isGroup = group;
}
public String getGroupID() {
return groupID;
}
public void setGroupID(String groupID) {
this.groupID = groupID;
}
public String getGroupName() {
return groupName;
}
public void setGroupName(String groupName) {
this.groupName = groupName;
}
public String getGroupType() {
return groupType;
}
public void setGroupType(String groupType) {
this.groupType = groupType;
}
public int getIsSubTextMatch() {
return isSubTextMatch;
}
public void setSubTextMatch(int isSubTextMatch) {
this.isSubTextMatch = isSubTextMatch;
}
public String getConversationID() {
return conversationID;
}
public void setConversationID(String conversationID) {
this.conversationID = conversationID;
}
public V2TIMMessage getLocateTimMessage() {
return locateTimMessage;
}
public void setLocateTimMessage(V2TIMMessage locateTimMessage) {
this.locateTimMessage = locateTimMessage;
}
public long getMessageTime() {
if (locateTimMessage != null) {
return locateTimMessage.getTimestamp();
}
return 0;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(title);
dest.writeString(subTitle);
dest.writeString(iconPath);
dest.writeInt(type);
dest.writeInt(isSubTextMatch);
dest.writeString(userID);
dest.writeString(nickName);
dest.writeString(remark);
dest.writeString(groupID);
dest.writeString(groupName);
dest.writeString(groupType);
dest.writeByte((byte) (isGroup ? 1 : 0));
dest.writeString(conversationID);
dest.writeSerializable(locateTimMessage);
}
}
@@ -0,0 +1,59 @@
package com.tencent.qcloud.tuikit.tuisearch.bean;
import com.tencent.imsdk.v2.V2TIMFriendInfo;
import com.tencent.imsdk.v2.V2TIMFriendInfoResult;
import com.tencent.imsdk.v2.V2TIMMessageSearchResultItem;
import com.tencent.qcloud.tuikit.tuisearch.util.MessageInfoUtil;
import java.util.ArrayList;
import java.util.List;
public class SearchDataBeanUtil {
public static SearchDataBean convertFriendInfo2SearchDataBean(V2TIMFriendInfoResult v2TIMFriendInfoResult) {
if (v2TIMFriendInfoResult == null) {
return null;
}
V2TIMFriendInfo friendInfo = v2TIMFriendInfoResult.getFriendInfo();
SearchDataBean dataBean = new SearchDataBean();
dataBean.setUserID(friendInfo.getUserID());
dataBean.setNickName(friendInfo.getUserProfile().getNickName());
dataBean.setRemark(friendInfo.getFriendRemark());
dataBean.setIconPath(friendInfo.getUserProfile().getFaceUrl());
return dataBean;
}
public static List<SearchDataBean> convertFriendInfos2SearchDataBeans(List<V2TIMFriendInfoResult> v2TIMFriendInfoResults) {
List<SearchDataBean> searchDataBeanList = new ArrayList<>();
for (V2TIMFriendInfoResult v2TIMFriendInfoResult : v2TIMFriendInfoResults) {
SearchDataBean bean = convertFriendInfo2SearchDataBean(v2TIMFriendInfoResult);
if (bean == null) {
continue;
}
searchDataBeanList.add(bean);
}
return searchDataBeanList;
}
public static SearchMessageBean convertSearchResultItem2SearchMessageBean(V2TIMMessageSearchResultItem v2TIMMessageSearchResultItem) {
if (v2TIMMessageSearchResultItem == null) {
return null;
}
SearchMessageBean searchMessageBean = new SearchMessageBean();
searchMessageBean.setConversationId(v2TIMMessageSearchResultItem.getConversationID());
searchMessageBean.setMessageCount(v2TIMMessageSearchResultItem.getMessageCount());
searchMessageBean.setMessageInfoList(MessageInfoUtil.convertTIMMessages2MessageInfos(v2TIMMessageSearchResultItem.getMessageList()));
return searchMessageBean;
}
public static List<SearchMessageBean> convertSearchResultItems2SearchMessageBeans(List<V2TIMMessageSearchResultItem> v2TIMMessageSearchResultItems) {
List<SearchMessageBean> searchMessageBeanList = new ArrayList<>();
for (V2TIMMessageSearchResultItem v2TIMMessageSearchResultItem : v2TIMMessageSearchResultItems) {
SearchMessageBean bean = convertSearchResultItem2SearchMessageBean(v2TIMMessageSearchResultItem);
if (bean == null) {
continue;
}
searchMessageBeanList.add(bean);
}
return searchMessageBeanList;
}
}
@@ -0,0 +1,33 @@
package com.tencent.qcloud.tuikit.tuisearch.bean;
import java.util.List;
public class SearchMessageBean {
private String conversationId;
private int messageCount;
private List<MessageInfo> messageInfoList;
public void setMessageCount(int messageCount) {
this.messageCount = messageCount;
}
public void setMessageInfoList(List<MessageInfo> messageInfoList) {
this.messageInfoList = messageInfoList;
}
public void setConversationId(String conversationId) {
this.conversationId = conversationId;
}
public int getMessageCount() {
return messageCount;
}
public List<MessageInfo> getMessageInfoList() {
return messageInfoList;
}
public String getConversationId() {
return conversationId;
}
}
@@ -0,0 +1,92 @@
package com.tencent.qcloud.tuikit.tuisearch.bean;
import java.util.List;
public class TUISearchGroupParam {
public static final class TUISearchGroupMatchField {
public static final int SEARCH_FIELD_GROUP_ID = 0x01;
public static final int SEARCH_FIELD_GROUP_NAME = 0x01 << 1;
public static final int SEARCH_FIELD_GROUP_NONE = 0x01 << 2;
}
public static final class TUISearchGroupMemberMatchField {
public static final int SEARCH_FIELD_MEMBER_USER_ID = 0x01;
public static final int SEARCH_FIELD_MEMBER_NICK_NAME = 0x01 << 1;
public static final int SEARCH_FIELD_MEMBER_REMARK = 0x01 << 2;
public static final int SEARCH_FIELD_MEMBER_NAME_CARD = 0x01 << 3;
public static final int SEARCH_FIELD_MEMBER_NONE = 0x01 << 4;
}
private boolean isSearchGroupID;
private boolean isSearchGroupName;
private boolean isSearchMemberUserID;
private boolean isSearchMemberNickName;
private boolean isSearchMemberRemark;
private boolean isSearchMemberNameCard;
public boolean isSearchGroupID() {
return isSearchGroupID;
}
public void setSearchGroupID(boolean searchGroupID) {
isSearchGroupID = searchGroupID;
}
public boolean isSearchGroupName() {
return isSearchGroupName;
}
public void setSearchGroupName(boolean searchGroupName) {
isSearchGroupName = searchGroupName;
}
public boolean isSearchMemberUserID() {
return isSearchMemberUserID;
}
public void setSearchMemberUserID(boolean searchMemberUserID) {
isSearchMemberUserID = searchMemberUserID;
}
public boolean isSearchMemberNickName() {
return isSearchMemberNickName;
}
public void setSearchMemberNickName(boolean searchMemberNickName) {
isSearchMemberNickName = searchMemberNickName;
}
public boolean isSearchMemberRemark() {
return isSearchMemberRemark;
}
public void setSearchMemberRemark(boolean searchMemberRemark) {
isSearchMemberRemark = searchMemberRemark;
}
public boolean isSearchMemberNameCard() {
return isSearchMemberNameCard;
}
public void setSearchMemberNameCard(boolean searchMemberNameCard) {
isSearchMemberNameCard = searchMemberNameCard;
}
/**
* Search keyword list, supports up to 5
*/
private List<String> keywordList;
public void setKeywordList(List<String> keywordList) {
this.keywordList = keywordList;
}
public List<String> getKeywordList() {
return keywordList;
}
}
@@ -0,0 +1,89 @@
package com.tencent.qcloud.tuikit.tuisearch.bean;
import java.util.List;
public class TUISearchGroupResult {
/**
* The matched group information, or the group information corresponding to the matched group members
*/
private GroupInfo groupInfo;
/**
* Group match field, see details @TUISearchGroupMatchField
*
* @note
* - If the match hits group information, matchValue is the value corresponding to the group match field. Matching information of group members is not
* searched, and matchMembers is empty.
* - On the contrary, matchField is TUISearchGroupMatchField.SEARCH_FIELD_GROUP_NONE, matchValue is empty, and there is no group matching information;
* further analysis of matchMembers is required to obtain the matched group member information.
*/
private int matchField;
/**
* The value corresponding to the group match field
*
* @note This field is invalid when matchField is SEARCH_FIELD_GROUP_NONE.
*/
private String matchValue;
/**
* Matched group member information
*/
private List<TUISearchGroupMemberMatchResult> matchMembers;
public GroupInfo getGroupInfo() {
return groupInfo;
}
public void setGroupInfo(GroupInfo groupInfo) {
this.groupInfo = groupInfo;
}
public void setMatchField(int matchField) {
this.matchField = matchField;
}
public int getMatchField() {
return matchField;
}
public String getMatchValue() {
return matchValue;
}
public void setMatchValue(String matchValue) {
this.matchValue = matchValue;
}
public List<TUISearchGroupMemberMatchResult> getMatchMembers() {
return matchMembers;
}
public void setMatchMembers(List<TUISearchGroupMemberMatchResult> matchMembers) {
this.matchMembers = matchMembers;
}
public static final class TUISearchGroupMemberMatchResult {
/**
* Group member matching field, see details @TUISearchGroupMemberMatchField
*/
private int memberMatchField;
/**
* The value corresponding to the group member match field
*/
private String memberMatchValue;
public void setMemberMatchField(int memberMatchField) {
this.memberMatchField = memberMatchField;
}
public int getMemberMatchField() {
return memberMatchField;
}
public String getMemberMatchValue() {
return memberMatchValue;
}
public void setMemberMatchValue(String memberMatchValue) {
this.memberMatchValue = memberMatchValue;
}
}
}
@@ -0,0 +1,65 @@
package com.tencent.qcloud.tuikit.tuisearch.classicui;
import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.auto.service.AutoService;
import com.tencent.qcloud.tuicore.ServiceInitializer;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuicore.annotations.TUIInitializerDependency;
import com.tencent.qcloud.tuicore.annotations.TUIInitializerID;
import com.tencent.qcloud.tuicore.interfaces.ITUIExtension;
import com.tencent.qcloud.tuicore.interfaces.TUIExtensionInfo;
import com.tencent.qcloud.tuicore.interfaces.TUIInitializer;
import com.tencent.qcloud.tuikit.tuisearch.R;
import java.util.List;
import java.util.Map;
@AutoService(TUIInitializer.class)
@TUIInitializerDependency({"TIMCommon"})
@TUIInitializerID("TUISearchClassicUIExtensionObserver")
public class ClassicUIExtensionObserver implements TUIInitializer, ITUIExtension {
@Override
public void init(Context context) {
TUICore.registerExtension(TUIConstants.TUIConversation.Extension.ConversationListHeader.CLASSIC_EXTENSION_ID, this);
}
@Override
public boolean onRaiseExtension(String extensionID, View parentView, Map<String, Object> param) {
if (TextUtils.equals(extensionID, TUIConstants.TUIConversation.Extension.ConversationListHeader.CLASSIC_EXTENSION_ID)) {
ViewGroup viewGroup = null;
if (parentView instanceof ViewGroup) {
viewGroup = (ViewGroup) parentView;
}
if (viewGroup == null) {
return false;
}
View searchView = LayoutInflater.from(getAppContext()).inflate(R.layout.search_bar_layout, null);
viewGroup.setVisibility(View.VISIBLE);
viewGroup.removeAllViews();
searchView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TUICore.startActivity("SearchMainActivity", null);
}
});
viewGroup.addView(searchView);
return true;
}
return false;
}
@Override
public List<TUIExtensionInfo> onGetExtension(String extensionID, Map<String, Object> param) {
return null;
}
public static Context getAppContext() {
return ServiceInitializer.getAppContext();
}
}
@@ -0,0 +1,486 @@
package com.tencent.qcloud.tuikit.tuisearch.classicui.page;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.text.Editable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUIThemeManager;
import com.tencent.qcloud.tuikit.timcommon.component.activities.BaseLightActivity;
import com.tencent.qcloud.tuikit.timcommon.component.dialog.TUIKitDialog;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuisearch.R;
import com.tencent.qcloud.tuikit.tuisearch.TUISearchConstants;
import com.tencent.qcloud.tuikit.tuisearch.bean.ChatInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import com.tencent.qcloud.tuikit.tuisearch.classicui.util.ClassicSearchUtils;
import com.tencent.qcloud.tuikit.tuisearch.classicui.widget.PageRecycleView;
import com.tencent.qcloud.tuikit.tuisearch.classicui.widget.SearchResultAdapter;
import com.tencent.qcloud.tuikit.tuisearch.presenter.SearchMainPresenter;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchLog;
import java.util.ArrayList;
import java.util.List;
public class SearchMainActivity extends BaseLightActivity {
private static final String TAG = SearchMainActivity.class.getSimpleName();
private EditText mEdtSearch;
private ImageView mImgvDelete;
private TextView mCancleView;
private RecyclerView mFriendRcSearch;
private RecyclerView mGroupRcSearch;
private PageRecycleView mConversationRcSearch;
private SearchResultAdapter mContactRcSearchAdapter;
private SearchResultAdapter mGroupRcSearchAdapter;
private SearchResultAdapter mConversationRcSearchAdapter;
private RelativeLayout mContactLayout;
private RelativeLayout mGroupLayout;
private RelativeLayout mConversationLayout;
private RelativeLayout mMoreContactLayout;
private RelativeLayout mMoreGroupLayout;
private RelativeLayout mMoreConversationLayout;
private List<SearchDataBean> mContactSearchData = new ArrayList<>();
private List<SearchDataBean> mGroupSearchData = new ArrayList<>();
private List<SearchDataBean> mConversationData = new ArrayList<>();
private SearchMainPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_main_activity);
init();
}
private void init() {
initView();
if (mContactRcSearchAdapter == null) {
mContactRcSearchAdapter = new SearchResultAdapter(this);
mFriendRcSearch.setAdapter(mContactRcSearchAdapter);
}
if (mGroupRcSearchAdapter == null) {
mGroupRcSearchAdapter = new SearchResultAdapter(this);
mGroupRcSearch.setAdapter(mGroupRcSearchAdapter);
}
if (mConversationRcSearchAdapter == null) {
mConversationRcSearchAdapter = new SearchResultAdapter(this);
mConversationRcSearch.setAdapter(mConversationRcSearchAdapter);
}
initPresenter();
setListener();
}
public void initPresenter() {
presenter = new SearchMainPresenter();
presenter.setGroupAdapter(mGroupRcSearchAdapter);
presenter.setContactAdapter(mContactRcSearchAdapter);
presenter.setConversationAdapter(mConversationRcSearchAdapter);
}
private void setListener() {
mEdtSearch.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void afterTextChanged(Editable editable) {
if (editable.length() == 0) {
mImgvDelete.setVisibility(View.GONE);
} else {
mImgvDelete.setVisibility(View.VISIBLE);
}
initData(editable.toString().trim());
doChangeColor(editable.toString().trim());
}
});
if (mContactRcSearchAdapter != null) {
mContactRcSearchAdapter.setOnItemClickListener(new SearchResultAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int pos) {
if (mContactSearchData != null && pos < mContactSearchData.size()) {
ChatInfo chatInfo = new ChatInfo();
chatInfo.setType(ChatInfo.TYPE_C2C);
SearchDataBean searchDataBean = mContactSearchData.get(pos);
chatInfo.setId(searchDataBean.getUserID());
String chatName = searchDataBean.getUserID();
if (!TextUtils.isEmpty(searchDataBean.getRemark())) {
chatName = searchDataBean.getRemark();
} else if (!TextUtils.isEmpty(searchDataBean.getNickName())) {
chatName = searchDataBean.getNickName();
}
chatInfo.setChatName(chatName);
ClassicSearchUtils.startChatActivity(chatInfo);
}
}
});
}
if (mGroupRcSearchAdapter != null) {
mGroupRcSearchAdapter.setOnItemClickListener(new SearchResultAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int pos) {
if (mGroupSearchData != null && pos < mGroupSearchData.size()) {
SearchDataBean searchDataBean = mGroupSearchData.get(pos);
ChatInfo chatInfo = new ChatInfo();
chatInfo.setType(ChatInfo.TYPE_GROUP);
chatInfo.setGroupType(searchDataBean.getGroupType());
String chatName = searchDataBean.getUserID();
if (!TextUtils.isEmpty(searchDataBean.getRemark())) {
chatName = searchDataBean.getRemark();
} else if (!TextUtils.isEmpty(searchDataBean.getNickName())) {
chatName = searchDataBean.getNickName();
}
chatInfo.setChatName(chatName);
chatInfo.setId(searchDataBean.getGroupID());
ClassicSearchUtils.startChatActivity(chatInfo);
}
}
});
}
if (mConversationRcSearchAdapter != null) {
mConversationRcSearchAdapter.setOnItemClickListener(new SearchResultAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int pos) {
if (mConversationRcSearchAdapter == null) {
return;
}
List<SearchDataBean> searchDataBeans = mConversationRcSearchAdapter.getDataSource();
if (searchDataBeans != null && pos < searchDataBeans.size()) {
SearchDataBean searchDataBean = searchDataBeans.get(pos);
Intent intent = new Intent(getApplicationContext(), SearchMoreMsgListActivity.class);
intent.putExtra(TUISearchConstants.SEARCH_KEY_WORDS, mEdtSearch.getText().toString().trim());
intent.putExtra(TUISearchConstants.SEARCH_DATA_BEAN, searchDataBean);
startActivity(intent);
}
}
});
}
mImgvDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mEdtSearch.setText("");
mContactLayout.setVisibility(View.GONE);
mGroupLayout.setVisibility(View.GONE);
mConversationLayout.setVisibility(View.GONE);
}
});
mCancleView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onBackPressed();
}
});
mMoreContactLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mContactRcSearchAdapter == null) {
return;
}
List<SearchDataBean> searchDataBeans = mContactRcSearchAdapter.getDataSource();
if (searchDataBeans == null || searchDataBeans.size() < 4) {
return;
}
Intent intent = new Intent(getApplicationContext(), SearchMoreListActivity.class);
intent.putExtra(TUISearchConstants.SEARCH_LIST_TYPE, TUISearchConstants.CONTACT_TYPE);
intent.putExtra(TUISearchConstants.SEARCH_KEY_WORDS, mEdtSearch.getText().toString().trim());
startActivity(intent);
}
});
mMoreGroupLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mGroupRcSearchAdapter == null) {
return;
}
List<SearchDataBean> searchDataBeans = mGroupRcSearchAdapter.getDataSource();
if (searchDataBeans == null || searchDataBeans.size() < 4) {
return;
}
Intent intent = new Intent(getApplicationContext(), SearchMoreListActivity.class);
intent.putExtra(TUISearchConstants.SEARCH_LIST_TYPE, TUISearchConstants.GROUP_TYPE);
intent.putExtra(TUISearchConstants.SEARCH_KEY_WORDS, mEdtSearch.getText().toString().trim());
startActivity(intent);
}
});
mMoreConversationLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mConversationRcSearchAdapter == null) {
return;
}
List<SearchDataBean> searchDataBeans = mConversationRcSearchAdapter.getDataSource();
if (searchDataBeans == null || searchDataBeans.size() < 4) {
return;
}
Intent intent = new Intent(getApplicationContext(), SearchMoreListActivity.class);
intent.putExtra(TUISearchConstants.SEARCH_LIST_TYPE, TUISearchConstants.CONVERSATION_TYPE);
intent.putExtra(TUISearchConstants.SEARCH_KEY_WORDS, mEdtSearch.getText().toString().trim());
startActivity(intent);
}
});
}
private void doChangeColor(String text) {
if (text.equals("")) {
mContactRcSearchAdapter.setText(null);
mGroupRcSearchAdapter.setText(null);
mConversationRcSearchAdapter.setText(null);
} else {
mContactRcSearchAdapter.setText(text);
mGroupRcSearchAdapter.setText(text);
mConversationRcSearchAdapter.setText(text);
}
}
private void initData(final String keyWords) {
if (keyWords == null || TextUtils.isEmpty(keyWords)) {
mContactLayout.setVisibility(View.GONE);
mGroupLayout.setVisibility(View.GONE);
mConversationLayout.setVisibility(View.GONE);
return;
}
final List<String> keywordList = new ArrayList<String>() {
{ add(keyWords); }
};
presenter.searchContact(keywordList, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> searchDataBeans) {
mContactSearchData = searchDataBeans;
if (searchDataBeans.isEmpty()) {
mContactLayout.setVisibility(View.GONE);
mMoreContactLayout.setVisibility(View.GONE);
} else {
mContactLayout.setVisibility(View.VISIBLE);
if (searchDataBeans.size() > 3) {
mMoreContactLayout.setVisibility(View.VISIBLE);
} else {
mMoreContactLayout.setVisibility(View.GONE);
}
}
mContactRcSearchAdapter.onIsShowAllChanged(false);
}
@Override
public void onError(String module, int code, String desc) {
if (code == TUIConstants.BuyingFeature.ERR_SDK_INTERFACE_NOT_SUPPORT) {
showNotSupportDialog();
}
TUISearchLog.d(TAG, "SearchContact onError code = " + code + ", desc = " + desc);
}
});
presenter.searchGroup(keywordList, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> searchDataBeans) {
mGroupSearchData = searchDataBeans;
if (searchDataBeans.size() > 0) {
mGroupLayout.setVisibility(View.VISIBLE);
if (searchDataBeans.size() > 3) {
mMoreGroupLayout.setVisibility(View.VISIBLE);
} else {
mMoreGroupLayout.setVisibility(View.GONE);
}
} else {
mGroupLayout.setVisibility(View.GONE);
mMoreGroupLayout.setVisibility(View.GONE);
}
mGroupRcSearchAdapter.onIsShowAllChanged(false);
}
@Override
public void onError(String module, int code, String desc) {
if (code == TUIConstants.BuyingFeature.ERR_SDK_INTERFACE_NOT_SUPPORT) {
showNotSupportDialog();
}
TUISearchLog.d(TAG, "SearchContact onError code = " + code + ", desc = " + desc);
}
});
presenter.searchConversation(keywordList, 0, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> data) {
if (data.size() > 0) {
mConversationLayout.setVisibility(View.VISIBLE);
if (data.size() > 3) {
mMoreConversationLayout.setVisibility(View.VISIBLE);
} else {
mMoreConversationLayout.setVisibility(View.GONE);
}
} else {
mConversationLayout.setVisibility(View.GONE);
mMoreConversationLayout.setVisibility(View.GONE);
}
mConversationRcSearchAdapter.onIsShowAllChanged(false);
}
@Override
public void onError(String module, int errCode, String errMsg) {
if (errCode == TUIConstants.BuyingFeature.ERR_SDK_INTERFACE_NOT_SUPPORT) {
showNotSupportDialog();
}
mConversationLayout.setVisibility(View.GONE);
mMoreConversationLayout.setVisibility(View.GONE);
}
});
}
private void showNotSupportDialog() {
String string = getResources().getString(R.string.search_im_flagship_edition_update_tip, getString(R.string.search));
String buyingGuidelines = getResources().getString(R.string.search_buying_guidelines);
int buyingGuidelinesIndex = string.lastIndexOf(buyingGuidelines);
final int foregroundColor =
getResources().getColor(TUIThemeManager.getAttrResId(SearchMainActivity.this, com.tencent.qcloud.tuicore.R.attr.core_primary_color));
SpannableString spannedString = new SpannableString(string);
ForegroundColorSpan colorSpan2 = new ForegroundColorSpan(foregroundColor);
spannedString.setSpan(colorSpan2, buyingGuidelinesIndex, buyingGuidelinesIndex + buyingGuidelines.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
ClickableSpan clickableSpan2 = new ClickableSpan() {
@Override
public void onClick(View view) {
if (TextUtils.equals(TUIThemeManager.getInstance().getCurrentLanguage(), "zh")) {
openWebUrl(TUIConstants.BuyingFeature.BUYING_PRICE_DESC);
} else {
openWebUrl(TUIConstants.BuyingFeature.BUYING_PRICE_DESC_EN);
}
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setUnderlineText(false);
}
};
spannedString.setSpan(clickableSpan2, buyingGuidelinesIndex, buyingGuidelinesIndex + buyingGuidelines.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
TUIKitDialog.TUIIMUpdateDialog.getInstance()
.createDialog(this)
.setShowOnlyDebug(true)
.setMovementMethod(LinkMovementMethod.getInstance())
.setHighlightColor(Color.TRANSPARENT)
.setCancelable(true)
.setCancelOutside(true)
.setTitle(spannedString)
.setDialogWidth(0.75f)
.setDialogFeatureName(TUIConstants.BuyingFeature.BUYING_FEATURE_SEARCH)
.setPositiveButton(getString(R.string.search_no_more_reminders),
new View.OnClickListener() {
@Override
public void onClick(View v) {
TUIKitDialog.TUIIMUpdateDialog.getInstance().dismiss();
TUIKitDialog.TUIIMUpdateDialog.getInstance().setNeverShow(true);
}
})
.setNegativeButton(getString(R.string.search_i_know),
new View.OnClickListener() {
@Override
public void onClick(View v) {
TUIKitDialog.TUIIMUpdateDialog.getInstance().dismiss();
}
})
.show();
}
private void openWebUrl(String url) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri contentUrl = Uri.parse(url);
intent.setData(contentUrl);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
private void initView() {
mEdtSearch = findViewById(R.id.edt_search);
mImgvDelete = findViewById(R.id.imgv_delete);
mFriendRcSearch = findViewById(R.id.friend_rc_search);
mGroupRcSearch = findViewById(R.id.group_rc_search);
mConversationRcSearch = findViewById(R.id.conversation_rc_search);
mCancleView = findViewById(R.id.cancel_button);
mFriendRcSearch.setLayoutManager(new LinearLayoutManager(this));
mGroupRcSearch.setLayoutManager(new LinearLayoutManager(this));
mConversationRcSearch.setLayoutManager(new LinearLayoutManager(this));
mFriendRcSearch.setNestedScrollingEnabled(false);
mGroupRcSearch.setNestedScrollingEnabled(false);
mConversationRcSearch.setNestedScrollingEnabled(false);
mContactLayout = findViewById(R.id.contact_layout);
mMoreContactLayout = findViewById(R.id.more_contact_layout);
mGroupLayout = findViewById(R.id.group_layout);
mMoreGroupLayout = findViewById(R.id.more_group_layout);
mConversationLayout = findViewById(R.id.conversation_layout);
mMoreConversationLayout = findViewById(R.id.more_conversation_layout);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
View v = getCurrentFocus();
if (isShouldHideInput(v, ev)) {
hideSoftInput(v.getWindowToken());
}
}
return super.dispatchTouchEvent(ev);
}
private boolean isShouldHideInput(View v, MotionEvent event) {
if (v != null && (v instanceof EditText)) {
int[] l = {0, 0};
v.getLocationInWindow(l);
int left = l[0];
int top = l[1];
int bottom = top + v.getHeight();
int right = left + v.getWidth();
if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) {
return false;
} else {
return true;
}
}
return false;
}
private void hideSoftInput(IBinder token) {
if (token != null) {
InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS);
}
}
}
@@ -0,0 +1,404 @@
package com.tencent.qcloud.tuikit.tuisearch.classicui.page;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.tencent.qcloud.tuikit.timcommon.component.activities.BaseLightActivity;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuisearch.R;
import com.tencent.qcloud.tuikit.tuisearch.TUISearchConstants;
import com.tencent.qcloud.tuikit.tuisearch.bean.ChatInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import com.tencent.qcloud.tuikit.tuisearch.classicui.util.ClassicSearchUtils;
import com.tencent.qcloud.tuikit.tuisearch.classicui.widget.PageRecycleView;
import com.tencent.qcloud.tuikit.tuisearch.classicui.widget.SearchResultAdapter;
import com.tencent.qcloud.tuikit.tuisearch.model.SearchDataProvider;
import com.tencent.qcloud.tuikit.tuisearch.presenter.SearchMainPresenter;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchLog;
import java.util.ArrayList;
import java.util.List;
public class SearchMoreListActivity extends BaseLightActivity {
private static final String TAG = SearchMoreListActivity.class.getSimpleName();
private EditText mEdtSearch;
private ImageView mImgvDelete;
private TextView mCancleView;
private RecyclerView mFriendRcSearch;
private RecyclerView mGroupRcSearch;
private PageRecycleView mConversationRcSearch;
private SearchResultAdapter mContactRcSearchAdapter;
private SearchResultAdapter mGroupRcSearchAdapter;
private SearchResultAdapter mConversationRcSearchAdapter;
private RelativeLayout mContactLayout;
private RelativeLayout mGroupLayout;
private RelativeLayout mConversationLayout;
private RelativeLayout mMoreContactLayout;
private RelativeLayout mMoreGroupLayout;
private RelativeLayout mMoreConversationLayout;
private int mViewType = -1;
private String mKeyWords;
private int pageIndex = 0;
private SearchMainPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_main_activity);
init();
}
private void init() {
initView();
if (mContactRcSearchAdapter == null) {
mContactRcSearchAdapter = new SearchResultAdapter(this);
mFriendRcSearch.setAdapter(mContactRcSearchAdapter);
}
if (mGroupRcSearchAdapter == null) {
mGroupRcSearchAdapter = new SearchResultAdapter(this);
mGroupRcSearch.setAdapter(mGroupRcSearchAdapter);
}
if (mConversationRcSearchAdapter == null) {
mConversationRcSearchAdapter = new SearchResultAdapter(this);
mConversationRcSearch.setAdapter(mConversationRcSearchAdapter);
}
initPresenter();
Intent intent = getIntent();
if (intent != null) {
mViewType = intent.getIntExtra(TUISearchConstants.SEARCH_LIST_TYPE, -1);
mKeyWords = intent.getStringExtra(TUISearchConstants.SEARCH_KEY_WORDS);
pageIndex = 0;
// also ok
initData(mKeyWords);
mEdtSearch.setText(mKeyWords);
doChangeColor(mKeyWords);
}
setListener();
}
private void initPresenter() {
presenter = new SearchMainPresenter();
presenter.setContactAdapter(mContactRcSearchAdapter);
presenter.setConversationAdapter(mConversationRcSearchAdapter);
presenter.setGroupAdapter(mGroupRcSearchAdapter);
}
private void setListener() {
mEdtSearch.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void afterTextChanged(Editable editable) {
if (editable.length() == 0) {
mImgvDelete.setVisibility(View.GONE);
} else {
mImgvDelete.setVisibility(View.VISIBLE);
}
mKeyWords = editable.toString().trim();
pageIndex = 0;
mConversationRcSearch.setNestedScrollingEnabled(true);
initData(mKeyWords);
doChangeColor(mKeyWords);
}
});
mCancleView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onBackPressed();
}
});
if (mContactRcSearchAdapter != null) {
mContactRcSearchAdapter.setOnItemClickListener(new SearchResultAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int pos) {
List<SearchDataBean> searchDataBeans = mContactRcSearchAdapter.getDataSource();
if (searchDataBeans != null && pos < searchDataBeans.size()) {
SearchDataBean searchDataBean = searchDataBeans.get(pos);
ChatInfo chatInfo = new ChatInfo();
chatInfo.setType(ChatInfo.TYPE_C2C);
chatInfo.setId(searchDataBean.getUserID());
String chatName = searchDataBean.getUserID();
if (!TextUtils.isEmpty(searchDataBean.getRemark())) {
chatName = searchDataBean.getRemark();
} else if (!TextUtils.isEmpty(searchDataBean.getNickName())) {
chatName = searchDataBean.getNickName();
}
chatInfo.setChatName(chatName);
ClassicSearchUtils.startChatActivity(chatInfo);
}
}
});
}
if (mGroupRcSearchAdapter != null) {
mGroupRcSearchAdapter.setOnItemClickListener(new SearchResultAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int pos) {
List<SearchDataBean> searchDataBeans = mGroupRcSearchAdapter.getDataSource();
if (searchDataBeans != null && pos < searchDataBeans.size()) {
SearchDataBean searchDataBean = searchDataBeans.get(pos);
ChatInfo chatInfo = new ChatInfo();
chatInfo.setType(ChatInfo.TYPE_GROUP);
chatInfo.setGroupType(searchDataBean.getGroupType());
String chatName = searchDataBean.getUserID();
if (!TextUtils.isEmpty(searchDataBean.getRemark())) {
chatName = searchDataBean.getRemark();
} else if (!TextUtils.isEmpty(searchDataBean.getNickName())) {
chatName = searchDataBean.getNickName();
}
chatInfo.setChatName(chatName);
chatInfo.setId(searchDataBean.getGroupID());
ClassicSearchUtils.startChatActivity(chatInfo);
}
}
});
}
if (mConversationRcSearchAdapter != null) {
mConversationRcSearchAdapter.setOnItemClickListener(new SearchResultAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int pos) {
if (mConversationRcSearchAdapter == null) {
return;
}
List<SearchDataBean> searchDataBeans = mConversationRcSearchAdapter.getDataSource();
if (searchDataBeans != null && pos < searchDataBeans.size()) {
SearchDataBean searchDataBean = searchDataBeans.get(pos);
Intent intent = new Intent(getApplicationContext(), SearchMoreMsgListActivity.class);
intent.putExtra(TUISearchConstants.SEARCH_KEY_WORDS, mEdtSearch.getText().toString().trim());
intent.putExtra(TUISearchConstants.SEARCH_DATA_BEAN, searchDataBean);
startActivity(intent);
}
}
});
mConversationRcSearch.setLoadMoreMessageHandler(new PageRecycleView.OnLoadMoreHandler() {
@Override
public void loadMore() {
final List<String> keywordList = new ArrayList<String>() {
{ add(mKeyWords); }
};
presenter.searchConversation(keywordList, ++pageIndex, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> data) {
if (data.size() > 0) {
mConversationLayout.setVisibility(View.VISIBLE);
} else {
mConversationLayout.setVisibility(View.GONE);
mMoreConversationLayout.setVisibility(View.GONE);
}
mConversationRcSearchAdapter.onIsShowAllChanged(true);
}
@Override
public void onError(String module, int errCode, String errMsg) {
mConversationLayout.setVisibility(View.GONE);
mMoreConversationLayout.setVisibility(View.GONE);
}
});
}
@Override
public boolean isListEnd(int postion) {
mConversationRcSearch.setNestedScrollingEnabled(false);
if (mConversationRcSearchAdapter == null || mConversationRcSearchAdapter.getTotalCount() == 0) {
return true;
}
int totalCount = mConversationRcSearchAdapter.getTotalCount();
int totalPage = (totalCount % SearchDataProvider.CONVERSATION_MESSAGE_PAGE_SIZE == 0)
? (totalCount / SearchDataProvider.CONVERSATION_MESSAGE_PAGE_SIZE)
: (totalCount / SearchDataProvider.CONVERSATION_MESSAGE_PAGE_SIZE + 1);
if (pageIndex + 1 < totalPage) {
return false;
}
return true;
}
});
}
mImgvDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mEdtSearch.setText("");
mContactLayout.setVisibility(View.GONE);
mGroupLayout.setVisibility(View.GONE);
mConversationLayout.setVisibility(View.GONE);
}
});
}
private void doChangeColor(String text) {
if (text.equals("")) {
mContactRcSearchAdapter.setText(null);
mGroupRcSearchAdapter.setText(null);
mConversationRcSearchAdapter.setText(null);
} else {
mContactRcSearchAdapter.setText(text);
mGroupRcSearchAdapter.setText(text);
mConversationRcSearchAdapter.setText(text);
}
}
private void initData(final String keyWords) {
if (keyWords == null || TextUtils.isEmpty(keyWords)) {
mContactLayout.setVisibility(View.GONE);
mGroupLayout.setVisibility(View.GONE);
mConversationLayout.setVisibility(View.GONE);
return;
}
final List<String> keywordList = new ArrayList<String>() {
{ add(keyWords); }
};
if (mViewType == TUISearchConstants.CONTACT_TYPE) {
presenter.searchContact(keywordList, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> searchDataBeans) {
if (searchDataBeans.isEmpty()) {
mContactLayout.setVisibility(View.GONE);
} else {
mContactLayout.setVisibility(View.VISIBLE);
}
mContactRcSearchAdapter.onIsShowAllChanged(true);
}
@Override
public void onError(String module, int code, String desc) {
TUISearchLog.d(TAG, "SearchContact onError code = " + code + ", desc = " + desc);
}
});
} else if (mViewType == TUISearchConstants.GROUP_TYPE) {
presenter.searchGroup(keywordList, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> searchDataBeans) {
if (searchDataBeans.size() > 0) {
mGroupLayout.setVisibility(View.VISIBLE);
} else {
mGroupLayout.setVisibility(View.GONE);
}
mGroupRcSearchAdapter.onIsShowAllChanged(true);
}
@Override
public void onError(String module, int code, String desc) {
TUISearchLog.d(TAG, "SearchContact onError code = " + code + ", desc = " + desc);
}
});
} else if (mViewType == TUISearchConstants.CONVERSATION_TYPE) {
presenter.searchConversation(keywordList, 0, new IUIKitCallback<List<SearchDataBean>>() {
public void onSuccess(List<SearchDataBean> data) {
if (data.size() > 0) {
mConversationLayout.setVisibility(View.VISIBLE);
} else {
mConversationLayout.setVisibility(View.GONE);
mMoreConversationLayout.setVisibility(View.GONE);
}
mConversationRcSearchAdapter.onIsShowAllChanged(true);
}
@Override
public void onError(String module, int errCode, String errMsg) {
mConversationLayout.setVisibility(View.GONE);
mMoreConversationLayout.setVisibility(View.GONE);
}
});
} else {
TUISearchLog.e(TAG, "mViewType is invalid :" + mViewType);
}
}
private void initView() {
mEdtSearch = findViewById(R.id.edt_search);
mImgvDelete = findViewById(R.id.imgv_delete);
mFriendRcSearch = findViewById(R.id.friend_rc_search);
mGroupRcSearch = findViewById(R.id.group_rc_search);
mConversationRcSearch = findViewById(R.id.conversation_rc_search);
mCancleView = findViewById(R.id.cancel_button);
mFriendRcSearch.setLayoutManager(new LinearLayoutManager(this));
mGroupRcSearch.setLayoutManager(new LinearLayoutManager(this));
mConversationRcSearch.setLayoutManager(new LinearLayoutManager(this));
mFriendRcSearch.setNestedScrollingEnabled(false);
mGroupRcSearch.setNestedScrollingEnabled(false);
mConversationRcSearch.setNestedScrollingEnabled(true);
mContactLayout = findViewById(R.id.contact_layout);
mMoreContactLayout = findViewById(R.id.more_contact_layout);
mGroupLayout = findViewById(R.id.group_layout);
mMoreGroupLayout = findViewById(R.id.more_group_layout);
mConversationLayout = findViewById(R.id.conversation_layout);
mMoreConversationLayout = findViewById(R.id.more_conversation_layout);
mMoreContactLayout.setVisibility(View.GONE);
mMoreConversationLayout.setVisibility(View.GONE);
mMoreGroupLayout.setVisibility(View.GONE);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
View v = getCurrentFocus();
if (isShouldHideInput(v, ev)) {
hideSoftInput(v.getWindowToken());
}
}
return super.dispatchTouchEvent(ev);
}
private boolean isShouldHideInput(View v, MotionEvent event) {
if (v != null && (v instanceof EditText)) {
int[] l = {0, 0};
v.getLocationInWindow(l);
int left = l[0];
int top = l[1];
int bottom = top + v.getHeight();
int right = left + v.getWidth();
if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) {
return false;
} else {
return true;
}
}
return false;
}
private void hideSoftInput(IBinder token) {
if (token != null) {
InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS);
}
}
}
@@ -0,0 +1,304 @@
package com.tencent.qcloud.tuikit.tuisearch.classicui.page;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.tencent.qcloud.tuikit.timcommon.component.activities.BaseLightActivity;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuisearch.R;
import com.tencent.qcloud.tuikit.tuisearch.TUISearchConstants;
import com.tencent.qcloud.tuikit.tuisearch.bean.ChatInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import com.tencent.qcloud.tuikit.tuisearch.classicui.util.ClassicSearchUtils;
import com.tencent.qcloud.tuikit.tuisearch.classicui.widget.PageRecycleView;
import com.tencent.qcloud.tuikit.tuisearch.classicui.widget.SearchMoreMsgAdapter;
import com.tencent.qcloud.tuikit.tuisearch.model.SearchDataProvider;
import com.tencent.qcloud.tuikit.tuisearch.presenter.SearchMoreMsgPresenter;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchLog;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchUtils;
import java.util.ArrayList;
import java.util.List;
public class SearchMoreMsgListActivity extends BaseLightActivity {
private static final String TAG = SearchMoreMsgListActivity.class.getSimpleName();
private EditText mEdtSearch;
private ImageView mImgvDelete;
private TextView mCancleView;
private PageRecycleView mMessageRcSearch;
private SearchMoreMsgAdapter mMessageRcSearchAdapter;
private RelativeLayout mMessageLayout;
private String mKeyWords;
private String mConversationId;
private boolean mIsGroup;
private SearchDataBean mSearchDataBean;
private int pageIndex = 0;
private SearchMoreMsgPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search_more_msg_activity);
init();
}
private void init() {
initView();
if (mMessageRcSearchAdapter == null) {
mMessageRcSearchAdapter = new SearchMoreMsgAdapter(this);
mMessageRcSearch.setAdapter(mMessageRcSearchAdapter);
}
initPresenter();
Intent intent = getIntent();
if (intent != null) {
mKeyWords = intent.getStringExtra(TUISearchConstants.SEARCH_KEY_WORDS);
mSearchDataBean = intent.getParcelableExtra(TUISearchConstants.SEARCH_DATA_BEAN);
pageIndex = 0;
mMessageRcSearchAdapter.setSearchDataBean(mSearchDataBean);
if (mSearchDataBean != null) {
mIsGroup = mSearchDataBean.isGroup();
if (mIsGroup) {
mConversationId = TUISearchUtils.getConversationIdByUserId(mSearchDataBean.getGroupID(), true);
} else {
mConversationId = TUISearchUtils.getConversationIdByUserId(mSearchDataBean.getUserID(), false);
}
}
initData(mKeyWords);
mEdtSearch.setText(mKeyWords);
doChangeColor(mKeyWords);
}
setListener();
}
private void initPresenter() {
presenter = new SearchMoreMsgPresenter();
presenter.setAdapter(mMessageRcSearchAdapter);
}
private void setListener() {
mEdtSearch.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void afterTextChanged(Editable editable) {
if (editable.length() == 0) {
mImgvDelete.setVisibility(View.GONE);
} else {
mImgvDelete.setVisibility(View.VISIBLE);
}
mKeyWords = editable.toString().trim();
pageIndex = 0;
mMessageRcSearch.setNestedScrollingEnabled(true);
initData(mKeyWords);
doChangeColor(mKeyWords);
}
});
mCancleView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onBackPressed();
}
});
if (mMessageRcSearchAdapter != null) {
mMessageRcSearchAdapter.setOnItemClickListener(new SearchMoreMsgAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int pos) {
if (mSearchDataBean == null) {
TUISearchLog.e(TAG, "mSearchDataBean == null");
return;
}
List<SearchDataBean> searchDataBeans = mMessageRcSearchAdapter.getDataSource();
if (searchDataBeans != null && pos < searchDataBeans.size()) {
SearchDataBean searchDataBean = searchDataBeans.get(pos);
ChatInfo chatInfo = presenter.generateChatInfo(searchDataBean);
ClassicSearchUtils.startChatActivity(chatInfo);
}
}
});
}
mMessageRcSearchAdapter.setOnConversationClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mSearchDataBean == null) {
TUISearchLog.e(TAG, "mSearchDataBean == null");
return;
}
ChatInfo chatInfo = new ChatInfo();
if (mSearchDataBean.isGroup()) {
chatInfo.setType(ChatInfo.TYPE_GROUP);
chatInfo.setId(mSearchDataBean.getGroupID());
chatInfo.setGroupType(mSearchDataBean.getGroupType());
} else {
chatInfo.setType(ChatInfo.TYPE_C2C);
chatInfo.setId(mSearchDataBean.getUserID());
}
ClassicSearchUtils.startChatActivity(chatInfo);
}
});
mMessageRcSearch.setLoadMoreMessageHandler(new PageRecycleView.OnLoadMoreHandler() {
@Override
public void loadMore() {
final List<String> keywordList = new ArrayList<String>() {
{ add(mKeyWords); }
};
presenter.searchMessage(keywordList, mConversationId, ++pageIndex, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> data) {
if (data.isEmpty() && pageIndex == 0) {
mMessageRcSearchAdapter.setConversationVisible(false);
mMessageLayout.setVisibility(View.GONE);
} else {
mMessageRcSearchAdapter.setConversationVisible(true);
mMessageLayout.setVisibility(View.VISIBLE);
}
}
@Override
public void onError(String module, int errCode, String errMsg) {
mMessageRcSearchAdapter.setConversationVisible(false);
mMessageLayout.setVisibility(View.GONE);
}
});
}
@Override
public boolean isListEnd(int position) {
if (mMessageRcSearchAdapter == null || mMessageRcSearchAdapter.getTotalCount() == 0) {
return true;
}
int totalCount = mMessageRcSearchAdapter.getTotalCount();
int totalPage = (totalCount % SearchDataProvider.CONVERSATION_MESSAGE_PAGE_SIZE == 0)
? (totalCount / SearchDataProvider.CONVERSATION_MESSAGE_PAGE_SIZE)
: (totalCount / SearchDataProvider.CONVERSATION_MESSAGE_PAGE_SIZE + 1);
if (pageIndex < totalPage) {
return false;
}
return true;
}
});
mImgvDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mEdtSearch.setText("");
mMessageLayout.setVisibility(View.GONE);
}
});
}
private void doChangeColor(String text) {
if (text.equals("")) {
mMessageRcSearchAdapter.setText(null);
} else {
mMessageRcSearchAdapter.setText(text);
}
}
private void initData(final String keyWords) {
if (keyWords == null || TextUtils.isEmpty(keyWords)) {
mMessageLayout.setVisibility(View.GONE);
return;
}
final List<String> keywordList = new ArrayList<String>() {
{ add(keyWords); }
};
presenter.searchMessage(keywordList, mConversationId, pageIndex, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> data) {
if (data.isEmpty() && pageIndex == 0) {
mMessageRcSearchAdapter.setConversationVisible(false);
mMessageLayout.setVisibility(View.GONE);
} else {
mMessageRcSearchAdapter.setConversationVisible(true);
mMessageLayout.setVisibility(View.VISIBLE);
}
}
@Override
public void onError(String module, int errCode, String errMsg) {
mMessageRcSearchAdapter.setConversationVisible(false);
mMessageLayout.setVisibility(View.GONE);
}
});
}
private void initView() {
mEdtSearch = findViewById(R.id.edt_search);
mImgvDelete = findViewById(R.id.imgv_delete);
mMessageRcSearch = findViewById(R.id.message_rc_search);
mCancleView = findViewById(R.id.cancel_button);
mMessageRcSearch.setLayoutManager(new LinearLayoutManager(this));
mMessageLayout = findViewById(R.id.message_layout);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
View v = getCurrentFocus();
if (isShouldHideInput(v, ev)) {
hideSoftInput(v.getWindowToken());
}
}
return super.dispatchTouchEvent(ev);
}
private boolean isShouldHideInput(View v, MotionEvent event) {
if (v != null && (v instanceof EditText)) {
int[] l = {0, 0};
v.getLocationInWindow(l);
int left = l[0];
int top = l[1];
int bottom = top + v.getHeight();
int right = left + v.getWidth();
if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) {
return false;
} else {
return true;
}
}
return false;
}
private void hideSoftInput(IBinder token) {
if (token != null) {
InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS);
}
}
}
@@ -0,0 +1,32 @@
package com.tencent.qcloud.tuikit.tuisearch.classicui.util;
import android.os.Bundle;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuikit.tuisearch.bean.ChatInfo;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchUtils;
public class ClassicSearchUtils {
public static void startChatActivity(ChatInfo chatInfo) {
Bundle param = new Bundle();
param.putInt(TUIConstants.TUIChat.CHAT_TYPE, chatInfo.getType());
param.putString(TUIConstants.TUIChat.CHAT_ID, chatInfo.getId());
param.putString(TUIConstants.TUIChat.CHAT_NAME, chatInfo.getChatName());
if (chatInfo.getDraft() != null) {
param.putString(TUIConstants.TUIChat.DRAFT_TEXT, chatInfo.getDraft().getDraftText());
param.putLong(TUIConstants.TUIChat.DRAFT_TIME, chatInfo.getDraft().getDraftTime());
}
param.putBoolean(TUIConstants.TUIChat.IS_TOP_CHAT, chatInfo.isTopChat());
if (chatInfo.getLocateMessage() != null && chatInfo.getLocateMessage().getTimMessage() != null) {
param.putSerializable(TUIConstants.TUIChat.LOCATE_MESSAGE, chatInfo.getLocateMessage().getTimMessage());
}
if (TUISearchUtils.isGroupChat(chatInfo.getType())) {
param.putString(TUIConstants.TUIChat.GROUP_TYPE, chatInfo.getGroupType());
}
if (TUISearchUtils.isGroupChat(chatInfo.getType())) {
TUICore.startActivity(TUIConstants.TUIChat.GROUP_CHAT_ACTIVITY_NAME, param);
} else {
TUICore.startActivity(TUIConstants.TUIChat.C2C_CHAT_ACTIVITY_NAME, param);
}
}
}
@@ -0,0 +1,48 @@
package com.tencent.qcloud.tuikit.tuisearch.classicui.widget;
import android.content.Context;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class PageRecycleView extends RecyclerView {
protected OnLoadMoreHandler mHandler;
public PageRecycleView(Context context) {
super(context);
}
public PageRecycleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public PageRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setLoadMoreMessageHandler(OnLoadMoreHandler mHandler) {
this.mHandler = mHandler;
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
if (state == RecyclerView.SCROLL_STATE_IDLE) {
if (mHandler != null) {
LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
int lastPosition = layoutManager.findLastCompletelyVisibleItemPosition();
if (lastPosition == getAdapter().getItemCount() - 1 && !mHandler.isListEnd(lastPosition)) {
mHandler.loadMore();
}
}
}
}
public interface OnLoadMoreHandler {
void loadMore();
boolean isListEnd(int position);
}
}
@@ -0,0 +1,245 @@
package com.tencent.qcloud.tuikit.tuisearch.classicui.widget;
import android.content.Context;
import android.graphics.Color;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.tencent.qcloud.tuicore.TUIThemeManager;
import com.tencent.qcloud.tuikit.timcommon.component.impl.GlideEngine;
import com.tencent.qcloud.tuikit.timcommon.util.TUIUtil;
import com.tencent.qcloud.tuikit.tuisearch.R;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import com.tencent.qcloud.tuikit.tuisearch.interfaces.ISearchMoreMsgAdapter;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SearchMoreMsgAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements ISearchMoreMsgAdapter {
private static final int SEARCH_MESSAGE_HEADER_TYPE = -1100;
private Context context;
private String text;
private int mViewType = -1;
// data list
private List<SearchDataBean> mDataList;
private int mTotalCount = 0;
private SearchDataBean searchDataBean;
private View.OnClickListener onConversationClickListener;
private boolean isConversationVisible = true;
public void setSearchDataBean(SearchDataBean searchDataBean) {
this.searchDataBean = searchDataBean;
}
public void setOnConversationClickListener(View.OnClickListener onConversationClickListener) {
this.onConversationClickListener = onConversationClickListener;
}
public void setText(String text) {
this.text = text;
}
public SearchMoreMsgAdapter(Context context) {
this.context = context;
}
public int getTotalCount() {
return mTotalCount;
}
@Override
public void onTotalCountChanged(int mTotalCount) {
this.mTotalCount = mTotalCount;
}
@Override
public void onDataSourceChanged(List<SearchDataBean> dataSource) {
if (dataSource == null) {
if (mDataList != null) {
mDataList.clear();
mDataList = null;
}
} else {
mDataList = dataSource;
}
notifyDataSetChanged();
}
public List<SearchDataBean> getDataSource() {
return mDataList;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == SEARCH_MESSAGE_HEADER_TYPE) {
return new SearchMessageHeaderHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.search_header, parent, false));
}
return new MessageViewHolder(LayoutInflater.from(context).inflate(R.layout.search_item_contact, parent, false));
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof SearchMessageHeaderHolder) {
bindSearchHeaderHolder((SearchMessageHeaderHolder) holder);
return;
}
MessageViewHolder contactViewHolder = (MessageViewHolder) holder;
if (contactViewHolder != null && mDataList != null && mDataList.size() > 0 && position <= mDataList.size()) {
SearchDataBean dataBean = mDataList.get(position - 1);
String title = dataBean.getTitle();
String subTitle = dataBean.getSubTitle();
String subTitleLabel = dataBean.getSubTitleLabel();
String path = dataBean.getIconPath();
contactViewHolder.mSubTvLabelText.setText(subTitleLabel);
if (!TextUtils.isEmpty(path)) {
GlideEngine.loadImage(contactViewHolder.mUserIconView, path);
} else {
int avatarIconResID;
if (searchDataBean.isGroup()) {
avatarIconResID = TUIUtil.getDefaultGroupIconResIDByGroupType(context, searchDataBean.getGroupType());
} else {
avatarIconResID = TUIThemeManager.getAttrResId(
contactViewHolder.mUserIconView.getContext(), com.tencent.qcloud.tuikit.timcommon.R.attr.core_default_user_icon);
}
contactViewHolder.mUserIconView.setImageResource(avatarIconResID);
}
if (text != null) {
SpannableString string = matcherSearchText(Color.rgb(0, 0, 255), title, text);
contactViewHolder.mTvText.setText(string);
SpannableString subString = matcherSearchText(Color.rgb(0, 0, 255), subTitle, text);
contactViewHolder.mSubTvText.setText(subString);
} else {
contactViewHolder.mTvText.setText(title);
contactViewHolder.mSubTvText.setText(subTitle);
}
contactViewHolder.mLlItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onItemClickListener.onClick(view, position - 1);
}
});
}
}
@Override
public int getItemCount() {
if (mDataList == null) {
return 1;
}
return mDataList.size() + 1;
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return SEARCH_MESSAGE_HEADER_TYPE;
}
return mViewType;
}
public interface OnItemClickListener {
void onClick(View view, int pos);
}
private OnItemClickListener onItemClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
private void bindSearchHeaderHolder(SearchMessageHeaderHolder holder) {
if (searchDataBean == null) {
return;
}
if (isConversationVisible) {
holder.conversationLayout.setVisibility(View.VISIBLE);
} else {
holder.conversationLayout.setVisibility(View.GONE);
}
holder.conversationLayout.setOnClickListener(onConversationClickListener);
int avatarDefaultIconResID;
if (searchDataBean.isGroup()) {
avatarDefaultIconResID = TUIUtil.getDefaultGroupIconResIDByGroupType(context, searchDataBean.getGroupType());
} else {
avatarDefaultIconResID =
TUIThemeManager.getAttrResId(holder.itemView.getContext(), com.tencent.qcloud.tuikit.timcommon.R.attr.core_default_user_icon);
}
if (!TextUtils.isEmpty(searchDataBean.getIconPath())) {
GlideEngine.loadImageSetDefault(holder.conversationIcon, searchDataBean.getIconPath(), avatarDefaultIconResID);
} else {
holder.conversationIcon.setImageResource(avatarDefaultIconResID);
}
holder.conversationTitle.setText(searchDataBean.getTitle());
}
public void setConversationVisible(boolean isVisible) {
isConversationVisible = isVisible;
notifyItemChanged(0);
}
static class MessageViewHolder extends RecyclerView.ViewHolder {
private LinearLayout mLlItem;
private ImageView mUserIconView;
private TextView mTvText;
private TextView mSubTvText;
private TextView mSubTvLabelText;
public MessageViewHolder(View itemView) {
super(itemView);
mLlItem = itemView.findViewById(R.id.ll_item);
mUserIconView = itemView.findViewById(R.id.ivAvatar);
mTvText = itemView.findViewById(R.id.conversation_title);
mSubTvText = itemView.findViewById(R.id.conversation_sub_title);
mSubTvLabelText = itemView.findViewById(R.id.conversation_sub_title_label);
}
}
static class SearchMessageHeaderHolder extends RecyclerView.ViewHolder {
private RelativeLayout conversationLayout;
private ImageView conversationIcon;
private TextView conversationTitle;
public SearchMessageHeaderHolder(@NonNull View itemView) {
super(itemView);
conversationLayout = itemView.findViewById(R.id.conversation_layout);
conversationIcon = itemView.findViewById(R.id.icon_conversation);
conversationTitle = itemView.findViewById(R.id.conversation_title);
}
}
private SpannableString matcherSearchText(int color, String text, String keyword) {
if (text == null || TextUtils.isEmpty(text)) {
return SpannableString.valueOf("");
}
SpannableString spannableString = new SpannableString(text);
Pattern pattern = Pattern.compile(Pattern.quote(keyword), Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(spannableString);
while (matcher.find()) {
int start = matcher.start();
int end = matcher.end();
spannableString.setSpan(new ForegroundColorSpan(color), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return spannableString;
}
}
@@ -0,0 +1,224 @@
package com.tencent.qcloud.tuikit.tuisearch.classicui.widget;
import android.content.Context;
import android.graphics.Color;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.tencent.qcloud.tuicore.TUIThemeManager;
import com.tencent.qcloud.tuikit.timcommon.component.impl.GlideEngine;
import com.tencent.qcloud.tuikit.timcommon.util.TUIUtil;
import com.tencent.qcloud.tuikit.tuisearch.R;
import com.tencent.qcloud.tuikit.tuisearch.TUISearchConstants;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import com.tencent.qcloud.tuikit.tuisearch.interfaces.ISearchResultAdapter;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SearchResultAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements ISearchResultAdapter {
private Context context;
private String text;
private int mViewType = -1;
private int mShowCount = 0;
private boolean mIsShowAll = false;
private int mTotalCount = 0;
// data list
private List<SearchDataBean> mDataList;
public void setText(String text) {
this.text = text;
}
public SearchResultAdapter(Context context) {
this.context = context;
}
public int getShowCount() {
if (mIsShowAll) {
return mShowCount;
} else {
if (mShowCount <= 3) {
return mShowCount;
} else {
return 3;
}
}
}
public void setShowCount(int mShowCount) {
this.mShowCount = mShowCount;
}
@Override
public void onIsShowAllChanged(boolean mIsShowAll) {
this.mIsShowAll = mIsShowAll;
}
public int getTotalCount() {
return mTotalCount;
}
@Override
public void onTotalCountChanged(int mTotalCount) {
this.mTotalCount = mTotalCount;
}
@Override
public void onDataSourceChanged(List<SearchDataBean> dataSource, int viewType) {
if (dataSource == null || dataSource.isEmpty()) {
if (mDataList != null) {
mDataList.clear();
mDataList = null;
}
setShowCount(0);
} else {
mDataList = dataSource;
setShowCount(mDataList.size());
}
mViewType = viewType;
notifyDataSetChanged();
}
public List<SearchDataBean> getDataSource() {
return mDataList;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ContactViewHolder holder = new ContactViewHolder(LayoutInflater.from(context).inflate(R.layout.search_item_contact, parent, false));
return holder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
/*If there is no search operation or the delete button is clicked after the search, we will empty the text in MainActivity and pass it over.*/
ContactViewHolder contactViewHolder = (ContactViewHolder) holder;
if (contactViewHolder != null && mDataList != null && mDataList.size() > 0 && position < mDataList.size()) {
SearchDataBean searchDataBean = mDataList.get(position);
String title = searchDataBean.getTitle();
String subTitle = searchDataBean.getSubTitle();
String subTitleLabel = searchDataBean.getSubTitleLabel();
contactViewHolder.mSubTvLabelText.setText(subTitleLabel);
if (TextUtils.isEmpty(subTitle)) {
RelativeLayout.LayoutParams layoutParams =
new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.CENTER_VERTICAL, RelativeLayout.TRUE);
contactViewHolder.mTvText.setLayoutParams(layoutParams);
} else {
RelativeLayout.LayoutParams layoutParams =
new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
contactViewHolder.mTvText.setLayoutParams(layoutParams);
}
int avatarDefaultIconResID;
if (searchDataBean.isGroup()) {
avatarDefaultIconResID = TUIUtil.getDefaultGroupIconResIDByGroupType(context, searchDataBean.getGroupType());
} else {
avatarDefaultIconResID = TUIThemeManager.getAttrResId(
contactViewHolder.mUserIconView.getContext(), com.tencent.qcloud.tuikit.timcommon.R.attr.core_default_user_icon);
}
String path = searchDataBean.getIconPath();
if (!TextUtils.isEmpty(path)) {
GlideEngine.loadImageSetDefault(contactViewHolder.mUserIconView, path, avatarDefaultIconResID);
} else {
contactViewHolder.mUserIconView.setImageResource(avatarDefaultIconResID);
}
if (text != null) {
if (mViewType == TUISearchConstants.CONVERSATION_TYPE) {
contactViewHolder.mTvText.setText(title);
int isSubTextMatch = mDataList.get(position).getIsSubTextMatch();
if (isSubTextMatch == 1) {
SpannableString subString = matcherSearchText(Color.rgb(0, 0, 255), subTitle, text);
contactViewHolder.mSubTvText.setText(subString);
} else {
contactViewHolder.mSubTvText.setText(subTitle);
}
} else {
SpannableString string = matcherSearchText(Color.rgb(0, 0, 255), title, text);
contactViewHolder.mTvText.setText(string);
SpannableString subString = matcherSearchText(Color.rgb(0, 0, 255), subTitle, text);
contactViewHolder.mSubTvText.setText(subString);
}
} else {
contactViewHolder.mTvText.setText(title);
contactViewHolder.mSubTvText.setText(subTitle);
}
contactViewHolder.mLlItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onItemClickListener.onClick(view, position);
}
});
}
}
@Override
public int getItemCount() {
return getShowCount();
}
@Override
public int getItemViewType(int position) {
return mViewType;
}
public interface OnItemClickListener {
void onClick(View view, int pos);
}
private OnItemClickListener onItemClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
class ContactViewHolder extends RecyclerView.ViewHolder {
private LinearLayout mLlItem;
private ImageView mUserIconView;
private TextView mTvText;
private TextView mSubTvText;
private TextView mSubTvLabelText;
public ContactViewHolder(View itemView) {
super(itemView);
mLlItem = itemView.findViewById(R.id.ll_item);
mUserIconView = itemView.findViewById(R.id.ivAvatar);
mTvText = itemView.findViewById(R.id.conversation_title);
mSubTvText = itemView.findViewById(R.id.conversation_sub_title);
mSubTvLabelText = itemView.findViewById(R.id.conversation_sub_title_label);
}
}
private SpannableString matcherSearchText(int color, String text, String keyword) {
if (text == null || TextUtils.isEmpty(text)) {
return SpannableString.valueOf("");
}
SpannableString spannableString = new SpannableString(text);
Pattern pattern = Pattern.compile(Pattern.quote(keyword), Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(spannableString);
while (matcher.find()) {
int start = matcher.start();
int end = matcher.end();
spannableString.setSpan(new ForegroundColorSpan(color), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return spannableString;
}
}
@@ -0,0 +1,11 @@
package com.tencent.qcloud.tuikit.tuisearch.interfaces;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import java.util.List;
public interface ISearchMoreMsgAdapter {
void onDataSourceChanged(List<SearchDataBean> searchDataBeanList);
void onTotalCountChanged(int totalCount);
}
@@ -0,0 +1,13 @@
package com.tencent.qcloud.tuikit.tuisearch.interfaces;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import java.util.List;
public interface ISearchResultAdapter {
void onDataSourceChanged(List<SearchDataBean> dataSource, int viewType);
void onIsShowAllChanged(boolean isShowAll);
void onTotalCountChanged(int totalCount);
}
@@ -0,0 +1,11 @@
package com.tencent.qcloud.tuikit.tuisearch.message;
public class MessageCustom {
public static final String BUSINESS_ID_GROUP_CREATE = "group_create";
public int version = 0;
public String businessID;
public String opUser;
public String content;
public String data;
}
@@ -0,0 +1,10 @@
package com.tencent.qcloud.tuikit.tuisearch.message;
public class MessageTyping {
public static final int TYPE_TYPING = 14;
public static final String EDIT_START = "EIMAMSG_InputStatus_Ing";
public static final String EDIT_END = "EIMAMSG_InputStatus_End";
public int userAction = 0;
public String actionParam = "";
}
@@ -0,0 +1,64 @@
package com.tencent.qcloud.tuikit.tuisearch.minimalistui;
import android.content.Context;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.google.auto.service.AutoService;
import com.tencent.qcloud.tuicore.ServiceInitializer;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuicore.annotations.TUIInitializerDependency;
import com.tencent.qcloud.tuicore.annotations.TUIInitializerID;
import com.tencent.qcloud.tuicore.interfaces.ITUIExtension;
import com.tencent.qcloud.tuicore.interfaces.TUIExtensionInfo;
import com.tencent.qcloud.tuicore.interfaces.TUIInitializer;
import com.tencent.qcloud.tuikit.tuisearch.R;
import java.util.List;
import java.util.Map;
@AutoService(TUIInitializer.class)
@TUIInitializerDependency({"TIMCommon"})
@TUIInitializerID("TUISearchMinimalistUIExtensionObserver")
public class MinimalistUIExtensionObserver implements TUIInitializer, ITUIExtension {
@Override
public void init(Context context) {
TUICore.registerExtension(TUIConstants.TUIConversation.Extension.ConversationListHeader.MINIMALIST_EXTENSION_ID, this);
}
@Override
public boolean onRaiseExtension(String extensionID, View parentView, Map<String, Object> param) {
if (TextUtils.equals(extensionID, TUIConstants.TUIConversation.Extension.ConversationListHeader.MINIMALIST_EXTENSION_ID)) {
ViewGroup viewGroup = null;
if (parentView instanceof ViewGroup) {
viewGroup = (ViewGroup) parentView;
}
if (viewGroup == null) {
return false;
}
View searchView = LayoutInflater.from(getAppContext()).inflate(R.layout.minimalist_search_view_layout, null);
viewGroup.removeAllViews();
searchView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
TUICore.startActivity("SearchMainMinimalistActivity", null);
}
});
viewGroup.addView(searchView);
return true;
}
return false;
}
@Override
public List<TUIExtensionInfo> onGetExtension(String extensionID, Map<String, Object> param) {
return null;
}
public static Context getAppContext() {
return ServiceInitializer.getAppContext();
}
}
@@ -0,0 +1,505 @@
package com.tencent.qcloud.tuikit.tuisearch.minimalistui.page;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.os.IBinder;
import android.text.Editable;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextPaint;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUIThemeManager;
import com.tencent.qcloud.tuikit.timcommon.component.activities.BaseMinimalistLightActivity;
import com.tencent.qcloud.tuikit.timcommon.component.dialog.TUIKitDialog;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuisearch.R;
import com.tencent.qcloud.tuikit.tuisearch.TUISearchConstants;
import com.tencent.qcloud.tuikit.tuisearch.bean.ChatInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import com.tencent.qcloud.tuikit.tuisearch.minimalistui.util.MinimalistSearchUtils;
import com.tencent.qcloud.tuikit.tuisearch.minimalistui.widget.PageRecycleView;
import com.tencent.qcloud.tuikit.tuisearch.minimalistui.widget.SearchResultAdapter;
import com.tencent.qcloud.tuikit.tuisearch.presenter.SearchMainPresenter;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchLog;
import java.util.ArrayList;
import java.util.List;
public class SearchMainMinimalistActivity extends BaseMinimalistLightActivity {
private static final String TAG = SearchMainMinimalistActivity.class.getSimpleName();
private EditText mEdtSearch;
private ImageView mImgvDelete;
private TextView mCancleView;
private RecyclerView mFriendRcSearch;
private RecyclerView mGroupRcSearch;
private PageRecycleView mConversationRcSearch;
private SearchResultAdapter mContactRcSearchAdapter;
private SearchResultAdapter mGroupRcSearchAdapter;
private SearchResultAdapter mConversationRcSearchAdapter;
private RelativeLayout mContactLayout;
private RelativeLayout mGroupLayout;
private RelativeLayout mConversationLayout;
private View mMoreContactButton;
private View mMoreGroupButton;
private View mMoreConversationButton;
private View notFoundArea;
private List<SearchDataBean> mContactSearchData = new ArrayList<>();
private List<SearchDataBean> mGroupSearchData = new ArrayList<>();
private List<SearchDataBean> mConversationData = new ArrayList<>();
private SearchMainPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.minimalist_search_main_activity);
init();
}
private void init() {
initView();
if (mContactRcSearchAdapter == null) {
mContactRcSearchAdapter = new SearchResultAdapter(this);
mFriendRcSearch.setAdapter(mContactRcSearchAdapter);
}
if (mGroupRcSearchAdapter == null) {
mGroupRcSearchAdapter = new SearchResultAdapter(this);
mGroupRcSearch.setAdapter(mGroupRcSearchAdapter);
}
if (mConversationRcSearchAdapter == null) {
mConversationRcSearchAdapter = new SearchResultAdapter(this);
mConversationRcSearch.setAdapter(mConversationRcSearchAdapter);
}
initPresenter();
setListener();
}
private void initView() {
mEdtSearch = findViewById(R.id.edt_search);
mImgvDelete = findViewById(R.id.imgv_delete);
mFriendRcSearch = findViewById(R.id.friend_rc_search);
mGroupRcSearch = findViewById(R.id.group_rc_search);
mConversationRcSearch = findViewById(R.id.conversation_rc_search);
mCancleView = findViewById(R.id.cancel_button);
mFriendRcSearch.setLayoutManager(new LinearLayoutManager(this));
mGroupRcSearch.setLayoutManager(new LinearLayoutManager(this));
mConversationRcSearch.setLayoutManager(new LinearLayoutManager(this));
mFriendRcSearch.setNestedScrollingEnabled(false);
mGroupRcSearch.setNestedScrollingEnabled(false);
mConversationRcSearch.setNestedScrollingEnabled(false);
mContactLayout = findViewById(R.id.contact_layout);
mMoreContactButton = findViewById(R.id.more_contact_button);
mGroupLayout = findViewById(R.id.group_layout);
mMoreGroupButton = findViewById(R.id.more_group_button);
mConversationLayout = findViewById(R.id.conversation_layout);
mMoreConversationButton = findViewById(R.id.more_conversation_button);
notFoundArea = findViewById(R.id.not_found_area);
mEdtSearch.requestFocus();
}
public void initPresenter() {
presenter = new SearchMainPresenter();
presenter.setGroupAdapter(mGroupRcSearchAdapter);
presenter.setContactAdapter(mContactRcSearchAdapter);
presenter.setConversationAdapter(mConversationRcSearchAdapter);
}
private void setListener() {
mEdtSearch.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void afterTextChanged(Editable editable) {
if (editable.length() == 0) {
mImgvDelete.setVisibility(View.GONE);
} else {
mImgvDelete.setVisibility(View.VISIBLE);
}
initData(editable.toString().trim());
doChangeColor(editable.toString().trim());
}
});
if (mContactRcSearchAdapter != null) {
mContactRcSearchAdapter.setOnItemClickListener(new SearchResultAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int pos) {
if (mContactSearchData != null && pos < mContactSearchData.size()) {
ChatInfo chatInfo = new ChatInfo();
chatInfo.setType(ChatInfo.TYPE_C2C);
SearchDataBean searchDataBean = mContactSearchData.get(pos);
chatInfo.setId(searchDataBean.getUserID());
String chatName = searchDataBean.getUserID();
if (!TextUtils.isEmpty(searchDataBean.getRemark())) {
chatName = searchDataBean.getRemark();
} else if (!TextUtils.isEmpty(searchDataBean.getNickName())) {
chatName = searchDataBean.getNickName();
}
chatInfo.setChatName(chatName);
MinimalistSearchUtils.startChatActivity(chatInfo);
}
}
});
}
if (mGroupRcSearchAdapter != null) {
mGroupRcSearchAdapter.setOnItemClickListener(new SearchResultAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int pos) {
if (mGroupSearchData != null && pos < mGroupSearchData.size()) {
SearchDataBean searchDataBean = mGroupSearchData.get(pos);
ChatInfo chatInfo = new ChatInfo();
chatInfo.setType(ChatInfo.TYPE_GROUP);
chatInfo.setGroupType(searchDataBean.getGroupType());
String chatName = searchDataBean.getUserID();
if (!TextUtils.isEmpty(searchDataBean.getRemark())) {
chatName = searchDataBean.getRemark();
} else if (!TextUtils.isEmpty(searchDataBean.getNickName())) {
chatName = searchDataBean.getNickName();
}
chatInfo.setChatName(chatName);
chatInfo.setId(searchDataBean.getGroupID());
MinimalistSearchUtils.startChatActivity(chatInfo);
}
}
});
}
if (mConversationRcSearchAdapter != null) {
mConversationRcSearchAdapter.setOnItemClickListener(new SearchResultAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int pos) {
if (mConversationRcSearchAdapter == null) {
return;
}
List<SearchDataBean> searchDataBeans = mConversationRcSearchAdapter.getDataSource();
if (searchDataBeans != null && pos < searchDataBeans.size()) {
SearchDataBean searchDataBean = searchDataBeans.get(pos);
Intent intent = new Intent(getApplicationContext(), SearchMoreMsgListMinimalistActivity.class);
intent.putExtra(TUISearchConstants.SEARCH_KEY_WORDS, mEdtSearch.getText().toString().trim());
intent.putExtra(TUISearchConstants.SEARCH_DATA_BEAN, searchDataBean);
startActivity(intent);
}
}
});
}
mImgvDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mEdtSearch.setText("");
mContactLayout.setVisibility(View.GONE);
mGroupLayout.setVisibility(View.GONE);
mConversationLayout.setVisibility(View.GONE);
}
});
mCancleView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onBackPressed();
}
});
mMoreContactButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mContactRcSearchAdapter == null) {
return;
}
List<SearchDataBean> searchDataBeans = mContactRcSearchAdapter.getDataSource();
if (searchDataBeans == null || searchDataBeans.size() < 4) {
return;
}
Intent intent = new Intent(getApplicationContext(), SearchMoreListMinimalistActivity.class);
intent.putExtra(TUISearchConstants.SEARCH_LIST_TYPE, TUISearchConstants.CONTACT_TYPE);
intent.putExtra(TUISearchConstants.SEARCH_KEY_WORDS, mEdtSearch.getText().toString().trim());
startActivity(intent);
}
});
mMoreGroupButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mGroupRcSearchAdapter == null) {
return;
}
List<SearchDataBean> searchDataBeans = mGroupRcSearchAdapter.getDataSource();
if (searchDataBeans == null || searchDataBeans.size() < 4) {
return;
}
Intent intent = new Intent(getApplicationContext(), SearchMoreListMinimalistActivity.class);
intent.putExtra(TUISearchConstants.SEARCH_LIST_TYPE, TUISearchConstants.GROUP_TYPE);
intent.putExtra(TUISearchConstants.SEARCH_KEY_WORDS, mEdtSearch.getText().toString().trim());
startActivity(intent);
}
});
mMoreConversationButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mConversationRcSearchAdapter == null) {
return;
}
List<SearchDataBean> searchDataBeans = mConversationRcSearchAdapter.getDataSource();
if (searchDataBeans == null || searchDataBeans.size() < 4) {
return;
}
Intent intent = new Intent(getApplicationContext(), SearchMoreListMinimalistActivity.class);
intent.putExtra(TUISearchConstants.SEARCH_LIST_TYPE, TUISearchConstants.CONVERSATION_TYPE);
intent.putExtra(TUISearchConstants.SEARCH_KEY_WORDS, mEdtSearch.getText().toString().trim());
startActivity(intent);
}
});
}
private void doChangeColor(String text) {
if (text.equals("")) {
mContactRcSearchAdapter.setText(null);
mGroupRcSearchAdapter.setText(null);
mConversationRcSearchAdapter.setText(null);
} else {
mContactRcSearchAdapter.setText(text);
mGroupRcSearchAdapter.setText(text);
mConversationRcSearchAdapter.setText(text);
}
}
private void initData(final String keyWords) {
if (keyWords == null || TextUtils.isEmpty(keyWords)) {
mContactLayout.setVisibility(View.GONE);
mGroupLayout.setVisibility(View.GONE);
mConversationLayout.setVisibility(View.GONE);
notFoundArea.setVisibility(View.GONE);
return;
}
final List<String> keywordList = new ArrayList<String>() {
{ add(keyWords); }
};
presenter.searchContact(keywordList, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> searchDataBeans) {
mContactSearchData = searchDataBeans;
if (searchDataBeans.isEmpty()) {
mContactLayout.setVisibility(View.GONE);
mMoreContactButton.setVisibility(View.GONE);
} else {
mContactLayout.setVisibility(View.VISIBLE);
if (searchDataBeans.size() > 3) {
mMoreContactButton.setVisibility(View.VISIBLE);
} else {
mMoreContactButton.setVisibility(View.GONE);
}
}
mContactRcSearchAdapter.onIsShowAllChanged(false);
invalidNotFoundInfo();
}
@Override
public void onError(String module, int code, String desc) {
if (code == TUIConstants.BuyingFeature.ERR_SDK_INTERFACE_NOT_SUPPORT) {
showNotSupportDialog();
}
TUISearchLog.d(TAG, "SearchContact onError code = " + code + ", desc = " + desc);
invalidNotFoundInfo();
}
});
presenter.searchGroup(keywordList, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> searchDataBeans) {
mGroupSearchData = searchDataBeans;
if (searchDataBeans.size() > 0) {
mGroupLayout.setVisibility(View.VISIBLE);
if (searchDataBeans.size() > 3) {
mMoreGroupButton.setVisibility(View.VISIBLE);
} else {
mMoreGroupButton.setVisibility(View.GONE);
}
} else {
mGroupLayout.setVisibility(View.GONE);
mMoreGroupButton.setVisibility(View.GONE);
}
mGroupRcSearchAdapter.onIsShowAllChanged(false);
invalidNotFoundInfo();
}
@Override
public void onError(String module, int code, String desc) {
if (code == TUIConstants.BuyingFeature.ERR_SDK_INTERFACE_NOT_SUPPORT) {
showNotSupportDialog();
}
TUISearchLog.d(TAG, "SearchContact onError code = " + code + ", desc = " + desc);
invalidNotFoundInfo();
}
});
presenter.searchConversation(keywordList, 0, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> data) {
if (data.size() > 0) {
mConversationLayout.setVisibility(View.VISIBLE);
if (data.size() > 3) {
mMoreConversationButton.setVisibility(View.VISIBLE);
} else {
mMoreConversationButton.setVisibility(View.GONE);
}
} else {
mConversationLayout.setVisibility(View.GONE);
mMoreConversationButton.setVisibility(View.GONE);
}
mConversationRcSearchAdapter.onIsShowAllChanged(false);
invalidNotFoundInfo();
}
@Override
public void onError(String module, int errCode, String errMsg) {
if (errCode == TUIConstants.BuyingFeature.ERR_SDK_INTERFACE_NOT_SUPPORT) {
showNotSupportDialog();
}
mConversationLayout.setVisibility(View.GONE);
mMoreConversationButton.setVisibility(View.GONE);
invalidNotFoundInfo();
}
});
}
private void invalidNotFoundInfo() {
if (mContactLayout.getVisibility() == View.GONE && mGroupLayout.getVisibility() == View.GONE && mConversationLayout.getVisibility() == View.GONE) {
notFoundArea.setVisibility(View.VISIBLE);
} else {
notFoundArea.setVisibility(View.GONE);
}
}
private void showNotSupportDialog() {
String string = getResources().getString(R.string.search_im_flagship_edition_update_tip, getString(R.string.search));
String buyingGuidelines = getResources().getString(R.string.search_buying_guidelines);
int buyingGuidelinesIndex = string.lastIndexOf(buyingGuidelines);
final int foregroundColor =
getResources().getColor(TUIThemeManager.getAttrResId(SearchMainMinimalistActivity.this, com.tencent.qcloud.tuicore.R.attr.core_primary_color));
SpannableString spannedString = new SpannableString(string);
ForegroundColorSpan colorSpan2 = new ForegroundColorSpan(foregroundColor);
spannedString.setSpan(colorSpan2, buyingGuidelinesIndex, buyingGuidelinesIndex + buyingGuidelines.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
ClickableSpan clickableSpan2 = new ClickableSpan() {
@Override
public void onClick(View view) {
if (TextUtils.equals(TUIThemeManager.getInstance().getCurrentLanguage(), "zh")) {
openWebUrl(TUIConstants.BuyingFeature.BUYING_PRICE_DESC);
} else {
openWebUrl(TUIConstants.BuyingFeature.BUYING_PRICE_DESC_EN);
}
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setUnderlineText(false);
}
};
spannedString.setSpan(clickableSpan2, buyingGuidelinesIndex, buyingGuidelinesIndex + buyingGuidelines.length(), Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
TUIKitDialog.TUIIMUpdateDialog.getInstance()
.createDialog(this)
.setShowOnlyDebug(true)
.setMovementMethod(LinkMovementMethod.getInstance())
.setHighlightColor(Color.TRANSPARENT)
.setCancelable(true)
.setCancelOutside(true)
.setTitle(spannedString)
.setDialogWidth(0.75f)
.setDialogFeatureName(TUIConstants.BuyingFeature.BUYING_FEATURE_SEARCH)
.setPositiveButton(getString(R.string.search_no_more_reminders),
new View.OnClickListener() {
@Override
public void onClick(View v) {
TUIKitDialog.TUIIMUpdateDialog.getInstance().dismiss();
TUIKitDialog.TUIIMUpdateDialog.getInstance().setNeverShow(true);
}
})
.setNegativeButton(getString(R.string.search_i_know),
new View.OnClickListener() {
@Override
public void onClick(View v) {
TUIKitDialog.TUIIMUpdateDialog.getInstance().dismiss();
}
})
.show();
}
private void openWebUrl(String url) {
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW);
Uri contentUrl = Uri.parse(url);
intent.setData(contentUrl);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
View v = getCurrentFocus();
if (isShouldHideInput(v, ev)) {
hideSoftInput(v.getWindowToken());
}
}
return super.dispatchTouchEvent(ev);
}
private boolean isShouldHideInput(View v, MotionEvent event) {
if (v != null && (v instanceof EditText)) {
int[] l = {0, 0};
v.getLocationInWindow(l);
int left = l[0];
int top = l[1];
int bottom = top + v.getHeight();
int right = left + v.getWidth();
if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) {
return false;
} else {
return true;
}
}
return false;
}
private void hideSoftInput(IBinder token) {
if (token != null) {
InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS);
}
}
}
@@ -0,0 +1,430 @@
package com.tencent.qcloud.tuikit.tuisearch.minimalistui.page;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.tencent.qcloud.tuikit.timcommon.component.activities.BaseMinimalistLightActivity;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuisearch.R;
import com.tencent.qcloud.tuikit.tuisearch.TUISearchConstants;
import com.tencent.qcloud.tuikit.tuisearch.bean.ChatInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import com.tencent.qcloud.tuikit.tuisearch.minimalistui.util.MinimalistSearchUtils;
import com.tencent.qcloud.tuikit.tuisearch.minimalistui.widget.PageRecycleView;
import com.tencent.qcloud.tuikit.tuisearch.minimalistui.widget.SearchResultAdapter;
import com.tencent.qcloud.tuikit.tuisearch.model.SearchDataProvider;
import com.tencent.qcloud.tuikit.tuisearch.presenter.SearchMainPresenter;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchLog;
import java.util.ArrayList;
import java.util.List;
public class SearchMoreListMinimalistActivity extends BaseMinimalistLightActivity {
private static final String TAG = SearchMoreListMinimalistActivity.class.getSimpleName();
private EditText mEdtSearch;
private ImageView mImgvDelete;
private TextView mCancleView;
private View searchBackButton;
private RecyclerView mFriendRcSearch;
private RecyclerView mGroupRcSearch;
private PageRecycleView mConversationRcSearch;
private SearchResultAdapter mContactRcSearchAdapter;
private SearchResultAdapter mGroupRcSearchAdapter;
private SearchResultAdapter mConversationRcSearchAdapter;
private RelativeLayout mContactLayout;
private RelativeLayout mGroupLayout;
private RelativeLayout mConversationLayout;
private View mMoreContactButton;
private View mMoreGroupButton;
private View mMoreConversationButton;
private View notFoundArea;
private int mViewType = -1;
private String mKeyWords;
private int pageIndex = 0;
private SearchMainPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.minimalist_search_main_activity);
init();
}
private void init() {
initView();
if (mContactRcSearchAdapter == null) {
mContactRcSearchAdapter = new SearchResultAdapter(this);
mFriendRcSearch.setAdapter(mContactRcSearchAdapter);
}
if (mGroupRcSearchAdapter == null) {
mGroupRcSearchAdapter = new SearchResultAdapter(this);
mGroupRcSearch.setAdapter(mGroupRcSearchAdapter);
}
if (mConversationRcSearchAdapter == null) {
mConversationRcSearchAdapter = new SearchResultAdapter(this);
mConversationRcSearch.setAdapter(mConversationRcSearchAdapter);
}
initPresenter();
Intent intent = getIntent();
if (intent != null) {
mViewType = intent.getIntExtra(TUISearchConstants.SEARCH_LIST_TYPE, -1);
mKeyWords = intent.getStringExtra(TUISearchConstants.SEARCH_KEY_WORDS);
pageIndex = 0;
// also ok
initData(mKeyWords);
mEdtSearch.setText(mKeyWords);
doChangeColor(mKeyWords);
}
setListener();
}
private void initView() {
mEdtSearch = (EditText) findViewById(R.id.edt_search);
mImgvDelete = (ImageView) findViewById(R.id.imgv_delete);
searchBackButton = (ImageView) findViewById(R.id.search_back_icon);
mFriendRcSearch = (RecyclerView) findViewById(R.id.friend_rc_search);
mGroupRcSearch = (RecyclerView) findViewById(R.id.group_rc_search);
mConversationRcSearch = (PageRecycleView) findViewById(R.id.conversation_rc_search);
mCancleView = (TextView) findViewById(R.id.cancel_button);
mFriendRcSearch.setLayoutManager(new LinearLayoutManager(this));
mGroupRcSearch.setLayoutManager(new LinearLayoutManager(this));
mConversationRcSearch.setLayoutManager(new LinearLayoutManager(this));
mFriendRcSearch.setNestedScrollingEnabled(false);
mGroupRcSearch.setNestedScrollingEnabled(false);
mConversationRcSearch.setNestedScrollingEnabled(true);
mContactLayout = (RelativeLayout) findViewById(R.id.contact_layout);
mMoreContactButton = findViewById(R.id.more_contact_button);
mGroupLayout = (RelativeLayout) findViewById(R.id.group_layout);
mMoreGroupButton = findViewById(R.id.more_group_button);
mConversationLayout = findViewById(R.id.conversation_layout);
mMoreConversationButton = findViewById(R.id.more_conversation_button);
notFoundArea = findViewById(R.id.not_found_area);
searchBackButton.setVisibility(View.VISIBLE);
searchBackButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
mMoreContactButton.setVisibility(View.GONE);
mMoreConversationButton.setVisibility(View.GONE);
mMoreGroupButton.setVisibility(View.GONE);
}
private void initPresenter() {
presenter = new SearchMainPresenter();
presenter.setContactAdapter(mContactRcSearchAdapter);
presenter.setConversationAdapter(mConversationRcSearchAdapter);
presenter.setGroupAdapter(mGroupRcSearchAdapter);
}
private void setListener() {
mEdtSearch.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void afterTextChanged(Editable editable) {
if (editable.length() == 0) {
mImgvDelete.setVisibility(View.GONE);
} else {
mImgvDelete.setVisibility(View.VISIBLE);
}
mKeyWords = editable.toString().trim();
pageIndex = 0;
mConversationRcSearch.setNestedScrollingEnabled(true);
initData(mKeyWords);
doChangeColor(mKeyWords);
}
});
mCancleView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onBackPressed();
}
});
if (mContactRcSearchAdapter != null) {
mContactRcSearchAdapter.setOnItemClickListener(new SearchResultAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int pos) {
List<SearchDataBean> searchDataBeans = mContactRcSearchAdapter.getDataSource();
if (searchDataBeans != null && pos < searchDataBeans.size()) {
SearchDataBean searchDataBean = searchDataBeans.get(pos);
ChatInfo chatInfo = new ChatInfo();
chatInfo.setType(ChatInfo.TYPE_C2C);
chatInfo.setId(searchDataBean.getUserID());
String chatName = searchDataBean.getUserID();
if (!TextUtils.isEmpty(searchDataBean.getRemark())) {
chatName = searchDataBean.getRemark();
} else if (!TextUtils.isEmpty(searchDataBean.getNickName())) {
chatName = searchDataBean.getNickName();
}
chatInfo.setChatName(chatName);
MinimalistSearchUtils.startChatActivity(chatInfo);
}
}
});
}
if (mGroupRcSearchAdapter != null) {
mGroupRcSearchAdapter.setOnItemClickListener(new SearchResultAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int pos) {
List<SearchDataBean> searchDataBeans = mGroupRcSearchAdapter.getDataSource();
if (searchDataBeans != null && pos < searchDataBeans.size()) {
SearchDataBean searchDataBean = searchDataBeans.get(pos);
ChatInfo chatInfo = new ChatInfo();
chatInfo.setType(ChatInfo.TYPE_GROUP);
chatInfo.setGroupType(searchDataBean.getGroupType());
String chatName = searchDataBean.getUserID();
if (!TextUtils.isEmpty(searchDataBean.getRemark())) {
chatName = searchDataBean.getRemark();
} else if (!TextUtils.isEmpty(searchDataBean.getNickName())) {
chatName = searchDataBean.getNickName();
}
chatInfo.setChatName(chatName);
chatInfo.setId(searchDataBean.getGroupID());
MinimalistSearchUtils.startChatActivity(chatInfo);
}
}
});
}
if (mConversationRcSearchAdapter != null) {
mConversationRcSearchAdapter.setOnItemClickListener(new SearchResultAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int pos) {
if (mConversationRcSearchAdapter == null) {
return;
}
List<SearchDataBean> searchDataBeans = mConversationRcSearchAdapter.getDataSource();
if (searchDataBeans != null && pos < searchDataBeans.size()) {
SearchDataBean searchDataBean = searchDataBeans.get(pos);
Intent intent = new Intent(getApplicationContext(), SearchMoreMsgListMinimalistActivity.class);
intent.putExtra(TUISearchConstants.SEARCH_KEY_WORDS, mEdtSearch.getText().toString().trim());
intent.putExtra(TUISearchConstants.SEARCH_DATA_BEAN, searchDataBean);
startActivity(intent);
}
}
});
mConversationRcSearch.setLoadMoreMessageHandler(new PageRecycleView.OnLoadMoreHandler() {
@Override
public void loadMore() {
final List<String> keywordList = new ArrayList<String>() {
{ add(mKeyWords); }
};
presenter.searchConversation(keywordList, ++pageIndex, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> data) {
if (data.size() > 0) {
mConversationLayout.setVisibility(View.VISIBLE);
} else {
mConversationLayout.setVisibility(View.GONE);
mMoreConversationButton.setVisibility(View.GONE);
}
mConversationRcSearchAdapter.onIsShowAllChanged(true);
}
@Override
public void onError(String module, int errCode, String errMsg) {
mConversationLayout.setVisibility(View.GONE);
mMoreConversationButton.setVisibility(View.GONE);
}
});
}
@Override
public boolean isListEnd(int postion) {
mConversationRcSearch.setNestedScrollingEnabled(false);
if (mConversationRcSearchAdapter == null || mConversationRcSearchAdapter.getTotalCount() == 0) {
return true;
}
int totalCount = mConversationRcSearchAdapter.getTotalCount();
int totalPage = (totalCount % SearchDataProvider.CONVERSATION_MESSAGE_PAGE_SIZE == 0)
? (totalCount / SearchDataProvider.CONVERSATION_MESSAGE_PAGE_SIZE)
: (totalCount / SearchDataProvider.CONVERSATION_MESSAGE_PAGE_SIZE + 1);
if (pageIndex + 1 < totalPage) {
return false;
}
return true;
}
});
}
mImgvDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mEdtSearch.setText("");
mContactLayout.setVisibility(View.GONE);
mGroupLayout.setVisibility(View.GONE);
mConversationLayout.setVisibility(View.GONE);
}
});
}
private void doChangeColor(String text) {
if (text.equals("")) {
mContactRcSearchAdapter.setText(null);
mGroupRcSearchAdapter.setText(null);
mConversationRcSearchAdapter.setText(null);
} else {
mContactRcSearchAdapter.setText(text);
mGroupRcSearchAdapter.setText(text);
mConversationRcSearchAdapter.setText(text);
}
}
private void invalidNotFoundInfo() {
if (mContactLayout.getVisibility() == View.GONE && mGroupLayout.getVisibility() == View.GONE && mConversationLayout.getVisibility() == View.GONE) {
notFoundArea.setVisibility(View.VISIBLE);
} else {
notFoundArea.setVisibility(View.GONE);
}
}
private void initData(final String keyWords) {
if (keyWords == null || TextUtils.isEmpty(keyWords)) {
mContactLayout.setVisibility(View.GONE);
mGroupLayout.setVisibility(View.GONE);
mConversationLayout.setVisibility(View.GONE);
notFoundArea.setVisibility(View.GONE);
return;
}
final List<String> keywordList = new ArrayList<String>() {
{ add(keyWords); }
};
if (mViewType == TUISearchConstants.CONTACT_TYPE) {
presenter.searchContact(keywordList, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> searchDataBeans) {
if (searchDataBeans.isEmpty()) {
mContactLayout.setVisibility(View.GONE);
} else {
mContactLayout.setVisibility(View.VISIBLE);
}
mContactRcSearchAdapter.onIsShowAllChanged(true);
invalidNotFoundInfo();
}
@Override
public void onError(String module, int code, String desc) {
TUISearchLog.d(TAG, "SearchContact onError code = " + code + ", desc = " + desc);
invalidNotFoundInfo();
}
});
} else if (mViewType == TUISearchConstants.GROUP_TYPE) {
presenter.searchGroup(keywordList, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> searchDataBeans) {
if (searchDataBeans.size() > 0) {
mGroupLayout.setVisibility(View.VISIBLE);
} else {
mGroupLayout.setVisibility(View.GONE);
}
mGroupRcSearchAdapter.onIsShowAllChanged(true);
invalidNotFoundInfo();
}
@Override
public void onError(String module, int code, String desc) {
TUISearchLog.d(TAG, "SearchContact onError code = " + code + ", desc = " + desc);
invalidNotFoundInfo();
}
});
} else if (mViewType == TUISearchConstants.CONVERSATION_TYPE) {
presenter.searchConversation(keywordList, 0, new IUIKitCallback<List<SearchDataBean>>() {
public void onSuccess(List<SearchDataBean> data) {
if (data.size() > 0) {
mConversationLayout.setVisibility(View.VISIBLE);
} else {
mConversationLayout.setVisibility(View.GONE);
mMoreConversationButton.setVisibility(View.GONE);
}
mConversationRcSearchAdapter.onIsShowAllChanged(true);
invalidNotFoundInfo();
}
@Override
public void onError(String module, int errCode, String errMsg) {
mConversationLayout.setVisibility(View.GONE);
mMoreConversationButton.setVisibility(View.GONE);
invalidNotFoundInfo();
}
});
} else {
TUISearchLog.e(TAG, "mViewType is invalid :" + mViewType);
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
View v = getCurrentFocus();
if (isShouldHideInput(v, ev)) {
hideSoftInput(v.getWindowToken());
}
}
return super.dispatchTouchEvent(ev);
}
private boolean isShouldHideInput(View v, MotionEvent event) {
if (v != null && (v instanceof EditText)) {
int[] l = {0, 0};
v.getLocationInWindow(l);
int left = l[0];
int top = l[1];
int bottom = top + v.getHeight();
int right = left + v.getWidth();
if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) {
return false;
} else {
return true;
}
}
return false;
}
private void hideSoftInput(IBinder token) {
if (token != null) {
InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS);
}
}
}
@@ -0,0 +1,335 @@
package com.tencent.qcloud.tuikit.tuisearch.minimalistui.page;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.IBinder;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.tencent.qcloud.tuikit.timcommon.component.activities.BaseMinimalistLightActivity;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuisearch.R;
import com.tencent.qcloud.tuikit.tuisearch.TUISearchConstants;
import com.tencent.qcloud.tuikit.tuisearch.bean.ChatInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import com.tencent.qcloud.tuikit.tuisearch.minimalistui.util.MinimalistSearchUtils;
import com.tencent.qcloud.tuikit.tuisearch.minimalistui.widget.PageRecycleView;
import com.tencent.qcloud.tuikit.tuisearch.minimalistui.widget.SearchMoreMsgAdapter;
import com.tencent.qcloud.tuikit.tuisearch.model.SearchDataProvider;
import com.tencent.qcloud.tuikit.tuisearch.presenter.SearchMoreMsgPresenter;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchLog;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchUtils;
import java.util.ArrayList;
import java.util.List;
public class SearchMoreMsgListMinimalistActivity extends BaseMinimalistLightActivity {
private static final String TAG = SearchMoreMsgListMinimalistActivity.class.getSimpleName();
private EditText mEdtSearch;
private ImageView mImgvDelete;
private TextView mCancleView;
private View searchBackButton;
private View notFoundArea;
private PageRecycleView mMessageRcSearch;
private SearchMoreMsgAdapter mMessageRcSearchAdapter;
private RelativeLayout mMessageLayout;
private String mKeyWords;
private String mConversationId;
private boolean mIsGroup;
private SearchDataBean mSearchDataBean;
private int pageIndex = 0;
private SearchMoreMsgPresenter presenter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.minimalist_search_more_msg_activity);
init();
}
private void init() {
initView();
if (mMessageRcSearchAdapter == null) {
mMessageRcSearchAdapter = new SearchMoreMsgAdapter(this);
mMessageRcSearch.setAdapter(mMessageRcSearchAdapter);
}
initPresenter();
Intent intent = getIntent();
if (intent != null) {
mKeyWords = intent.getStringExtra(TUISearchConstants.SEARCH_KEY_WORDS);
mSearchDataBean = intent.getParcelableExtra(TUISearchConstants.SEARCH_DATA_BEAN);
pageIndex = 0;
mMessageRcSearchAdapter.setSearchDataBean(mSearchDataBean);
if (mSearchDataBean != null) {
mIsGroup = mSearchDataBean.isGroup();
if (mIsGroup) {
mConversationId = TUISearchUtils.getConversationIdByUserId(mSearchDataBean.getGroupID(), true);
} else {
mConversationId = TUISearchUtils.getConversationIdByUserId(mSearchDataBean.getUserID(), false);
}
}
initData(mKeyWords);
mEdtSearch.setText(mKeyWords);
doChangeColor(mKeyWords);
}
setListener();
}
private void initView() {
mEdtSearch = findViewById(R.id.edt_search);
mImgvDelete = findViewById(R.id.imgv_delete);
searchBackButton = findViewById(R.id.search_back_icon);
searchBackButton.setVisibility(View.VISIBLE);
searchBackButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
}
});
mMessageRcSearch = findViewById(R.id.message_rc_search);
mCancleView = findViewById(R.id.cancel_button);
mMessageRcSearch.setLayoutManager(new LinearLayoutManager(this));
mMessageLayout = findViewById(R.id.message_layout);
notFoundArea = findViewById(R.id.not_found_area);
}
private void initPresenter() {
presenter = new SearchMoreMsgPresenter();
presenter.setAdapter(mMessageRcSearchAdapter);
}
private void setListener() {
mEdtSearch.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {}
@Override
public void afterTextChanged(Editable editable) {
if (editable.length() == 0) {
mImgvDelete.setVisibility(View.GONE);
} else {
mImgvDelete.setVisibility(View.VISIBLE);
}
mKeyWords = editable.toString().trim();
pageIndex = 0;
mMessageRcSearch.setNestedScrollingEnabled(true);
initData(mKeyWords);
doChangeColor(mKeyWords);
}
});
mCancleView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onBackPressed();
}
});
if (mMessageRcSearchAdapter != null) {
mMessageRcSearchAdapter.setOnItemClickListener(new SearchMoreMsgAdapter.OnItemClickListener() {
@Override
public void onClick(View view, int pos) {
if (mSearchDataBean == null) {
TUISearchLog.e(TAG, "mSearchDataBean == null");
return;
}
List<SearchDataBean> searchDataBeans = mMessageRcSearchAdapter.getDataSource();
if (searchDataBeans != null && pos < searchDataBeans.size()) {
SearchDataBean searchDataBean = searchDataBeans.get(pos);
ChatInfo chatInfo = presenter.generateChatInfo(searchDataBean);
MinimalistSearchUtils.startChatActivity(chatInfo);
}
}
});
}
mMessageRcSearchAdapter.setOnConversationClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mSearchDataBean == null) {
TUISearchLog.e(TAG, "mSearchDataBean == null");
return;
}
ChatInfo chatInfo = new ChatInfo();
if (mSearchDataBean.isGroup()) {
chatInfo.setType(ChatInfo.TYPE_GROUP);
chatInfo.setId(mSearchDataBean.getGroupID());
chatInfo.setGroupType(mSearchDataBean.getGroupType());
} else {
chatInfo.setType(ChatInfo.TYPE_C2C);
chatInfo.setId(mSearchDataBean.getUserID());
}
String chatName = mSearchDataBean.getUserID();
if (!TextUtils.isEmpty(mSearchDataBean.getRemark())) {
chatName = mSearchDataBean.getRemark();
} else if (!TextUtils.isEmpty(mSearchDataBean.getNickName())) {
chatName = mSearchDataBean.getNickName();
}
chatInfo.setChatName(chatName);
MinimalistSearchUtils.startChatActivity(chatInfo);
}
});
mMessageRcSearch.setLoadMoreMessageHandler(new PageRecycleView.OnLoadMoreHandler() {
@Override
public void loadMore() {
final List<String> keywordList = new ArrayList<String>() {
{ add(mKeyWords); }
};
presenter.searchMessage(keywordList, mConversationId, ++pageIndex, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> data) {
if (data.isEmpty() && pageIndex == 0) {
mMessageRcSearchAdapter.setConversationVisible(false);
mMessageLayout.setVisibility(View.GONE);
} else {
mMessageRcSearchAdapter.setConversationVisible(true);
mMessageLayout.setVisibility(View.VISIBLE);
}
invalidNotFoundInfo();
}
@Override
public void onError(String module, int errCode, String errMsg) {
mMessageRcSearchAdapter.setConversationVisible(false);
mMessageLayout.setVisibility(View.GONE);
invalidNotFoundInfo();
}
});
}
@Override
public boolean isListEnd(int position) {
if (mMessageRcSearchAdapter == null || mMessageRcSearchAdapter.getTotalCount() == 0) {
return true;
}
int totalCount = mMessageRcSearchAdapter.getTotalCount();
int totalPage = (totalCount % SearchDataProvider.CONVERSATION_MESSAGE_PAGE_SIZE == 0)
? (totalCount / SearchDataProvider.CONVERSATION_MESSAGE_PAGE_SIZE)
: (totalCount / SearchDataProvider.CONVERSATION_MESSAGE_PAGE_SIZE + 1);
if (pageIndex < totalPage) {
return false;
}
return true;
}
});
mImgvDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mEdtSearch.setText("");
mMessageLayout.setVisibility(View.GONE);
}
});
}
private void invalidNotFoundInfo() {
if (mMessageLayout.getVisibility() == View.GONE) {
notFoundArea.setVisibility(View.VISIBLE);
} else {
notFoundArea.setVisibility(View.GONE);
}
}
private void doChangeColor(String text) {
if (text.equals("")) {
mMessageRcSearchAdapter.setText(null);
} else {
mMessageRcSearchAdapter.setText(text);
}
}
private void initData(final String keyWords) {
if (keyWords == null || TextUtils.isEmpty(keyWords)) {
mMessageLayout.setVisibility(View.GONE);
notFoundArea.setVisibility(View.GONE);
return;
}
final List<String> keywordList = new ArrayList<String>() {
{ add(keyWords); }
};
presenter.searchMessage(keywordList, mConversationId, pageIndex, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> data) {
if (data.isEmpty() && pageIndex == 0) {
mMessageRcSearchAdapter.setConversationVisible(false);
mMessageLayout.setVisibility(View.GONE);
} else {
mMessageRcSearchAdapter.setConversationVisible(true);
mMessageLayout.setVisibility(View.VISIBLE);
}
invalidNotFoundInfo();
}
@Override
public void onError(String module, int errCode, String errMsg) {
mMessageRcSearchAdapter.setConversationVisible(false);
mMessageLayout.setVisibility(View.GONE);
invalidNotFoundInfo();
}
});
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
View v = getCurrentFocus();
if (isShouldHideInput(v, ev)) {
hideSoftInput(v.getWindowToken());
}
}
return super.dispatchTouchEvent(ev);
}
private boolean isShouldHideInput(View v, MotionEvent event) {
if (v != null && (v instanceof EditText)) {
int[] l = {0, 0};
v.getLocationInWindow(l);
int left = l[0];
int top = l[1];
int bottom = top + v.getHeight();
int right = left + v.getWidth();
if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) {
return false;
} else {
return true;
}
}
return false;
}
private void hideSoftInput(IBinder token) {
if (token != null) {
InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
im.hideSoftInputFromWindow(token, InputMethodManager.HIDE_NOT_ALWAYS);
}
}
}
@@ -0,0 +1,32 @@
package com.tencent.qcloud.tuikit.tuisearch.minimalistui.util;
import android.os.Bundle;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuicore.TUICore;
import com.tencent.qcloud.tuikit.tuisearch.bean.ChatInfo;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchUtils;
public class MinimalistSearchUtils {
public static void startChatActivity(ChatInfo chatInfo) {
Bundle param = new Bundle();
param.putInt(TUIConstants.TUIChat.CHAT_TYPE, chatInfo.getType());
param.putString(TUIConstants.TUIChat.CHAT_ID, chatInfo.getId());
if (chatInfo.getDraft() != null) {
param.putString(TUIConstants.TUIChat.DRAFT_TEXT, chatInfo.getDraft().getDraftText());
param.putLong(TUIConstants.TUIChat.DRAFT_TIME, chatInfo.getDraft().getDraftTime());
}
param.putBoolean(TUIConstants.TUIChat.IS_TOP_CHAT, chatInfo.isTopChat());
if (chatInfo.getLocateMessage() != null && chatInfo.getLocateMessage().getTimMessage() != null) {
param.putSerializable(TUIConstants.TUIChat.LOCATE_MESSAGE, chatInfo.getLocateMessage().getTimMessage());
}
if (TUISearchUtils.isGroupChat(chatInfo.getType())) {
param.putString(TUIConstants.TUIChat.GROUP_TYPE, chatInfo.getGroupType());
}
if (TUISearchUtils.isGroupChat(chatInfo.getType())) {
TUICore.startActivity("TUIGroupChatMinimalistActivity", param);
} else {
TUICore.startActivity("TUIC2CChatMinimalistActivity", param);
}
}
}
@@ -0,0 +1,48 @@
package com.tencent.qcloud.tuikit.tuisearch.minimalistui.widget;
import android.content.Context;
import android.util.AttributeSet;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class PageRecycleView extends RecyclerView {
protected OnLoadMoreHandler mHandler;
public PageRecycleView(Context context) {
super(context);
}
public PageRecycleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public PageRecycleView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public void setLoadMoreMessageHandler(OnLoadMoreHandler mHandler) {
this.mHandler = mHandler;
}
@Override
public void onScrollStateChanged(int state) {
super.onScrollStateChanged(state);
if (state == RecyclerView.SCROLL_STATE_IDLE) {
if (mHandler != null) {
LinearLayoutManager layoutManager = (LinearLayoutManager) getLayoutManager();
int lastPosition = layoutManager.findLastCompletelyVisibleItemPosition();
if (lastPosition == getAdapter().getItemCount() - 1 && !mHandler.isListEnd(lastPosition)) {
mHandler.loadMore();
}
}
}
}
public interface OnLoadMoreHandler {
void loadMore();
boolean isListEnd(int position);
}
}
@@ -0,0 +1,248 @@
package com.tencent.qcloud.tuikit.tuisearch.minimalistui.widget;
import android.content.Context;
import android.graphics.Color;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.tencent.qcloud.tuicore.TUIThemeManager;
import com.tencent.qcloud.tuikit.timcommon.component.impl.GlideEngine;
import com.tencent.qcloud.tuikit.timcommon.util.DateTimeUtil;
import com.tencent.qcloud.tuikit.timcommon.util.TUIUtil;
import com.tencent.qcloud.tuikit.tuisearch.R;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import com.tencent.qcloud.tuikit.tuisearch.interfaces.ISearchMoreMsgAdapter;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SearchMoreMsgAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements ISearchMoreMsgAdapter {
private static final int SEARCH_MESSAGE_HEADER_TYPE = -1100;
private Context context;
private String text;
private int mViewType = -1;
// data list
private List<SearchDataBean> mDataList;
private int mTotalCount = 0;
private SearchDataBean searchDataBean;
private View.OnClickListener onConversationClickListener;
private boolean isConversationVisible = true;
public void setSearchDataBean(SearchDataBean searchDataBean) {
this.searchDataBean = searchDataBean;
}
public void setOnConversationClickListener(View.OnClickListener onConversationClickListener) {
this.onConversationClickListener = onConversationClickListener;
}
public void setText(String text) {
this.text = text;
}
public SearchMoreMsgAdapter(Context context) {
this.context = context;
}
public int getTotalCount() {
return mTotalCount;
}
@Override
public void onTotalCountChanged(int mTotalCount) {
this.mTotalCount = mTotalCount;
}
@Override
public void onDataSourceChanged(List<SearchDataBean> dataSource) {
if (dataSource == null) {
if (mDataList != null) {
mDataList.clear();
mDataList = null;
}
} else {
mDataList = dataSource;
}
notifyDataSetChanged();
}
public List<SearchDataBean> getDataSource() {
return mDataList;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == SEARCH_MESSAGE_HEADER_TYPE) {
return new SearchMessageHeaderHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.minimalist_search_header, parent, false));
}
return new MessageViewHolder(LayoutInflater.from(context).inflate(R.layout.minimalist_message_item_layout, parent, false));
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if (holder instanceof SearchMessageHeaderHolder) {
bindSearchHeaderHolder((SearchMessageHeaderHolder) holder);
return;
}
MessageViewHolder contactViewHolder = (MessageViewHolder) holder;
if (contactViewHolder != null && mDataList != null && mDataList.size() > 0 && position <= mDataList.size()) {
SearchDataBean dataBean = mDataList.get(position - 1);
String title = dataBean.getTitle();
String subTitle = dataBean.getSubTitle();
String subTitleLabel = dataBean.getSubTitleLabel();
String path = dataBean.getIconPath();
contactViewHolder.mSubTvLabelText.setText(subTitleLabel);
if (!TextUtils.isEmpty(path)) {
GlideEngine.loadImage(contactViewHolder.mUserIconView, path);
} else {
int avatarIconResID;
if (searchDataBean.isGroup()) {
avatarIconResID = TUIUtil.getDefaultGroupIconResIDByGroupType(context, searchDataBean.getGroupType());
} else {
avatarIconResID = TUIThemeManager.getAttrResId(
contactViewHolder.mUserIconView.getContext(), com.tencent.qcloud.tuikit.timcommon.R.attr.core_default_user_icon);
}
GlideEngine.loadImage(contactViewHolder.mUserIconView, avatarIconResID);
}
if (text != null) {
SpannableString string = matcherSearchText(Color.rgb(0, 0, 255), title, text);
contactViewHolder.mTvText.setText(string);
SpannableString subString = matcherSearchText(Color.rgb(0, 0, 255), subTitle, text);
contactViewHolder.mSubTvText.setText(subString);
} else {
contactViewHolder.mTvText.setText(title);
contactViewHolder.mSubTvText.setText(subTitle);
}
contactViewHolder.mLlItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onItemClickListener.onClick(view, position - 1);
}
});
contactViewHolder.messageTimeTv.setText(DateTimeUtil.getTimeFormatText(new Date(dataBean.getMessageTime() * 1000)));
}
}
@Override
public int getItemCount() {
if (mDataList == null) {
return 1;
}
return mDataList.size() + 1;
}
@Override
public int getItemViewType(int position) {
if (position == 0) {
return SEARCH_MESSAGE_HEADER_TYPE;
}
return mViewType;
}
public interface OnItemClickListener {
void onClick(View view, int pos);
}
private OnItemClickListener onItemClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
private void bindSearchHeaderHolder(SearchMessageHeaderHolder holder) {
if (searchDataBean == null) {
return;
}
if (isConversationVisible) {
holder.conversationLayout.setVisibility(View.VISIBLE);
} else {
holder.conversationLayout.setVisibility(View.GONE);
}
holder.conversationLayout.setOnClickListener(onConversationClickListener);
int avatarDefaultIconResID;
if (searchDataBean.isGroup()) {
avatarDefaultIconResID = TUIUtil.getDefaultGroupIconResIDByGroupType(context, searchDataBean.getGroupType());
} else {
avatarDefaultIconResID =
TUIThemeManager.getAttrResId(holder.itemView.getContext(), com.tencent.qcloud.tuikit.timcommon.R.attr.core_default_user_icon);
}
GlideEngine.loadImageSetDefault(holder.conversationIcon, searchDataBean.getIconPath(), avatarDefaultIconResID);
holder.conversationTitle.setText(searchDataBean.getTitle());
}
public void setConversationVisible(boolean isVisible) {
isConversationVisible = isVisible;
notifyItemChanged(0);
}
static class MessageViewHolder extends RecyclerView.ViewHolder {
private LinearLayout mLlItem;
private ImageView mUserIconView;
private TextView mTvText;
private TextView mSubTvText;
private TextView mSubTvLabelText;
private TextView messageTimeTv;
private ImageView messageStatusIcon;
public MessageViewHolder(View itemView) {
super(itemView);
mLlItem = itemView.findViewById(R.id.ll_item);
mUserIconView = itemView.findViewById(R.id.ivAvatar);
mTvText = itemView.findViewById(R.id.conversation_title);
mSubTvText = itemView.findViewById(R.id.conversation_sub_title);
mSubTvLabelText = itemView.findViewById(R.id.conversation_sub_title_label);
messageTimeTv = itemView.findViewById(R.id.message_time_tv);
messageStatusIcon = itemView.findViewById(R.id.message_status_icon);
}
}
static class SearchMessageHeaderHolder extends RecyclerView.ViewHolder {
private View conversationLayout;
private ImageView conversationIcon;
private TextView conversationTitle;
public SearchMessageHeaderHolder(@NonNull View itemView) {
super(itemView);
conversationLayout = itemView.findViewById(R.id.conversation_layout);
conversationIcon = (ImageView) itemView.findViewById(R.id.icon_conversation);
conversationTitle = (TextView) itemView.findViewById(R.id.conversation_title);
}
}
private SpannableString matcherSearchText(int color, String text, String keyword) {
if (text == null || TextUtils.isEmpty(text)) {
return SpannableString.valueOf("");
}
SpannableString spannableString = new SpannableString(text);
Pattern pattern = Pattern.compile(Pattern.quote(keyword), Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(spannableString);
while (matcher.find()) {
int start = matcher.start();
int end = matcher.end();
spannableString.setSpan(new ForegroundColorSpan(color), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return spannableString;
}
}
@@ -0,0 +1,221 @@
package com.tencent.qcloud.tuikit.tuisearch.minimalistui.widget;
import android.animation.Animator;
import android.content.Context;
import android.graphics.Color;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
import com.tencent.qcloud.tuicore.TUIThemeManager;
import com.tencent.qcloud.tuikit.timcommon.component.impl.GlideEngine;
import com.tencent.qcloud.tuikit.timcommon.util.TUIUtil;
import com.tencent.qcloud.tuikit.tuisearch.R;
import com.tencent.qcloud.tuikit.tuisearch.TUISearchConstants;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import com.tencent.qcloud.tuikit.tuisearch.interfaces.ISearchResultAdapter;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SearchResultAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements ISearchResultAdapter {
private Context context;
private String text;
private int mViewType = -1;
private int mShowCount = 0;
private boolean mIsShowAll = false;
private int mTotalCount = 0;
// data list
private List<SearchDataBean> mDataList;
public void setText(String text) {
this.text = text;
}
public SearchResultAdapter(Context context) {
this.context = context;
}
public int getShowCount() {
if (mIsShowAll) {
return mShowCount;
} else {
if (mShowCount <= 3) {
return mShowCount;
} else {
return 3;
}
}
}
public void setShowCount(int mShowCount) {
this.mShowCount = mShowCount;
}
@Override
public void onIsShowAllChanged(boolean mIsShowAll) {
this.mIsShowAll = mIsShowAll;
}
public int getTotalCount() {
return mTotalCount;
}
@Override
public void onTotalCountChanged(int mTotalCount) {
this.mTotalCount = mTotalCount;
}
@Override
public void onDataSourceChanged(List<SearchDataBean> dataSource, int viewType) {
if (dataSource == null || dataSource.isEmpty()) {
if (mDataList != null) {
mDataList.clear();
mDataList = null;
}
setShowCount(0);
} else {
mDataList = dataSource;
setShowCount(mDataList.size());
}
mViewType = viewType;
notifyDataSetChanged();
}
public List<SearchDataBean> getDataSource() {
return mDataList;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ContactViewHolder holder = new ContactViewHolder(LayoutInflater.from(context).inflate(R.layout.minimalist_item_contact_search, parent, false));
return holder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
/*If there is no search operation or the delete button is clicked after the search, we will empty the text in MainActivity and pass it over.*/
ContactViewHolder contactViewHolder = (ContactViewHolder) holder;
if (contactViewHolder != null && mDataList != null && mDataList.size() > 0 && position < mDataList.size()) {
SearchDataBean searchDataBean = mDataList.get(position);
String title = searchDataBean.getTitle();
String subTitle = searchDataBean.getSubTitle();
String subTitleLabel = searchDataBean.getSubTitleLabel();
if (mViewType == TUISearchConstants.CONTACT_TYPE) {
subTitleLabel = holder.itemView.getResources().getString(R.string.search_ID_label);
title = searchDataBean.getSubTitle();
subTitle = searchDataBean.getTitle();
}
contactViewHolder.mSubTvLabelText.setText(subTitleLabel);
int avatarDefaultIconResID;
if (searchDataBean.isGroup()) {
avatarDefaultIconResID = TUIUtil.getDefaultGroupIconResIDByGroupType(context, searchDataBean.getGroupType());
} else {
avatarDefaultIconResID = TUIThemeManager.getAttrResId(
contactViewHolder.mUserIconView.getContext(), com.tencent.qcloud.tuikit.timcommon.R.attr.core_default_user_icon);
}
String path = searchDataBean.getIconPath();
GlideEngine.loadImageSetDefault(contactViewHolder.mUserIconView, path, avatarDefaultIconResID);
if (text != null) {
if (mViewType == TUISearchConstants.CONVERSATION_TYPE) {
contactViewHolder.mTvText.setText(title);
int isSubTextMatch = mDataList.get(position).getIsSubTextMatch();
if (isSubTextMatch == 1) {
SpannableString subString = matcherSearchText(Color.rgb(0, 0, 255), subTitle, text);
contactViewHolder.mSubTvText.setText(subString);
} else {
contactViewHolder.mSubTvText.setText(subTitle);
}
} else {
SpannableString string = matcherSearchText(Color.rgb(0, 0, 255), title, text);
contactViewHolder.mTvText.setText(string);
SpannableString subString = matcherSearchText(Color.rgb(0, 0, 255), subTitle, text);
contactViewHolder.mSubTvText.setText(subString);
}
} else {
contactViewHolder.mTvText.setText(title);
contactViewHolder.mSubTvText.setText(subTitle);
}
if (TextUtils.isEmpty(contactViewHolder.mSubTvText.getText())) {
contactViewHolder.mSubTvText.setVisibility(View.GONE);
contactViewHolder.mSubTvLabelText.setVisibility(View.GONE);
} else {
contactViewHolder.mSubTvText.setVisibility(View.VISIBLE);
contactViewHolder.mSubTvLabelText.setVisibility(View.VISIBLE);
}
contactViewHolder.mLlItem.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
onItemClickListener.onClick(view, position);
}
});
}
}
@Override
public int getItemCount() {
return getShowCount();
}
@Override
public int getItemViewType(int position) {
return mViewType;
}
public interface OnItemClickListener {
void onClick(View view, int pos);
}
private OnItemClickListener onItemClickListener;
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
class ContactViewHolder extends RecyclerView.ViewHolder {
private LinearLayout mLlItem;
private ImageView mUserIconView;
private TextView mTvText;
private TextView mSubTvText;
private TextView mSubTvLabelText;
public ContactViewHolder(View itemView) {
super(itemView);
mLlItem = itemView.findViewById(R.id.ll_item);
mUserIconView = itemView.findViewById(R.id.ivAvatar);
mTvText = itemView.findViewById(R.id.conversation_title);
mSubTvText = itemView.findViewById(R.id.conversation_sub_title);
mSubTvLabelText = itemView.findViewById(R.id.conversation_sub_title_label);
}
}
private SpannableString matcherSearchText(int color, String text, String keyword) {
if (text == null || TextUtils.isEmpty(text)) {
return SpannableString.valueOf("");
}
SpannableString spannableString = new SpannableString(text);
Pattern pattern = Pattern.compile(Pattern.quote(keyword), Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(spannableString);
while (matcher.find()) {
int start = matcher.start();
int end = matcher.end();
spannableString.setSpan(new ForegroundColorSpan(color), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return spannableString;
}
}
@@ -0,0 +1,358 @@
package com.tencent.qcloud.tuikit.tuisearch.model;
import android.text.SpannableString;
import android.text.TextUtils;
import android.util.Pair;
import com.tencent.imsdk.v2.V2TIMConversation;
import com.tencent.imsdk.v2.V2TIMFriendInfoResult;
import com.tencent.imsdk.v2.V2TIMFriendSearchParam;
import com.tencent.imsdk.v2.V2TIMGroupInfo;
import com.tencent.imsdk.v2.V2TIMGroupInfoResult;
import com.tencent.imsdk.v2.V2TIMGroupMemberFullInfo;
import com.tencent.imsdk.v2.V2TIMGroupMemberSearchParam;
import com.tencent.imsdk.v2.V2TIMGroupSearchParam;
import com.tencent.imsdk.v2.V2TIMManager;
import com.tencent.imsdk.v2.V2TIMMessage;
import com.tencent.imsdk.v2.V2TIMMessageSearchParam;
import com.tencent.imsdk.v2.V2TIMMessageSearchResult;
import com.tencent.imsdk.v2.V2TIMValueCallback;
import com.tencent.qcloud.tuicore.util.ErrorMessageConverter;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuisearch.bean.ChatInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.GroupInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.MessageInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBeanUtil;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchMessageBean;
import com.tencent.qcloud.tuikit.tuisearch.bean.TUISearchGroupParam;
import com.tencent.qcloud.tuikit.tuisearch.bean.TUISearchGroupResult;
import com.tencent.qcloud.tuikit.tuisearch.util.ConversationUtils;
import com.tencent.qcloud.tuikit.tuisearch.util.GroupInfoUtils;
import com.tencent.qcloud.tuikit.tuisearch.util.MessageInfoUtil;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchLog;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class SearchDataProvider {
private static final String TAG = SearchDataProvider.class.getSimpleName();
public static final int CONVERSATION_MESSAGE_PAGE_SIZE = 10;
public boolean groupInfoFinish = false;
public boolean groupMemberFullInfofinish = false;
/**
* group search
* @param searchParam
*
* @note
* - Support matching group information when searching, support matching group ID and group name, see @TUISearchGroupMatchField for details.
* - Support matching group member information when searching, support matching member ID, matching member nickname, matching member note, matching member
* business card, see @TUISearchGroupMemberMatchField for details
*/
public void searchGroups(final TUISearchGroupParam searchParam, final IUIKitCallback<List<TUISearchGroupResult>> callback) {
if (searchParam == null || searchParam.getKeywordList().size() == 0) {
TUISearchLog.e(TAG, "searchParam is null");
return;
}
final List<V2TIMGroupInfo> groupInfos = new ArrayList<>();
final HashMap<String, List<V2TIMGroupMemberFullInfo>> groupMemberFullInfos = new HashMap<String, List<V2TIMGroupMemberFullInfo>>();
// search group
V2TIMGroupSearchParam groupSearchParam = new V2TIMGroupSearchParam();
groupSearchParam.setKeywordList(searchParam.getKeywordList());
groupSearchParam.setSearchGroupID(searchParam.isSearchGroupID());
groupSearchParam.setSearchGroupName(searchParam.isSearchGroupName());
V2TIMManager.getGroupManager().searchGroups(groupSearchParam, new V2TIMValueCallback<List<V2TIMGroupInfo>>() {
@Override
public void onSuccess(List<V2TIMGroupInfo> v2TIMGroupInfos) {
TUISearchLog.d(TAG, "v2TIMGroupInfos.size() = " + v2TIMGroupInfos.size());
for (V2TIMGroupInfo v2TIMGroupInfo : v2TIMGroupInfos) {
groupInfos.add(v2TIMGroupInfo);
}
groupInfoFinish = true;
mergeGroupAndGroupMemberResult(searchParam.getKeywordList(), groupInfos, groupMemberFullInfos, callback);
}
@Override
public void onError(int code, String desc) {
TUISearchLog.e(TAG, "code = " + code + ", desc = " + ErrorMessageConverter.convertIMError(code, desc));
groupInfoFinish = true;
mergeGroupAndGroupMemberResult(searchParam.getKeywordList(), groupInfos, groupMemberFullInfos, callback);
}
});
// search group member
V2TIMGroupMemberSearchParam groupMemberSearchParam = new V2TIMGroupMemberSearchParam();
groupMemberSearchParam.setKeywordList(searchParam.getKeywordList());
groupMemberSearchParam.setSearchMemberUserID(searchParam.isSearchMemberUserID());
groupMemberSearchParam.setSearchMemberNickName(searchParam.isSearchMemberNickName());
groupMemberSearchParam.setSearchMemberNameCard(searchParam.isSearchMemberNameCard());
groupMemberSearchParam.setSearchMemberRemark(searchParam.isSearchMemberRemark());
V2TIMManager.getGroupManager().searchGroupMembers(groupMemberSearchParam, new V2TIMValueCallback<HashMap<String, List<V2TIMGroupMemberFullInfo>>>() {
@Override
public void onSuccess(HashMap<String, List<V2TIMGroupMemberFullInfo>> v2TIMGroupMemberInfoMap) {
if (v2TIMGroupMemberInfoMap == null || v2TIMGroupMemberInfoMap.isEmpty()) {
groupMemberFullInfos.clear();
groupMemberFullInfofinish = true;
mergeGroupAndGroupMemberResult(searchParam.getKeywordList(), groupInfos, groupMemberFullInfos, callback);
return;
}
TUISearchLog.d(TAG, "v2TIMGroupMemberInfoMap.size() = " + v2TIMGroupMemberInfoMap.size());
for (Map.Entry<String, List<V2TIMGroupMemberFullInfo>> entry : v2TIMGroupMemberInfoMap.entrySet()) {
groupMemberFullInfos.put(entry.getKey(), entry.getValue());
}
groupMemberFullInfofinish = true;
mergeGroupAndGroupMemberResult(searchParam.getKeywordList(), groupInfos, groupMemberFullInfos, callback);
}
@Override
public void onError(int code, String desc) {
TUISearchLog.e(TAG, "code = " + code + ", desc = " + ErrorMessageConverter.convertIMError(code, desc));
groupMemberFullInfofinish = true;
mergeGroupAndGroupMemberResult(searchParam.getKeywordList(), groupInfos, groupMemberFullInfos, callback);
}
});
}
public void searchContact(List<String> keywordList, IUIKitCallback<List<SearchDataBean>> callBack) {
V2TIMFriendSearchParam searchParam = new V2TIMFriendSearchParam();
searchParam.setKeywordList(keywordList);
searchParam.setSearchUserID(true);
searchParam.setSearchNickName(true);
searchParam.setSearchRemark(true);
V2TIMManager.getFriendshipManager().searchFriends(searchParam, new V2TIMValueCallback<List<V2TIMFriendInfoResult>>() {
@Override
public void onSuccess(List<V2TIMFriendInfoResult> v2TIMFriendInfoResults) {
List<SearchDataBean> searchDataBeanList = SearchDataBeanUtil.convertFriendInfos2SearchDataBeans(v2TIMFriendInfoResults);
TUISearchUtils.callbackOnSuccess(callBack, searchDataBeanList);
}
@Override
public void onError(int code, String desc) {
TUISearchUtils.callbackOnError(callBack, TAG, code, desc);
}
});
}
public void searchMessages(
final List<String> keywordList, String conversationId, int index, IUIKitCallback<Pair<Integer, List<SearchMessageBean>>> callBack) {
final V2TIMMessageSearchParam v2TIMMessageSearchParam = new V2TIMMessageSearchParam();
v2TIMMessageSearchParam.setKeywordList(keywordList);
v2TIMMessageSearchParam.setPageSize(CONVERSATION_MESSAGE_PAGE_SIZE);
v2TIMMessageSearchParam.setPageIndex(index);
if (!TextUtils.isEmpty(conversationId)) {
v2TIMMessageSearchParam.setConversationID(conversationId);
}
V2TIMManager.getMessageManager().searchLocalMessages(v2TIMMessageSearchParam, new V2TIMValueCallback<V2TIMMessageSearchResult>() {
@Override
public void onSuccess(V2TIMMessageSearchResult v2TIMMessageSearchResult) {
List<SearchMessageBean> searchMessageBeanList =
SearchDataBeanUtil.convertSearchResultItems2SearchMessageBeans(v2TIMMessageSearchResult.getMessageSearchResultItems());
TUISearchUtils.callbackOnSuccess(callBack, new Pair<>(v2TIMMessageSearchResult.getTotalCount(), searchMessageBeanList));
}
@Override
public void onError(int code, String desc) {
TUISearchLog.e(TAG, "searchMessages code = " + code + ", desc = " + ErrorMessageConverter.convertIMError(code, desc));
TUISearchUtils.callbackOnError(callBack, TAG, code, desc);
}
});
}
public void getConversationList(List<String> conversationIdList, IUIKitCallback<List<ConversationInfo>> callBack) {
V2TIMManager.getConversationManager().getConversationList(conversationIdList, new V2TIMValueCallback<List<V2TIMConversation>>() {
@Override
public void onSuccess(List<V2TIMConversation> v2TIMConversationList) {
List<ConversationInfo> conversationInfoList = ConversationUtils.convertV2TIMConversationList(v2TIMConversationList);
TUISearchUtils.callbackOnSuccess(callBack, conversationInfoList);
}
@Override
public void onError(int code, String desc) {
TUISearchLog.e(TAG, "getConversation code = " + code + ", desc = " + ErrorMessageConverter.convertIMError(code, desc));
TUISearchUtils.callbackOnError(callBack, code, desc);
}
});
}
public String getMessageText(MessageInfo messageInfo) {
String text = "";
if (messageInfo != null && messageInfo.getTimMessage().getElemType() != V2TIMMessage.V2TIM_ELEM_TYPE_GROUP_TIPS) {
text = (String) messageInfo.getExtra();
}
return text;
}
private static boolean matcherSearchText(String text, List<String> keywordList) {
if (text == null || TextUtils.isEmpty(text) || keywordList == null || keywordList.size() == 0) {
return false;
}
String keyword = keywordList.get(0);
// return text.toLowerCase().contains(keyword.toLowerCase());
SpannableString spannableString = new SpannableString(text);
Pattern pattern = Pattern.compile(Pattern.quote(keyword), Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(spannableString);
while (matcher.find()) {
return true;
}
return false;
}
private void mergeGroupAndGroupMemberResult(List<String> keywordList, List<V2TIMGroupInfo> groupInfos,
HashMap<String, List<V2TIMGroupMemberFullInfo>> groupMemberFullInfos, final IUIKitCallback<List<TUISearchGroupResult>> callback) {
if (!groupInfoFinish || !groupMemberFullInfofinish) {
return;
}
groupInfoFinish = false;
groupMemberFullInfofinish = false;
if ((groupInfos == null || groupInfos.size() == 0) && (groupMemberFullInfos == null || groupMemberFullInfos.size() == 0)) {
if (callback != null) {
callback.onSuccess(new ArrayList<TUISearchGroupResult>());
}
return;
}
final List<TUISearchGroupResult> searchGroupResults = new ArrayList<>();
TUISearchLog.d(
TAG, "mergeGroupAndGroupMemberResult groupInfos.size() =" + groupInfos.size() + "groupMemberFullInfos.size() = " + groupMemberFullInfos.size());
// GroupInfo
if (groupInfos != null && groupInfos.size() != 0) {
for (V2TIMGroupInfo v2TIMGroupInfo : groupInfos) {
// Assemble the matched group information data
TUISearchGroupResult searchGroupResult = new TUISearchGroupResult();
GroupInfo groupInfo = GroupInfoUtils.convertTimGroupInfo2GroupInfo(v2TIMGroupInfo);
searchGroupResult.setGroupInfo(groupInfo);
if (matcherSearchText(v2TIMGroupInfo.getGroupName(), keywordList)) {
searchGroupResult.setMatchField(TUISearchGroupParam.TUISearchGroupMatchField.SEARCH_FIELD_GROUP_NAME);
searchGroupResult.setMatchValue(v2TIMGroupInfo.getGroupName());
} else if (matcherSearchText(v2TIMGroupInfo.getGroupID(), keywordList)) {
searchGroupResult.setMatchField(TUISearchGroupParam.TUISearchGroupMatchField.SEARCH_FIELD_GROUP_ID);
searchGroupResult.setMatchValue(v2TIMGroupInfo.getGroupID());
} else {
TUISearchLog.d(TAG, "groupInfos have not matched, group id is " + v2TIMGroupInfo.getGroupID());
searchGroupResult.setMatchField(TUISearchGroupParam.TUISearchGroupMatchField.SEARCH_FIELD_GROUP_NONE);
searchGroupResult.setMatchValue("");
}
searchGroupResults.add(searchGroupResult);
// Remove data matching group information in groupMemberFullInfos
Iterator iterator = groupMemberFullInfos.keySet().iterator();
while (iterator.hasNext()) {
String key = (String) iterator.next();
if (v2TIMGroupInfo.getGroupID().equals(key)) {
iterator.remove();
// groupMemberFullInfos.remove(key);
}
}
}
}
TUISearchLog.d(TAG, "mergeGroupAndGroupMemberResult remove repeat, groupMemberFullInfos.size() = " + groupMemberFullInfos.size());
// GroupMemberFullInfo
List<String> groupIDList = new ArrayList<>();
final HashMap<String, TUISearchGroupResult> searchGroupMemberResults = new HashMap<>();
for (Map.Entry<String, List<V2TIMGroupMemberFullInfo>> entry : groupMemberFullInfos.entrySet()) {
String groupId = entry.getKey();
groupIDList.add(groupId);
// Traverse the remaining matched groupMemberFullInfos and fill in the result data
TUISearchGroupResult searchGroupResult = new TUISearchGroupResult();
searchGroupResult.setMatchField(TUISearchGroupParam.TUISearchGroupMatchField.SEARCH_FIELD_GROUP_NONE);
searchGroupResult.setMatchValue("");
// fill group member data
List<TUISearchGroupResult.TUISearchGroupMemberMatchResult> matchMembers = new ArrayList<>();
for (V2TIMGroupMemberFullInfo v2TIMGroupMemberFullInfo : entry.getValue()) {
TUISearchGroupResult.TUISearchGroupMemberMatchResult searchGroupMemberMatchResult = new TUISearchGroupResult.TUISearchGroupMemberMatchResult();
if (matcherSearchText(v2TIMGroupMemberFullInfo.getNameCard(), keywordList)) {
searchGroupMemberMatchResult.setMemberMatchField(TUISearchGroupParam.TUISearchGroupMemberMatchField.SEARCH_FIELD_MEMBER_NAME_CARD);
searchGroupMemberMatchResult.setMemberMatchValue(v2TIMGroupMemberFullInfo.getNameCard());
} else if (matcherSearchText(v2TIMGroupMemberFullInfo.getFriendRemark(), keywordList)) {
searchGroupMemberMatchResult.setMemberMatchField(TUISearchGroupParam.TUISearchGroupMemberMatchField.SEARCH_FIELD_MEMBER_REMARK);
searchGroupMemberMatchResult.setMemberMatchValue(v2TIMGroupMemberFullInfo.getFriendRemark());
} else if (matcherSearchText(v2TIMGroupMemberFullInfo.getNickName(), keywordList)) {
searchGroupMemberMatchResult.setMemberMatchField(TUISearchGroupParam.TUISearchGroupMemberMatchField.SEARCH_FIELD_MEMBER_NICK_NAME);
searchGroupMemberMatchResult.setMemberMatchValue(v2TIMGroupMemberFullInfo.getNickName());
} else if (matcherSearchText(v2TIMGroupMemberFullInfo.getUserID(), keywordList)) {
searchGroupMemberMatchResult.setMemberMatchField(TUISearchGroupParam.TUISearchGroupMemberMatchField.SEARCH_FIELD_MEMBER_USER_ID);
searchGroupMemberMatchResult.setMemberMatchValue(v2TIMGroupMemberFullInfo.getUserID());
} else {
TUISearchLog.d(TAG, "groupMemberFullInfos have not matched, user id is " + v2TIMGroupMemberFullInfo.getUserID());
searchGroupMemberMatchResult.setMemberMatchField(TUISearchGroupParam.TUISearchGroupMemberMatchField.SEARCH_FIELD_MEMBER_NONE);
searchGroupMemberMatchResult.setMemberMatchValue("");
}
matchMembers.add(searchGroupMemberMatchResult);
}
searchGroupResult.setMatchMembers(matchMembers);
// In the temporary storage of group member data searchGroupMemberResults, the groupInfo information is missing
searchGroupMemberResults.put(groupId, searchGroupResult);
}
TUISearchLog.d(TAG, "mergeGroupAndGroupMemberResult searchGroupMemberResults.size() = " + searchGroupMemberResults.size());
V2TIMManager.getGroupManager().getGroupsInfo(groupIDList, new V2TIMValueCallback<List<V2TIMGroupInfoResult>>() {
@Override
public void onError(int code, String desc) {
TUISearchLog.e(TAG, "getGroupsInfo failed, code: " + code + "|desc: " + ErrorMessageConverter.convertIMError(code, desc));
if (callback != null) {
callback.onSuccess(searchGroupResults);
}
}
@Override
public void onSuccess(List<V2TIMGroupInfoResult> v2TIMGroupInfoResults) {
if (v2TIMGroupInfoResults != null && v2TIMGroupInfoResults.size() > 0) {
for (V2TIMGroupInfoResult v2TIMGroupInfoResult : v2TIMGroupInfoResults) {
TUISearchGroupResult searchGroupResult = searchGroupMemberResults.get(v2TIMGroupInfoResult.getGroupInfo().getGroupID());
if (searchGroupResult != null) {
searchGroupResult.setGroupInfo(GroupInfoUtils.convertTimGroupInfo2GroupInfo(v2TIMGroupInfoResult.getGroupInfo()));
searchGroupResults.add(searchGroupResult);
} else {
TUISearchLog.e(TAG,
"getGroupsInfo not searchGroupMemberResults.get(v2TIMGroupInfoResult.getGroupInfo().getGroupID(): "
+ v2TIMGroupInfoResult.getGroupInfo().getGroupID());
}
}
TUISearchLog.d(TAG, "mergeGroupAndGroupMemberResult callback.onSuccess searchGroupResults.size() = " + searchGroupResults.size());
if (callback != null) {
callback.onSuccess(searchGroupResults);
}
}
}
});
}
public ChatInfo generateChatInfo(SearchDataBean searchDataBean) {
ChatInfo chatInfo = new ChatInfo();
if (searchDataBean.isGroup()) {
chatInfo.setType(V2TIMConversation.V2TIM_GROUP);
chatInfo.setId(searchDataBean.getGroupID());
} else {
chatInfo.setType(V2TIMConversation.V2TIM_C2C);
chatInfo.setId(searchDataBean.getUserID());
}
chatInfo.setLocateMessage(MessageInfoUtil.convertTIMMessage2MessageInfo(searchDataBean.getLocateTimMessage()));
chatInfo.getLocateMessage().setFaceUrl(searchDataBean.getIconPath());
return chatInfo;
}
}
@@ -0,0 +1,296 @@
package com.tencent.qcloud.tuikit.tuisearch.presenter;
import android.text.TextUtils;
import android.util.Pair;
import com.tencent.qcloud.tuicore.ServiceInitializer;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuisearch.R;
import com.tencent.qcloud.tuikit.tuisearch.TUISearchConstants;
import com.tencent.qcloud.tuikit.tuisearch.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.GroupInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchMessageBean;
import com.tencent.qcloud.tuikit.tuisearch.bean.TUISearchGroupParam;
import com.tencent.qcloud.tuikit.tuisearch.bean.TUISearchGroupResult;
import com.tencent.qcloud.tuikit.tuisearch.interfaces.ISearchResultAdapter;
import com.tencent.qcloud.tuikit.tuisearch.model.SearchDataProvider;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchLog;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchUtils;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class SearchMainPresenter {
private static final String TAG = SearchMainPresenter.class.getSimpleName();
private final SearchDataProvider groupProvider;
private final SearchDataProvider contactProvider;
private final SearchDataProvider conversationProvider;
private ISearchResultAdapter contactAdapter;
private ISearchResultAdapter groupAdapter;
private ISearchResultAdapter conversationAdapter;
private final Set<String> conversationSearchIdSet = new HashSet<>();
private final List<SearchDataBean> conversationSearchDataBeans = new ArrayList<>();
private final Map<String, SearchMessageBean> msgCountInConversationMap = new HashMap<>();
public SearchMainPresenter() {
groupProvider = new SearchDataProvider();
contactProvider = new SearchDataProvider();
conversationProvider = new SearchDataProvider();
}
public void setContactAdapter(ISearchResultAdapter contactAdapter) {
this.contactAdapter = contactAdapter;
}
public void setGroupAdapter(ISearchResultAdapter groupAdapter) {
this.groupAdapter = groupAdapter;
}
public void setConversationAdapter(ISearchResultAdapter conversationAdapter) {
this.conversationAdapter = conversationAdapter;
}
public void searchContact(final List<String> keywordList, final IUIKitCallback<List<SearchDataBean>> callback) {
if (keywordList == null || keywordList.size() == 0 || contactAdapter == null) {
TUISearchLog.e(TAG, "param is null");
return;
}
final List<SearchDataBean> contactSearchDataList = new ArrayList<>();
// search contact
contactProvider.searchContact(keywordList, new IUIKitCallback<List<SearchDataBean>>() {
@Override
public void onSuccess(List<SearchDataBean> searchDataBeanList) {
if (searchDataBeanList == null || searchDataBeanList.isEmpty()) {
contactSearchDataList.clear();
TUISearchLog.d(TAG, "searchFriends is null, mContactSearchData.size() = " + contactSearchDataList.size());
contactAdapter.onDataSourceChanged(null, TUISearchConstants.CONTACT_TYPE);
if (callback != null) {
callback.onSuccess(contactSearchDataList);
}
return;
}
for (int i = 0; i < searchDataBeanList.size(); i++) {
SearchDataBean searchDataBean = searchDataBeanList.get(i);
SearchDataBean dataBean = new SearchDataBean();
dataBean.setIconPath(searchDataBean.getIconPath());
dataBean.setTitle(searchDataBean.getUserID());
dataBean.setSubTitleLabel(ServiceInitializer.getAppContext().getString(R.string.nick_name));
if (!TextUtils.isEmpty(searchDataBean.getRemark())) {
dataBean.setSubTitle(searchDataBean.getRemark());
} else if (!TextUtils.isEmpty(searchDataBean.getNickName())) {
dataBean.setSubTitle(searchDataBean.getNickName());
} else if (!TextUtils.isEmpty(searchDataBean.getUserID())) {
dataBean.setSubTitle(searchDataBean.getUserID());
}
dataBean.setType(TUISearchConstants.CONTACT_TYPE);
dataBean.setUserID(searchDataBean.getUserID());
dataBean.setNickName(searchDataBean.getNickName());
dataBean.setRemark(searchDataBean.getRemark());
contactSearchDataList.add(dataBean);
}
contactAdapter.onDataSourceChanged(contactSearchDataList, TUISearchConstants.CONTACT_TYPE);
if (callback != null) {
callback.onSuccess(contactSearchDataList);
}
}
@Override
public void onError(String module, int errCode, String errMsg) {
TUISearchLog.e(TAG, "code = " + errCode + ", desc = " + errMsg);
if (callback != null) {
callback.onSuccess(contactSearchDataList);
}
}
});
}
public void searchGroup(final List<String> keywordList, final IUIKitCallback<List<SearchDataBean>> callback) {
if (keywordList == null || keywordList.size() == 0 || groupAdapter == null) {
TUISearchLog.e(TAG, "param is null");
return;
}
final List<SearchDataBean> groupSearchDataList = new ArrayList<>();
TUISearchGroupParam searchParam = new TUISearchGroupParam();
searchParam.setKeywordList(keywordList);
searchParam.setSearchGroupID(true);
searchParam.setSearchGroupName(true);
searchParam.setSearchMemberUserID(true);
searchParam.setSearchMemberNickName(true);
searchParam.setSearchMemberNameCard(true);
searchParam.setSearchMemberRemark(true);
groupProvider.searchGroups(searchParam, new IUIKitCallback<List<TUISearchGroupResult>>() {
@Override
public void onSuccess(List<TUISearchGroupResult> tuiSearchGroupResults) {
groupSearchDataList.clear();
if (tuiSearchGroupResults == null || tuiSearchGroupResults.isEmpty()) {
TUISearchLog.d(TAG, "searchGroups is null, tuiSearchGroupResults.size() = " + tuiSearchGroupResults.size());
groupAdapter.onDataSourceChanged(null, TUISearchConstants.GROUP_TYPE);
if (callback != null) {
callback.onSuccess(groupSearchDataList);
}
return;
}
TUISearchLog.d(TAG, "tuiSearchGroupResults.size() = " + tuiSearchGroupResults.size());
for (int i = 0; i < tuiSearchGroupResults.size(); i++) {
TUISearchGroupResult searchGroupResult = tuiSearchGroupResults.get(i);
SearchDataBean dataBean = new SearchDataBean();
GroupInfo groupInfo = searchGroupResult.getGroupInfo();
String groupId = groupInfo.getId();
dataBean.setGroupID(groupId);
dataBean.setGroup(true);
dataBean.setGroupName(groupInfo.getGroupName());
dataBean.setGroupType(groupInfo.getGroupType());
dataBean.setRemark(groupInfo.getGroupName());
dataBean.setIconPath(groupInfo.getFaceUrl());
if (searchGroupResult.getMatchField() == TUISearchGroupParam.TUISearchGroupMatchField.SEARCH_FIELD_GROUP_ID) {
dataBean.setTitle(groupInfo.getGroupName());
dataBean.setSubTitleLabel(ServiceInitializer.getAppContext().getString(R.string.include_group_id));
dataBean.setSubTitle(groupId);
} else if (searchGroupResult.getMatchField() == TUISearchGroupParam.TUISearchGroupMatchField.SEARCH_FIELD_GROUP_NAME) {
dataBean.setTitle(groupInfo.getGroupName());
} else {
dataBean.setTitle(groupInfo.getGroupName());
if (searchGroupResult.getMatchMembers() != null && !searchGroupResult.getMatchMembers().isEmpty()) {
TUISearchGroupResult.TUISearchGroupMemberMatchResult searchGroupMemberMatchResult = searchGroupResult.getMatchMembers().get(0);
if (searchGroupMemberMatchResult.getMemberMatchField()
!= TUISearchGroupParam.TUISearchGroupMemberMatchField.SEARCH_FIELD_MEMBER_NONE) {
dataBean.setSubTitleLabel(ServiceInitializer.getAppContext().getString(R.string.include_group_member));
dataBean.setSubTitle(searchGroupMemberMatchResult.getMemberMatchValue());
} else {
dataBean.setSubTitle("");
}
}
}
dataBean.setType(TUISearchConstants.GROUP_TYPE);
groupSearchDataList.add(dataBean);
}
groupAdapter.onDataSourceChanged(groupSearchDataList, TUISearchConstants.GROUP_TYPE);
if (callback != null) {
callback.onSuccess(groupSearchDataList);
}
}
@Override
public void onError(String module, int code, String desc) {
groupAdapter.onDataSourceChanged(groupSearchDataList, TUISearchConstants.GROUP_TYPE);
if (callback != null) {
callback.onSuccess(groupSearchDataList);
}
}
});
}
public void searchConversation(final List<String> keywordList, int pageIndex, IUIKitCallback<List<SearchDataBean>> callback) {
if (keywordList == null || keywordList.size() <= 0 || conversationAdapter == null) {
return;
}
conversationProvider.searchMessages(keywordList, null, pageIndex, new IUIKitCallback<Pair<Integer, List<SearchMessageBean>>>() {
@Override
public void onSuccess(Pair<Integer, List<SearchMessageBean>> data) {
List<SearchMessageBean> searchMessageBeanList = data.second;
int totalCount = data.first;
if (pageIndex == 0) {
conversationSearchIdSet.clear();
msgCountInConversationMap.clear();
if (totalCount == 0) {
conversationAdapter.onDataSourceChanged(conversationSearchDataBeans, TUISearchConstants.CONVERSATION_TYPE);
TUISearchUtils.callbackOnError(callback, -1, "search conversation , total count is 0");
return;
}
}
conversationAdapter.onTotalCountChanged(totalCount);
List<String> conversationIdList = new ArrayList<>();
for (SearchMessageBean searchMessageBean : searchMessageBeanList) {
if (conversationSearchIdSet.contains(searchMessageBean.getConversationId())) {
continue;
}
conversationIdList.add(searchMessageBean.getConversationId());
msgCountInConversationMap.put(searchMessageBean.getConversationId(), searchMessageBean);
}
if (conversationIdList.isEmpty()) {
TUISearchUtils.callbackOnSuccess(callback, conversationSearchDataBeans);
return;
}
conversationProvider.getConversationList(conversationIdList, new IUIKitCallback<List<ConversationInfo>>() {
@Override
public void onSuccess(List<ConversationInfo> conversationInfoList) {
if (pageIndex == 0) {
conversationSearchDataBeans.clear();
}
for (ConversationInfo conversationInfo : conversationInfoList) {
SearchDataBean searchDataBean = new SearchDataBean();
searchDataBean.setConversationID(conversationInfo.getConversationId());
searchDataBean.setUserID(conversationInfo.getId());
searchDataBean.setGroupID(conversationInfo.getId());
searchDataBean.setGroup(conversationInfo.isGroup());
searchDataBean.setGroupType(conversationInfo.getGroupType());
searchDataBean.setIconPath(conversationInfo.getIconPath());
searchDataBean.setTitle(conversationInfo.getTitle());
conversationSearchDataBeans.add(searchDataBean);
conversationSearchIdSet.add(searchDataBean.getConversationID());
}
TUISearchLog.i(TAG, "searchDataBeans.size() = " + conversationSearchDataBeans.size());
TUISearchLog.i(TAG, "mMsgsInConversationMap.size() = " + msgCountInConversationMap.size());
if (conversationSearchDataBeans.size() > 0) {
for (int i = 0; i < conversationSearchDataBeans.size(); i++) {
SearchMessageBean searchMessageBean = msgCountInConversationMap.get(conversationSearchDataBeans.get(i).getConversationID());
if (searchMessageBean != null) {
int count = searchMessageBean.getMessageCount();
if (count == 1) {
conversationSearchDataBeans.get(i).setSubTitle(
conversationProvider.getMessageText(searchMessageBean.getMessageInfoList().get(0)));
conversationSearchDataBeans.get(i).setSubTextMatch(1);
} else if (count > 1) {
conversationSearchDataBeans.get(i).setSubTitle(
count + ServiceInitializer.getAppContext().getString(R.string.chat_records));
conversationSearchDataBeans.get(i).setSubTextMatch(0);
}
}
}
}
conversationAdapter.onDataSourceChanged(conversationSearchDataBeans, TUISearchConstants.CONVERSATION_TYPE);
TUISearchUtils.callbackOnSuccess(callback, conversationSearchDataBeans);
}
@Override
public void onError(String module, int errCode, String errMsg) {
conversationAdapter.onDataSourceChanged(conversationSearchDataBeans, TUISearchConstants.CONVERSATION_TYPE);
TUISearchUtils.callbackOnError(callback, module, errCode, errMsg);
}
});
}
@Override
public void onError(String module, int errCode, String errMsg) {
conversationAdapter.onDataSourceChanged(conversationSearchDataBeans, TUISearchConstants.CONVERSATION_TYPE);
conversationAdapter.onTotalCountChanged(conversationSearchDataBeans.size());
TUISearchUtils.callbackOnError(callback, module, errCode, errMsg);
}
});
}
}
@@ -0,0 +1,130 @@
package com.tencent.qcloud.tuikit.tuisearch.presenter;
import android.text.TextUtils;
import android.util.Pair;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
import com.tencent.qcloud.tuikit.tuisearch.bean.ChatInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.MessageInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchDataBean;
import com.tencent.qcloud.tuikit.tuisearch.bean.SearchMessageBean;
import com.tencent.qcloud.tuikit.tuisearch.interfaces.ISearchMoreMsgAdapter;
import com.tencent.qcloud.tuikit.tuisearch.model.SearchDataProvider;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchLog;
import com.tencent.qcloud.tuikit.tuisearch.util.TUISearchUtils;
import java.util.ArrayList;
import java.util.List;
public class SearchMoreMsgPresenter {
private static final String TAG = SearchMoreMsgPresenter.class.getSimpleName();
private final SearchDataProvider provider;
private ISearchMoreMsgAdapter adapter;
private final List<SearchDataBean> searchDataBeanList = new ArrayList<>();
public SearchMoreMsgPresenter() {
provider = new SearchDataProvider();
}
public void setAdapter(ISearchMoreMsgAdapter adapter) {
this.adapter = adapter;
}
private boolean isLoad = false;
public void searchMessage(List<String> keywordList, String conversationId, int pageIndex, IUIKitCallback<List<SearchDataBean>> callback) {
if (isLoad) {
return;
}
TUISearchLog.d(TAG, "searchMessage() index = " + pageIndex);
final boolean isGetByPage = pageIndex > 0;
isLoad = true;
provider.searchMessages(keywordList, conversationId, pageIndex, new IUIKitCallback<Pair<Integer, List<SearchMessageBean>>>() {
@Override
public void onSuccess(Pair<Integer, List<SearchMessageBean>> data) {
List<SearchMessageBean> searchMessageBeanList = data.second;
int totalCount = data.first;
if (!isGetByPage) {
searchDataBeanList.clear();
}
if (searchMessageBeanList.size() == 0) {
TUISearchLog.i(TAG, "searchMessages searchMessageBeanList is empty");
if (!isGetByPage) {
adapter.onDataSourceChanged(searchDataBeanList);
adapter.onTotalCountChanged(totalCount);
}
TUISearchUtils.callbackOnSuccess(callback, searchDataBeanList);
isLoad = false;
return;
}
adapter.onTotalCountChanged(searchMessageBeanList.size());
List<MessageInfo> messageInfoList = searchMessageBeanList.get(0).getMessageInfoList();
if (!isGetByPage && (messageInfoList == null || messageInfoList.isEmpty())) {
TUISearchLog.i(TAG, "searchMessages is null, messageInfoList.size() = " + messageInfoList.size());
adapter.onDataSourceChanged(searchDataBeanList);
adapter.onTotalCountChanged(totalCount);
TUISearchUtils.callbackOnSuccess(callback, searchDataBeanList);
isLoad = false;
return;
}
if (messageInfoList != null && !messageInfoList.isEmpty()) {
for (MessageInfo message : messageInfoList) {
SearchDataBean searchDataBean = new SearchDataBean();
String title = "";
if (!TextUtils.isEmpty(message.getFriendRemark())) {
title = message.getFriendRemark();
} else if (!TextUtils.isEmpty(message.getNameCard())) {
title = message.getNameCard();
} else if (!TextUtils.isEmpty(message.getNickName())) {
title = message.getNickName();
} else {
title = message.getFromUser();
}
String subTitle = provider.getMessageText(message);
String path = message.getFaceUrl();
searchDataBean.setTitle(title);
searchDataBean.setSubTitle(subTitle);
searchDataBean.setIconPath(path);
searchDataBean.setUserID(message.getUserId());
searchDataBean.setGroupID(message.getGroupId());
searchDataBean.setGroup(message.isGroup());
searchDataBean.setIconPath(message.getFaceUrl());
searchDataBean.setLocateTimMessage(message.getTimMessage());
searchDataBeanList.add(searchDataBean);
}
TUISearchUtils.callbackOnSuccess(callback, searchDataBeanList);
adapter.onDataSourceChanged(searchDataBeanList);
adapter.onTotalCountChanged(totalCount);
}
isLoad = false;
}
@Override
public void onError(String module, int errCode, String errMsg) {
TUISearchLog.e(TAG, "searchMessages code = " + errCode + ", desc = " + errMsg);
if (!isGetByPage) {
searchDataBeanList.clear();
adapter.onDataSourceChanged(null);
adapter.onTotalCountChanged(0);
}
TUISearchUtils.callbackOnError(callback, module, errCode, errMsg);
isLoad = false;
}
});
}
public ChatInfo generateChatInfo(SearchDataBean searchDataBean) {
return provider.generateChatInfo(searchDataBean);
}
}
@@ -0,0 +1,212 @@
package com.tencent.qcloud.tuikit.tuisearch.util;
import android.text.TextUtils;
import com.tencent.imsdk.v2.V2TIMConversation;
import com.tencent.imsdk.v2.V2TIMGroupAtInfo;
import com.tencent.imsdk.v2.V2TIMGroupMemberFullInfo;
import com.tencent.imsdk.v2.V2TIMGroupMemberInfoResult;
import com.tencent.imsdk.v2.V2TIMManager;
import com.tencent.imsdk.v2.V2TIMMessage;
import com.tencent.imsdk.v2.V2TIMValueCallback;
import com.tencent.qcloud.tuicore.ServiceInitializer;
import com.tencent.qcloud.tuicore.TUILogin;
import com.tencent.qcloud.tuicore.TUIThemeManager;
import com.tencent.qcloud.tuicore.util.SPUtils;
import com.tencent.qcloud.tuikit.timcommon.util.DateTimeUtil;
import com.tencent.qcloud.tuikit.tuisearch.R;
import com.tencent.qcloud.tuikit.tuisearch.bean.ConversationInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.DraftInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.MessageInfo;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class ConversationUtils {
private static final String TAG = ConversationUtils.class.getSimpleName();
public static final String SP_IMAGE = "_conversation_group_face";
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;
}
TUISearchLog.i(TAG,
"TIMConversation2ConversationInfo id:" + conversation.getConversationID() + "|name:" + conversation.getShowName()
+ "|unreadNum:" + conversation.getUnreadCount());
final ConversationInfo info = new ConversationInfo();
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());
}
MessageInfo messageInfo = MessageInfoUtil.convertTIMMessage2MessageInfo(message);
if (messageInfo != null) {
info.setLastMessage(messageInfo);
}
int atInfoType = getAtInfoType(conversation);
switch (atInfoType) {
case V2TIMGroupAtInfo.TIM_AT_ME:
info.setAtInfoText(ServiceInitializer.getAppContext().getString(R.string.ui_at_me));
break;
case V2TIMGroupAtInfo.TIM_AT_ALL:
info.setAtInfoText(ServiceInitializer.getAppContext().getString(R.string.ui_at_all));
break;
case V2TIMGroupAtInfo.TIM_AT_ALL_AT_ME:
info.setAtInfoText(ServiceInitializer.getAppContext().getString(R.string.ui_at_all_me));
break;
default:
info.setAtInfoText("");
break;
}
boolean isGroup = type == V2TIMConversation.V2TIM_GROUP;
info.setTitle(conversation.getShowName());
if (isGroup) {
fillConversationUrlForGroup(conversation, info);
} else {
List<Object> faceList = new ArrayList<>();
if (TextUtils.isEmpty(conversation.getFaceUrl())) {
faceList.add(
TUIThemeManager.getAttrResId(ServiceInitializer.getAppContext(), com.tencent.qcloud.tuikit.timcommon.R.attr.core_default_user_icon));
} 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());
}
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());
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;
}
private static void fillConversationUrlForGroup(final V2TIMConversation conversation, final ConversationInfo info) {
if (TextUtils.isEmpty(conversation.getFaceUrl())) {
final String savedIcon = getGroupConversationAvatar(conversation.getConversationID());
if (TextUtils.isEmpty(savedIcon)) {
fillFaceUrlList(conversation.getGroupID(), info);
} else {
List<Object> list = new ArrayList<>();
list.add(savedIcon);
info.setIconUrlList(list);
}
} else {
List<Object> list = new ArrayList<>();
list.add(conversation.getFaceUrl());
info.setIconUrlList(list);
}
}
private static void fillFaceUrlList(final String groupID, final ConversationInfo info) {
V2TIMManager.getGroupManager().getGroupMemberList(
groupID, V2TIMGroupMemberFullInfo.V2TIM_GROUP_MEMBER_FILTER_ALL, 0, new V2TIMValueCallback<V2TIMGroupMemberInfoResult>() {
@Override
public void onError(int code, String desc) {
TUISearchLog.e(TAG, "getGroupMemberList failed! groupID:" + groupID + "|code:" + code + "|desc: " + desc);
}
@Override
public void onSuccess(V2TIMGroupMemberInfoResult v2TIMGroupMemberInfoResult) {
List<V2TIMGroupMemberFullInfo> v2TIMGroupMemberFullInfoList = v2TIMGroupMemberInfoResult.getMemberInfoList();
int faceSize = v2TIMGroupMemberFullInfoList.size() > 9 ? 9 : v2TIMGroupMemberFullInfoList.size();
List<Object> urlList = new ArrayList<>();
for (int i = 0; i < faceSize; i++) {
V2TIMGroupMemberFullInfo v2TIMGroupMemberFullInfo = v2TIMGroupMemberFullInfoList.get(i);
if (TextUtils.isEmpty(v2TIMGroupMemberFullInfo.getFaceUrl())) {
urlList.add(TUIThemeManager.getAttrResId(
ServiceInitializer.getAppContext(), com.tencent.qcloud.tuikit.timcommon.R.attr.core_default_user_icon));
} else {
urlList.add(v2TIMGroupMemberFullInfo.getFaceUrl());
}
}
info.setIconUrlList(urlList);
}
});
}
public static String getGroupConversationAvatar(String groupId) {
final String savedIcon = SPUtils.getInstance(TUILogin.getSdkAppId() + SP_IMAGE).getString(groupId);
if (!TextUtils.isEmpty(savedIcon) && new File(savedIcon).isFile() && new File(savedIcon).exists()) {
return savedIcon;
}
return "";
}
}
@@ -0,0 +1,21 @@
package com.tencent.qcloud.tuikit.tuisearch.util;
import com.tencent.imsdk.v2.V2TIMGroupInfo;
import com.tencent.qcloud.tuikit.tuisearch.bean.GroupInfo;
public class GroupInfoUtils {
public static GroupInfo convertTimGroupInfo2GroupInfo(V2TIMGroupInfo v2TIMGroupInfo) {
if (v2TIMGroupInfo == null) {
return null;
}
GroupInfo groupInfo = new GroupInfo();
groupInfo.setId(v2TIMGroupInfo.getGroupID());
groupInfo.setGroupName(v2TIMGroupInfo.getGroupName());
groupInfo.setGroupType(v2TIMGroupInfo.getGroupType());
groupInfo.setMemberCount(v2TIMGroupInfo.getMemberCount());
groupInfo.setOwner(v2TIMGroupInfo.getOwner());
groupInfo.setNotice(v2TIMGroupInfo.getNotification());
groupInfo.setFaceUrl(v2TIMGroupInfo.getFaceUrl());
return groupInfo;
}
}
@@ -0,0 +1,655 @@
package com.tencent.qcloud.tuikit.tuisearch.util;
import android.content.Context;
import android.net.Uri;
import android.text.TextUtils;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.tencent.imsdk.v2.V2TIMCustomElem;
import com.tencent.imsdk.v2.V2TIMDownloadCallback;
import com.tencent.imsdk.v2.V2TIMElem;
import com.tencent.imsdk.v2.V2TIMFaceElem;
import com.tencent.imsdk.v2.V2TIMFileElem;
import com.tencent.imsdk.v2.V2TIMGroupChangeInfo;
import com.tencent.imsdk.v2.V2TIMGroupMemberChangeInfo;
import com.tencent.imsdk.v2.V2TIMGroupMemberInfo;
import com.tencent.imsdk.v2.V2TIMGroupTipsElem;
import com.tencent.imsdk.v2.V2TIMImageElem;
import com.tencent.imsdk.v2.V2TIMManager;
import com.tencent.imsdk.v2.V2TIMMessage;
import com.tencent.imsdk.v2.V2TIMSignalingInfo;
import com.tencent.imsdk.v2.V2TIMSoundElem;
import com.tencent.imsdk.v2.V2TIMTextElem;
import com.tencent.imsdk.v2.V2TIMVideoElem;
import com.tencent.qcloud.tuicore.ServiceInitializer;
import com.tencent.qcloud.tuicore.TUIConfig;
import com.tencent.qcloud.tuicore.TUIConstants;
import com.tencent.qcloud.tuikit.timcommon.util.DateTimeUtil;
import com.tencent.qcloud.tuikit.timcommon.util.FileUtil;
import com.tencent.qcloud.tuikit.timcommon.util.ImageUtil;
import com.tencent.qcloud.tuikit.tuisearch.R;
import com.tencent.qcloud.tuikit.tuisearch.TUISearchConstants;
import com.tencent.qcloud.tuikit.tuisearch.bean.CallModel;
import com.tencent.qcloud.tuikit.tuisearch.bean.MessageInfo;
import com.tencent.qcloud.tuikit.tuisearch.message.MessageCustom;
import com.tencent.qcloud.tuikit.tuisearch.message.MessageTyping;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class MessageInfoUtil {
private static final String TAG = MessageInfoUtil.class.getSimpleName();
public static List<MessageInfo> convertTIMMessages2MessageInfos(List<V2TIMMessage> timMessages) {
if (timMessages == null) {
return null;
}
List<MessageInfo> messageInfos = new ArrayList<>();
for (int i = 0; i < timMessages.size(); i++) {
V2TIMMessage timMessage = timMessages.get(i);
MessageInfo info = convertTIMMessage2MessageInfo(timMessage);
if (info != null) {
messageInfos.add(info);
}
}
return messageInfos;
}
public static MessageInfo convertTIMMessage2MessageInfo(V2TIMMessage timMessage) {
if (timMessage == null || timMessage.getStatus() == V2TIMMessage.V2TIM_MSG_STATUS_HAS_DELETED
|| timMessage.getElemType() == V2TIMMessage.V2TIM_ELEM_TYPE_NONE) {
return null;
}
return createMessageInfo(timMessage);
}
public static boolean isTyping(byte[] data) {
try {
String str = new String(data, "UTF-8");
MessageTyping typing = new Gson().fromJson(str, MessageTyping.class);
if (typing != null && typing.userAction == MessageTyping.TYPE_TYPING && TextUtils.equals(typing.actionParam, MessageTyping.EDIT_START)) {
return true;
}
return false;
} catch (Exception e) {
TUISearchLog.e(TAG, "parse json error");
}
return false;
}
public static MessageInfo createMessageInfo(V2TIMMessage timMessage) {
if (timMessage == null || timMessage.getStatus() == V2TIMMessage.V2TIM_MSG_STATUS_HAS_DELETED
|| timMessage.getElemType() == V2TIMMessage.V2TIM_ELEM_TYPE_NONE) {
TUISearchLog.e(TAG, "ele2MessageInfo parameters error");
return null;
}
Context context = ServiceInitializer.getAppContext();
if (context == null) {
TUISearchLog.e(TAG, "context == null");
return new MessageInfo();
}
final MessageInfo msgInfo;
int type = timMessage.getElemType();
if (type == V2TIMMessage.V2TIM_ELEM_TYPE_CUSTOM) {
msgInfo = createCustomMessageInfo(timMessage, context);
} else if (type == V2TIMMessage.V2TIM_ELEM_TYPE_GROUP_TIPS) {
msgInfo = createGroupTipsMessageInfo(timMessage, context);
} else {
msgInfo = createNormalMessageInfo(timMessage, context, type);
}
if (msgInfo == null) {
return null;
}
if (timMessage.getStatus() == V2TIMMessage.V2TIM_MSG_STATUS_LOCAL_REVOKED) {
msgInfo.setStatus(MessageInfo.MSG_STATUS_REVOKE);
msgInfo.setMsgType(MessageInfo.MSG_STATUS_REVOKE);
if (msgInfo.isSelf()) {
msgInfo.setExtra(context.getString(R.string.revoke_tips_you));
} else if (msgInfo.isGroup()) {
String message = TUISearchConstants.covert2HTMLString(msgInfo.getFromUser());
msgInfo.setExtra(message + context.getString(R.string.revoke_tips));
} else {
msgInfo.setExtra(context.getString(R.string.revoke_tips_other));
}
} else {
if (msgInfo.isSelf()) {
if (timMessage.getStatus() == V2TIMMessage.V2TIM_MSG_STATUS_SEND_FAIL) {
msgInfo.setStatus(MessageInfo.MSG_STATUS_SEND_FAIL);
} else if (timMessage.getStatus() == V2TIMMessage.V2TIM_MSG_STATUS_SEND_SUCC) {
msgInfo.setStatus(MessageInfo.MSG_STATUS_SEND_SUCCESS);
} else if (timMessage.getStatus() == V2TIMMessage.V2TIM_MSG_STATUS_SENDING) {
msgInfo.setStatus(MessageInfo.MSG_STATUS_SENDING);
}
}
}
return msgInfo;
}
private static MessageInfo createCustomMessageInfo(V2TIMMessage timMessage, Context context) {
MessageInfo msgInfo = new MessageInfo();
setMessageInfoCommonAttributes(msgInfo, timMessage);
V2TIMCustomElem customElem = timMessage.getCustomElem();
if (customElem == null || customElem.getData() == null) {
return null;
}
String data = new String(customElem.getData());
Gson gson = new Gson();
HashMap customJsonMap = null;
try {
customJsonMap = gson.fromJson(data, HashMap.class);
} catch (JsonSyntaxException e) {
TUISearchLog.e(TAG, " getCustomJsonMap error ");
}
String businessId = null;
Double businessIdForTimeout = 0.0;
Object businessIdObj = null;
if (customJsonMap != null) {
businessIdObj = customJsonMap.get(TUIConstants.Message.CUSTOM_BUSINESS_ID_KEY);
}
if (businessIdObj instanceof String) {
businessId = (String) businessIdObj;
} else if (businessIdObj instanceof Double) {
businessIdForTimeout = (Double) businessIdObj;
}
V2TIMSignalingInfo signalingInfo = V2TIMManager.getSignalingManager().getSignalingInfo(msgInfo.getTimMessage());
if (TextUtils.equals(businessId, "text_link")) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_CUSTOM);
msgInfo.setExtra(customJsonMap.get("text"));
} else if (TextUtils.equals(businessId, TUIConstants.TUILive.CUSTOM_MESSAGE_BUSINESS_ID)) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_CUSTOM);
setLiveExtra(msgInfo, customJsonMap);
} else if (signalingInfo != null) {
try {
HashMap signalDataMap = gson.fromJson(signalingInfo.getData(), HashMap.class);
if (signalDataMap != null) {
businessIdObj = signalDataMap.get(TUIConstants.Message.CUSTOM_BUSINESS_ID_KEY);
}
} catch (JsonSyntaxException e) {
TUISearchLog.e(TAG, " get signalingInfoCustomJsonMap error ");
}
if (businessIdObj instanceof String) {
businessId = (String) businessIdObj;
} else if (businessIdObj instanceof Double) {
businessIdForTimeout = (Double) businessIdObj;
}
boolean isV2CallBusinessId = TextUtils.equals(businessId, TUIConstants.TUICalling.CUSTOM_MESSAGE_BUSINESS_ID);
boolean isV3CallBusinessId = TextUtils.equals(businessId, TUIConstants.TUICalling.V3_CALL_BUSINESS_ID);
if (isV2CallBusinessId || isV3CallBusinessId
|| Math.abs(businessIdForTimeout - TUIConstants.TUICalling.CALL_TIMEOUT_BUSINESS_ID) < 0.000001) {
boolean isGroup = !TextUtils.isEmpty(timMessage.getGroupID());
if (isGroup) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_TIPS);
} else {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_TEXT);
}
setCallingExtra(msgInfo);
} else {
return null;
}
} else if (data.equals(MessageCustom.BUSINESS_ID_GROUP_CREATE)) {
// Compatible with tuikit prior to version 4.7
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_CREATE);
String message = TUISearchConstants.covert2HTMLString(getDisplayName(timMessage)) + context.getString(R.string.create_group);
msgInfo.setExtra(message);
} else {
if (isTyping(customElem.getData())) {
return null;
}
TUISearchLog.i(TAG, "custom data:" + data);
String content = context.getString(R.string.custom_msg);
msgInfo.setMsgType(MessageInfo.MSG_TYPE_CUSTOM);
msgInfo.setExtra(content);
MessageCustom messageCustom = null;
try {
messageCustom = gson.fromJson(data, MessageCustom.class);
if (!TextUtils.isEmpty(messageCustom.businessID) && messageCustom.businessID.equals(MessageCustom.BUSINESS_ID_GROUP_CREATE)) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_CREATE);
String message = TUISearchConstants.covert2HTMLString(getDisplayName(timMessage)) + messageCustom.content;
msgInfo.setExtra(message);
}
} catch (Exception e) {
TUISearchLog.e(TAG, "invalid json: " + data + ", exception:" + e);
}
}
return msgInfo;
}
private static void setCallingExtra(MessageInfo messageInfo) {
V2TIMMessage timMessage = messageInfo.getTimMessage();
CallModel callModel = CallModel.convert2VideoCallData(timMessage);
if (callModel == null) {
return;
}
boolean isGroup = messageInfo.isGroup();
String senderShowName = getDisplayName(timMessage);
String content = "";
Context context = ServiceInitializer.getAppContext();
switch (callModel.action) {
case CallModel.VIDEO_CALL_ACTION_DIALING:
content = isGroup ? ("\"" + senderShowName + "\"" + context.getString(R.string.start_group_call)) : (context.getString(R.string.start_call));
break;
case CallModel.VIDEO_CALL_ACTION_SPONSOR_CANCEL:
content = isGroup ? context.getString(R.string.cancle_group_call) : context.getString(R.string.cancle_call);
break;
case CallModel.VIDEO_CALL_ACTION_LINE_BUSY:
content = isGroup ? ("\"" + senderShowName + "\"" + context.getString(R.string.line_busy)) : context.getString(R.string.other_line_busy);
break;
case CallModel.VIDEO_CALL_ACTION_REJECT:
content = isGroup ? ("\"" + senderShowName + "\"" + context.getString(R.string.reject_group_calls)) : context.getString(R.string.reject_calls);
break;
case CallModel.VIDEO_CALL_ACTION_SPONSOR_TIMEOUT:
if (isGroup && callModel.invitedList != null && callModel.invitedList.size() == 1
&& callModel.invitedList.get(0).equals(timMessage.getSender())) {
content = "\"" + senderShowName + "\"" + context.getString(R.string.no_response_call);
} else {
StringBuilder inviteeShowStringBuilder = new StringBuilder();
if (callModel.invitedList != null && callModel.invitedList.size() > 0) {
for (String invitee : callModel.invitedList) {
inviteeShowStringBuilder.append(invitee).append("");
}
if (inviteeShowStringBuilder.length() > 0) {
inviteeShowStringBuilder.delete(inviteeShowStringBuilder.length() - 1, inviteeShowStringBuilder.length());
}
}
content = isGroup ? ("\"" + inviteeShowStringBuilder.toString() + "\"" + context.getString(R.string.no_response_call))
: context.getString(R.string.no_response_call);
}
break;
case CallModel.VIDEO_CALL_ACTION_ACCEPT:
content = isGroup ? ("\"" + senderShowName + "\"" + context.getString(R.string.accept_call)) : context.getString(R.string.accept_call);
break;
case CallModel.VIDEO_CALL_ACTION_HANGUP:
content = isGroup ? context.getString(R.string.stop_group_call)
: context.getString(R.string.stop_call_tip) + DateTimeUtil.formatSecondsTo00(callModel.duration);
break;
default:
content = context.getString(R.string.invalid_command);
break;
}
messageInfo.setExtra(content);
}
private static void setLiveExtra(MessageInfo messageInfo, HashMap customJsonMap) {
if (messageInfo == null || customJsonMap == null) {
return;
}
String content;
String anchorName = (String) customJsonMap.get(TUIConstants.TUILive.ANCHOR_NAME);
String anchorId = (String) customJsonMap.get(TUIConstants.TUILive.ANCHOR_ID);
String roomName = (String) customJsonMap.get(TUIConstants.TUILive.ROOM_NAME);
if (TextUtils.isEmpty(anchorName)) {
if (!TextUtils.isEmpty(anchorId)) {
anchorName = anchorId;
} else {
anchorName = roomName;
}
}
content = "[" + anchorName + ServiceInitializer.getAppContext().getString(R.string.live) + "]";
messageInfo.setExtra(content);
}
public static String getDisplayName(V2TIMMessage timMessage) {
String displayName;
if (timMessage == null) {
return null;
}
if (!TextUtils.isEmpty(timMessage.getNameCard())) {
displayName = timMessage.getNameCard();
} else if (!TextUtils.isEmpty(timMessage.getFriendRemark())) {
displayName = timMessage.getFriendRemark();
} else if (!TextUtils.isEmpty(timMessage.getNickName())) {
displayName = timMessage.getNickName();
} else {
displayName = timMessage.getSender();
}
return displayName;
}
public static String getDisplayName(V2TIMGroupMemberInfo groupMemberInfo) {
String displayName;
if (groupMemberInfo == null) {
return null;
}
if (!TextUtils.isEmpty(groupMemberInfo.getNameCard())) {
displayName = groupMemberInfo.getNameCard();
} else if (!TextUtils.isEmpty(groupMemberInfo.getFriendRemark())) {
displayName = groupMemberInfo.getFriendRemark();
} else if (!TextUtils.isEmpty(groupMemberInfo.getNickName())) {
displayName = groupMemberInfo.getNickName();
} else {
displayName = groupMemberInfo.getUserID();
}
return displayName;
}
private static MessageInfo createGroupTipsMessageInfo(V2TIMMessage timMessage, Context context) {
MessageInfo msgInfo = new MessageInfo();
setMessageInfoCommonAttributes(msgInfo, timMessage);
V2TIMGroupTipsElem groupTipElem = timMessage.getGroupTipsElem();
String operationUser = "";
String targetUser = "";
if (groupTipElem.getMemberList().size() > 0) {
List<V2TIMGroupMemberInfo> v2TIMGroupMemberInfoList = groupTipElem.getMemberList();
for (int i = 0; i < v2TIMGroupMemberInfoList.size(); i++) {
V2TIMGroupMemberInfo v2TIMGroupMemberInfo = v2TIMGroupMemberInfoList.get(i);
if (i == 0) {
targetUser = targetUser + getDisplayName(v2TIMGroupMemberInfo);
} else {
if (i == 2 && v2TIMGroupMemberInfoList.size() > 3) {
targetUser = targetUser + context.getString(R.string.etc);
break;
} else {
targetUser = targetUser + "" + getDisplayName(v2TIMGroupMemberInfo);
}
}
}
}
operationUser = getDisplayName(groupTipElem.getOpMember());
if (!TextUtils.isEmpty(targetUser)) {
targetUser = TUISearchConstants.covert2HTMLString(targetUser);
}
if (!TextUtils.isEmpty(operationUser)) {
operationUser = TUISearchConstants.covert2HTMLString(operationUser);
}
int tipsType = groupTipElem.getType();
String tipsMessage = "";
if (tipsType == V2TIMGroupTipsElem.V2TIM_GROUP_TIPS_TYPE_JOIN) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_JOIN);
tipsMessage = context.getString(R.string.join_group, targetUser);
}
if (tipsType == V2TIMGroupTipsElem.V2TIM_GROUP_TIPS_TYPE_INVITE) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_JOIN);
tipsMessage = context.getString(R.string.invite_joined_group, operationUser, targetUser);
}
if (tipsType == V2TIMGroupTipsElem.V2TIM_GROUP_TIPS_TYPE_QUIT) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_QUITE);
tipsMessage = context.getString(R.string.quit_group, operationUser);
}
if (tipsType == V2TIMGroupTipsElem.V2TIM_GROUP_TIPS_TYPE_KICKED) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_KICK);
tipsMessage = context.getString(R.string.kick_group_tip, operationUser, targetUser);
}
if (tipsType == V2TIMGroupTipsElem.V2TIM_GROUP_TIPS_TYPE_SET_ADMIN) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_MODIFY_NOTICE);
tipsMessage = context.getString(R.string.be_group_manager, targetUser);
}
if (tipsType == V2TIMGroupTipsElem.V2TIM_GROUP_TIPS_TYPE_CANCEL_ADMIN) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_MODIFY_NOTICE);
tipsMessage = context.getString(R.string.cancle_group_manager, targetUser);
}
if (tipsType == V2TIMGroupTipsElem.V2TIM_GROUP_TIPS_TYPE_GROUP_INFO_CHANGE) {
List<V2TIMGroupChangeInfo> modifyList = groupTipElem.getGroupChangeInfoList();
for (int i = 0; i < modifyList.size(); i++) {
V2TIMGroupChangeInfo modifyInfo = modifyList.get(i);
int modifyType = modifyInfo.getType();
if (modifyType == V2TIMGroupChangeInfo.V2TIM_GROUP_INFO_CHANGE_TYPE_NAME) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_MODIFY_NAME);
tipsMessage = context.getString(R.string.modify_group_name_is, operationUser, "\"" + modifyInfo.getValue() + "\"");
} else if (modifyType == V2TIMGroupChangeInfo.V2TIM_GROUP_INFO_CHANGE_TYPE_NOTIFICATION) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_MODIFY_NOTICE);
tipsMessage = context.getString(R.string.modify_notice, operationUser, "\"" + modifyInfo.getValue() + "\"");
} else if (modifyType == V2TIMGroupChangeInfo.V2TIM_GROUP_INFO_CHANGE_TYPE_OWNER) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_MODIFY_NOTICE);
if (!TextUtils.isEmpty(targetUser)) {
tipsMessage = context.getString(R.string.move_owner, operationUser, "\"" + targetUser + "\"");
} else {
tipsMessage = context.getString(R.string.move_owner, operationUser, "\""
+ TUISearchConstants.covert2HTMLString(modifyInfo.getValue()) + "\"");
}
} else if (modifyType == V2TIMGroupChangeInfo.V2TIM_GROUP_INFO_CHANGE_TYPE_FACE_URL) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_MODIFY_NOTICE);
tipsMessage = context.getString(R.string.modify_group_avatar, operationUser);
} else if (modifyType == V2TIMGroupChangeInfo.V2TIM_GROUP_INFO_CHANGE_TYPE_INTRODUCTION) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_MODIFY_NOTICE);
tipsMessage = context.getString(R.string.modify_introduction, operationUser, "\"" + modifyInfo.getValue() + "\"");
} else if (modifyType == V2TIMGroupChangeInfo.V2TIM_GROUP_INFO_CHANGE_TYPE_SHUT_UP_ALL) {
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_MODIFY_NOTICE);
boolean isShutUpAll = modifyInfo.getBoolValue();
if (isShutUpAll) {
tipsMessage = context.getString(R.string.modify_shut_up_all, operationUser);
} else {
tipsMessage = context.getString(R.string.modify_cancel_shut_up_all, operationUser);
}
}
if (i < modifyList.size() - 1) {
tipsMessage = tipsMessage + "";
}
}
}
if (tipsType == V2TIMGroupTipsElem.V2TIM_GROUP_TIPS_TYPE_MEMBER_INFO_CHANGE) {
List<V2TIMGroupMemberChangeInfo> modifyList = groupTipElem.getMemberChangeInfoList();
if (modifyList.size() > 0) {
long shutupTime = modifyList.get(0).getMuteTime();
msgInfo.setMsgType(MessageInfo.MSG_TYPE_GROUP_MODIFY_NOTICE);
if (shutupTime > 0) {
tipsMessage = context.getString(R.string.banned, targetUser, "\"" + DateTimeUtil.formatSeconds(shutupTime) + "\"");
} else {
tipsMessage = context.getString(R.string.cancle_banned, targetUser);
}
}
}
if (TextUtils.isEmpty(tipsMessage)) {
return null;
}
msgInfo.setExtra(tipsMessage);
return msgInfo;
}
private static MessageInfo createNormalMessageInfo(V2TIMMessage timMessage, Context context, int type) {
final MessageInfo msgInfo = new MessageInfo();
setMessageInfoCommonAttributes(msgInfo, timMessage);
if (type == V2TIMMessage.V2TIM_ELEM_TYPE_TEXT) {
V2TIMTextElem txtEle = timMessage.getTextElem();
msgInfo.setExtra(txtEle.getText());
} else if (type == V2TIMMessage.V2TIM_ELEM_TYPE_FACE) {
V2TIMFaceElem faceElem = timMessage.getFaceElem();
if (faceElem.getIndex() < 1 || faceElem.getData() == null) {
TUISearchLog.e("MessageInfoUtil", "faceElem data is null or index<1");
return null;
}
msgInfo.setExtra(context.getString(R.string.custom_emoji));
} else if (type == V2TIMMessage.V2TIM_ELEM_TYPE_SOUND) {
V2TIMSoundElem soundElemEle = timMessage.getSoundElem();
if (msgInfo.isSelf()) {
msgInfo.setDataPath(soundElemEle.getPath());
} else {
final String path = TUIConfig.getRecordDownloadDir() + soundElemEle.getUUID();
File file = new File(path);
if (!file.exists()) {
soundElemEle.downloadSound(path, new V2TIMDownloadCallback() {
@Override
public void onProgress(V2TIMElem.V2ProgressInfo progressInfo) {
long currentSize = progressInfo.getCurrentSize();
long totalSize = progressInfo.getTotalSize();
int progress = 0;
if (totalSize > 0) {
progress = (int) (100 * currentSize / totalSize);
}
if (progress > 100) {
progress = 100;
}
TUISearchLog.i("MessageInfoUtil getSoundToFile", "progress:" + progress);
}
@Override
public void onError(int code, String desc) {
TUISearchLog.e("MessageInfoUtil getSoundToFile", code + ":" + desc);
}
@Override
public void onSuccess() {
msgInfo.setDataPath(path);
}
});
} else {
msgInfo.setDataPath(path);
}
}
msgInfo.setExtra(context.getString(R.string.audio_extra));
} else if (type == V2TIMMessage.V2TIM_ELEM_TYPE_IMAGE) {
V2TIMImageElem imageEle = timMessage.getImageElem();
String localPath = imageEle.getPath();
if (msgInfo.isSelf() && !TextUtils.isEmpty(localPath) && new File(localPath).exists()) {
msgInfo.setDataPath(localPath);
int[] size = ImageUtil.getImageSize(localPath);
msgInfo.setImgWidth(size[0]);
msgInfo.setImgHeight(size[1]);
} else {
List<V2TIMImageElem.V2TIMImage> imgs = imageEle.getImageList();
for (int i = 0; i < imgs.size(); i++) {
V2TIMImageElem.V2TIMImage img = imgs.get(i);
if (img.getType() == V2TIMImageElem.V2TIM_IMAGE_TYPE_THUMB) {
final String path = ImageUtil.generateImagePath(img.getUUID(), V2TIMImageElem.V2TIM_IMAGE_TYPE_THUMB);
msgInfo.setImgWidth(img.getWidth());
msgInfo.setImgHeight(img.getHeight());
File file = new File(path);
if (file.exists()) {
msgInfo.setDataPath(path);
}
}
}
}
msgInfo.setExtra(context.getString(R.string.picture_extra));
} else if (type == V2TIMMessage.V2TIM_ELEM_TYPE_VIDEO) {
V2TIMVideoElem videoEle = timMessage.getVideoElem();
if (msgInfo.isSelf() && !TextUtils.isEmpty(videoEle.getSnapshotPath())) {
int[] size = ImageUtil.getImageSize(videoEle.getSnapshotPath());
msgInfo.setImgWidth(size[0]);
msgInfo.setImgHeight(size[1]);
msgInfo.setDataPath(videoEle.getSnapshotPath());
msgInfo.setDataUri(FileUtil.getUriFromPath(videoEle.getVideoPath()));
} else {
final String videoPath = TUIConfig.getVideoDownloadDir() + videoEle.getVideoUUID();
Uri uri = Uri.parse(videoPath);
msgInfo.setDataUri(uri);
msgInfo.setImgWidth((int) videoEle.getSnapshotWidth());
msgInfo.setImgHeight((int) videoEle.getSnapshotHeight());
final String snapPath = TUIConfig.getImageDownloadDir() + videoEle.getSnapshotUUID();
if (new File(snapPath).exists()) {
msgInfo.setDataPath(snapPath);
}
}
msgInfo.setExtra(context.getString(R.string.video_extra));
} else if (type == V2TIMMessage.V2TIM_ELEM_TYPE_FILE) {
V2TIMFileElem fileElem = timMessage.getFileElem();
String filename = fileElem.getUUID();
if (TextUtils.isEmpty(filename)) {
filename = System.currentTimeMillis() + fileElem.getFileName();
}
final String path = TUIConfig.getFileDownloadDir() + filename;
String finalPath = path;
File file = new File(path);
if (file.exists()) {
if (msgInfo.isSelf()) {
msgInfo.setStatus(MessageInfo.MSG_STATUS_SEND_SUCCESS);
}
msgInfo.setDownloadStatus(MessageInfo.MSG_STATUS_DOWNLOADED);
} else {
if (msgInfo.isSelf()) {
if (TextUtils.isEmpty(fileElem.getPath())) {
msgInfo.setDownloadStatus(MessageInfo.MSG_STATUS_UN_DOWNLOAD);
} else {
file = new File(fileElem.getPath());
if (file.exists()) {
msgInfo.setStatus(MessageInfo.MSG_STATUS_SEND_SUCCESS);
msgInfo.setDownloadStatus(MessageInfo.MSG_STATUS_DOWNLOADED);
finalPath = fileElem.getPath();
} else {
msgInfo.setDownloadStatus(MessageInfo.MSG_STATUS_UN_DOWNLOAD);
}
}
} else {
msgInfo.setDownloadStatus(MessageInfo.MSG_STATUS_UN_DOWNLOAD);
}
}
msgInfo.setDataPath(finalPath);
msgInfo.setExtra(context.getString(R.string.file_extra));
} else if (type == V2TIMMessage.V2TIM_ELEM_TYPE_MERGER) {
msgInfo.setExtra(context.getString(R.string.forward_extra));
}
msgInfo.setMsgType(convertTIMElemType2MessageInfoType(type));
return msgInfo;
}
public static void setMessageInfoCommonAttributes(MessageInfo msgInfo, V2TIMMessage timMessage) {
if (msgInfo == null) {
return;
}
boolean isGroup = !TextUtils.isEmpty(timMessage.getGroupID());
String sender = timMessage.getSender();
if (TextUtils.isEmpty(sender)) {
sender = V2TIMManager.getInstance().getLoginUser();
}
msgInfo.setTimMessage(timMessage);
msgInfo.setGroup(isGroup);
msgInfo.setId(timMessage.getMsgID());
msgInfo.setPeerRead(timMessage.isPeerRead());
msgInfo.setFromUser(sender);
msgInfo.setNameCard(timMessage.getNameCard());
msgInfo.setNickName(timMessage.getNickName());
msgInfo.setFaceUrl(timMessage.getFaceUrl());
msgInfo.setFriendRemark(timMessage.getFriendRemark());
msgInfo.setUserId(timMessage.getUserID());
msgInfo.setGroupId(timMessage.getGroupID());
if (isGroup) {
if (!TextUtils.isEmpty(timMessage.getNameCard())) {
msgInfo.setGroupNameCard(timMessage.getNameCard());
}
}
msgInfo.setMsgTime(timMessage.getTimestamp());
msgInfo.setSelf(sender.equals(V2TIMManager.getInstance().getLoginUser()));
}
public static int convertTIMElemType2MessageInfoType(int type) {
switch (type) {
case V2TIMMessage.V2TIM_ELEM_TYPE_TEXT:
return MessageInfo.MSG_TYPE_TEXT;
case V2TIMMessage.V2TIM_ELEM_TYPE_CUSTOM:
return MessageInfo.MSG_TYPE_CUSTOM;
case V2TIMMessage.V2TIM_ELEM_TYPE_IMAGE:
return MessageInfo.MSG_TYPE_IMAGE;
case V2TIMMessage.V2TIM_ELEM_TYPE_SOUND:
return MessageInfo.MSG_TYPE_AUDIO;
case V2TIMMessage.V2TIM_ELEM_TYPE_VIDEO:
return MessageInfo.MSG_TYPE_VIDEO;
case V2TIMMessage.V2TIM_ELEM_TYPE_FILE:
return MessageInfo.MSG_TYPE_FILE;
case V2TIMMessage.V2TIM_ELEM_TYPE_LOCATION:
return MessageInfo.MSG_TYPE_LOCATION;
case V2TIMMessage.V2TIM_ELEM_TYPE_FACE:
return MessageInfo.MSG_TYPE_CUSTOM_FACE;
case V2TIMMessage.V2TIM_ELEM_TYPE_GROUP_TIPS:
return MessageInfo.MSG_TYPE_TIPS;
case V2TIMMessage.V2TIM_ELEM_TYPE_MERGER:
return MessageInfo.MSG_TYPE_MERGE;
default:
break;
}
return -1;
}
}
@@ -0,0 +1,35 @@
package com.tencent.qcloud.tuikit.tuisearch.util;
import com.tencent.imsdk.common.IMLog;
public class TUISearchLog extends IMLog {
private static final String PRE = "TUISearch-";
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);
}
}
@@ -0,0 +1,41 @@
package com.tencent.qcloud.tuikit.tuisearch.util;
import static com.tencent.qcloud.tuicore.TUIConstants.TUIConversation.CONVERSATION_C2C_PREFIX;
import static com.tencent.qcloud.tuicore.TUIConstants.TUIConversation.CONVERSATION_GROUP_PREFIX;
import com.tencent.imsdk.v2.V2TIMConversation;
import com.tencent.qcloud.tuicore.util.ErrorMessageConverter;
import com.tencent.qcloud.tuikit.timcommon.component.interfaces.IUIKitCallback;
public class TUISearchUtils {
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 String getConversationIdByUserId(String id, boolean isGroup) {
String conversationIdPrefix = isGroup ? CONVERSATION_GROUP_PREFIX : CONVERSATION_C2C_PREFIX;
return conversationIdPrefix + id;
}
public static boolean isC2CChat(int chatType) {
return chatType == V2TIMConversation.V2TIM_C2C;
}
public static boolean isGroupChat(int chatType) {
return chatType == V2TIMConversation.V2TIM_GROUP;
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/search_minimalist_back_icon"
android:autoMirrored="true">
</bitmap>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#0365F9" />
<size android:width="1.5dp" />
</shape>
Binary file not shown.

After

Width:  |  Height:  |  Size: 590 B

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/search_minimalist_forward_icon"
android:autoMirrored="true">
</bitmap>
@@ -0,0 +1,6 @@
<?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>
@@ -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: 734 B

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/search_not_found_icon"
android:autoMirrored="true">
</bitmap>
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -0,0 +1,93 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll_item"
android:layout_width="match_parent"
android:layout_height="72dp"
android:background="#FFFFFF"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingEnd="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.tencent.qcloud.tuikit.timcommon.component.RoundCornerImageView
android:id="@+id/ivAvatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:clickable="false"
android:focusable="false"
app:corner_radius="20dp" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="13dp"
android:orientation="vertical"
android:layout_weight="1">
<TextView
android:id="@+id/conversation_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/black_font_color"
android:textSize="14sp"
tools:text="title" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="@+id/conversation_sub_title_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/list_bottom_text_bg"
android:textDirection="locale"
android:textSize="14sp"
tools:text="label" />
<TextView
android:id="@+id/conversation_sub_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:layout_marginEnd="48dp"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/list_bottom_text_bg"
android:textSize="14sp"
tools:text="aaa" />
</LinearLayout>
</LinearLayout>
<ImageView
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:background="@drawable/search_minimalist_forward_icon"
android:visibility="gone"/>
</LinearLayout>
<View
android:id="@+id/view_line"
android:layout_width="match_parent"
android:layout_height="0.3dp"
android:layout_marginStart="53dp"
android:background="@color/split_lint_color" />
</LinearLayout>
@@ -0,0 +1,94 @@
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ll_item"
android:layout_width="match_parent"
android:layout_height="64dp"
android:background="#FFFFFF"
android:orientation="vertical"
android:paddingStart="16dp"
android:paddingEnd="16dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gravity="center_vertical"
android:orientation="horizontal">
<com.tencent.qcloud.tuikit.timcommon.component.RoundCornerImageView
android:id="@+id/ivAvatar"
android:layout_width="40dp"
android:layout_height="40dp"
android:clickable="false"
android:focusable="false"
app:corner_radius="20dp" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="13dp"
android:orientation="vertical"
android:layout_weight="1">
<TextView
android:id="@+id/conversation_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/black"
android:textStyle="bold"
android:textSize="14sp"
tools:text="title" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/conversation_sub_title_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#666666"
android:textSize="12sp"
tools:text="label" />
<TextView
android:id="@+id/conversation_sub_title"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textAlignment="viewStart"
android:layout_marginStart="2dp"
android:layout_marginEnd="48dp"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#666666"
android:textSize="12sp"
tools:text="aaa" />
<ImageView
android:id="@+id/message_status_icon"
android:layout_width="16dp"
android:layout_height="16dp"/>
<TextView
android:id="@+id/message_time_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#666666"
android:textSize="14sp"
android:visibility="gone"
tools:visibility="visible"
tools:text="2022/08/20"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/conversation_layout"
android:layout_width="match_parent"
android:layout_height="64dp"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:orientation="horizontal"
android:background="@color/transparent">
<com.tencent.qcloud.tuikit.timcommon.component.RoundCornerImageView
android:id="@+id/icon_conversation"
android:layout_width="40dp"
android:layout_height="40dp"
app:corner_radius="20dp"
android:layout_centerVertical="true"
android:layout_alignParentStart="true"
android:background="#FFFFFF"
android:scaleType="fitCenter" />
<TextView
android:id="@+id/conversation_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_toEndOf="@id/icon_conversation"
android:layout_toStartOf="@id/more_conversation_arrow"
android:ellipsize="end"
android:singleLine="true"
android:textAlignment="viewStart"
android:background="#FFFFFF"
android:layout_centerVertical="true"
android:text="@string/more_conversation_label"
android:textColor="@color/black"
android:textSize="14sp" />
<ImageView
android:id="@+id/more_conversation_arrow"
android:layout_width="16dp"
android:layout_height="16dp"
android:scaleType="centerInside"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginStart="16dp"
android:background="#FFFFFF"
android:src="@drawable/search_minimalist_forward_icon_drawable" />
<View
android:layout_width="match_parent"
android:layout_alignParentBottom="true"
android:layout_height="1dp"
android:background="#EEEEEE"/>
</RelativeLayout>
@@ -0,0 +1,164 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical">
<include layout="@layout/search_minimalist_search_bar_layout" />
<!-- ScrollView-->
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="24dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="vertical">
<!-- contact_layout-->
<RelativeLayout
android:id="@+id/contact_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/search_search_box_bg"
android:layout_marginBottom="24dp"
android:visibility="gone"
tools:visibility="visible">
<TextView
android:id="@+id/contact_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_marginStart="24dp"
android:layout_marginBottom="12dp"
android:ellipsize="end"
android:singleLine="true"
android:text="@string/contact_subtitle"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="16sp" />
<TextView
android:id="@+id/more_contact_button"
android:textSize="12sp"
android:textColor="#007AFF"
android:layout_alignBottom="@id/contact_title"
android:layout_alignParentEnd="true"
android:layout_marginEnd="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/search_more_label"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/friend_rc_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/contact_title" />
</RelativeLayout>
<!-- group_layout-->
<RelativeLayout
android:id="@+id/group_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/search_search_box_bg"
android:layout_marginBottom="24dp"
android:visibility="gone"
tools:visibility="visible">
<TextView
android:id="@+id/group_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_marginStart="24dp"
android:layout_marginBottom="12dp"
android:ellipsize="end"
android:singleLine="true"
android:text="@string/group_subtitle"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="16sp" />
<TextView
android:id="@+id/more_group_button"
android:textSize="12sp"
android:textColor="#007AFF"
android:layout_alignBottom="@id/group_title"
android:layout_alignParentEnd="true"
android:layout_marginEnd="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/search_more_label"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/group_rc_search"
android:layout_below="@id/group_title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
<!-- conversation_layout-->
<RelativeLayout
android:id="@+id/conversation_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/search_search_box_bg"
android:visibility="gone"
tools:visibility="visible">
<TextView
android:id="@+id/conversation_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_marginStart="24dp"
android:layout_marginBottom="12dp"
android:ellipsize="end"
android:singleLine="true"
android:text="@string/chat_record"
android:textStyle="bold"
android:textColor="@color/black"
android:textSize="16sp" />
<TextView
android:id="@+id/more_conversation_button"
android:textSize="12sp"
android:textColor="#007AFF"
android:layout_alignBottom="@id/conversation_title"
android:layout_alignParentEnd="true"
android:layout_marginEnd="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/search_more_label"/>
<com.tencent.qcloud.tuikit.tuisearch.minimalistui.widget.PageRecycleView
android:id="@+id/conversation_rc_search"
android:layout_below="@id/conversation_title"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
<include
android:id="@+id/not_found_area"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_marginTop="42dp"
android:visibility="gone"
tools:visibility="visible"
layout="@layout/search_minimalist_not_found_layout"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="24dp"
android:background="@color/white"
android:orientation="vertical">
<include layout="@layout/search_minimalist_search_bar_layout" />
<!-- conversation_layout-->
<RelativeLayout
android:id="@+id/message_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/search_search_box_bg"
android:visibility="visible">
<com.tencent.qcloud.tuikit.tuisearch.minimalistui.widget.PageRecycleView
android:id="@+id/message_rc_search"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>
<include
android:id="@+id/not_found_area"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:layout_marginTop="42dp"
android:visibility="gone"
tools:visibility="visible"
layout="@layout/search_minimalist_not_found_layout"/>
</LinearLayout>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:gravity="center_vertical"
android:background="@drawable/search_minimalist_search_border"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/search_icon"
android:layout_width="15.6dp"
android:layout_height="15.6dp"
android:background="@drawable/search_minimalist_search_icon"
android:layout_marginStart="8dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15.7dp"
android:layout_marginStart="6dp"
android:textColor="#993C3C43"
android:text="@string/search"/>
</LinearLayout>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- search-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical"
tools:showIn="@layout/minimalist_search_main_activity">
<ImageView
android:layout_width="105dp"
android:layout_height="105dp"
android:background="@drawable/search_not_found_drawable" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:textSize="14sp"
android:textColor="#99000000"
android:text="@string/search_not_found_info"
/>
</LinearLayout>
@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- search-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView
android:id="@+id/cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/font_blue"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="23dp"
android:text="@string/cancle"
android:textSize="16sp" />
<ImageView
android:id="@+id/search_back_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:scaleType="fitCenter"
android:layout_alignParentStart="true"
android:layout_marginStart="16dp"
android:layout_marginEnd="-8dp"
android:layout_centerVertical="true"
android:visibility="gone"
tools:visibility="visible"
android:background="@drawable/search_minimalist_back_icon_drawable" />
<LinearLayout
android:id="@+id/search_bar"
android:focusable="true"
android:layout_toStartOf="@+id/cancel_button"
android:layout_toEndOf="@id/search_back_icon"
android:focusableInTouchMode="true"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_marginStart="24dp"
android:layout_marginEnd="14dp"
android:background="@drawable/search_minimalist_search_bar_shape"
android:orientation="horizontal">
<ImageView
android:layout_marginStart="8dp"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_gravity="center"
android:scaleType="fitCenter"
android:src="@drawable/search_minimalist_search_icon" />
<EditText
android:id="@+id/edt_search"
android:layout_width="0dp"
android:layout_height="28dp"
android:layout_gravity="center"
android:layout_weight="1"
android:layout_marginStart="10dp"
android:textAlignment="viewStart"
android:background="@null"
android:imeOptions="actionSearch"
android:textCursorDrawable="@drawable/search_minimalist_cursor_shape"
android:hint="@string/search"
android:textColorHint="#8E8E93"
android:lines="1"
android:textSize="16sp"
android:singleLine="true" />
<ImageView
android:id="@+id/imgv_delete"
android:layout_width="13.82dp"
android:layout_height="13.82dp"
android:layout_gravity="center"
android:scaleType="centerInside"
android:layout_marginEnd="8dp"
android:src="@drawable/core_delete_icon"
tools:visibility="visible"
android:visibility="gone" />
</LinearLayout>
</RelativeLayout>
@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape>
<solid android:color="#ece9e9" />
<corners android:radius="5dp"/>
</shape>
</item>
<item android:bottom="1dp"
android:start="1dp"
android:right="1dp"
android:left="1dp">
<shape>
<solid android:color="#fff" />
<corners android:radius="5dp"/>
</shape>
</item>
</layer-list>
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="12dp"
android:paddingBottom="15.36dp"
android:background="?attr/core_header_start_color">
<LinearLayout
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_width="match_parent"
android:layout_height="@dimen/search_bar_height"
android:gravity="center"
android:layout_marginStart="@dimen/search_bar_margin"
android:layout_marginEnd="@dimen/search_bar_margin"
android:background="@drawable/search_search_box_bg"
android:orientation="horizontal">
<ImageView
android:id="@+id/search_button"
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@drawable/core_search_icon"
android:textCursorDrawable="@drawable/common_edit_cursor" />
<TextView
android:id="@+id/search_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/search_tip_text_color"
android:text="@string/search"
android:textSize="16.3sp"
android:layout_marginStart="@dimen/btn_margin_left" />
</LinearLayout>
</RelativeLayout>
@@ -0,0 +1,84 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/conversation_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="horizontal"
android:background="@color/transparent"
android:paddingTop="12dp">
<ImageView
android:id="@+id/icon_conversation"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_alignParentStart="true"
android:layout_gravity="center"
android:layout_marginStart="14.85dp"
android:background="#FFFFFF"
android:scaleType="fitCenter"
android:src="@drawable/core_search_icon" />
<TextView
android:id="@+id/conversation_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/btn_margin_left"
android:layout_toEndOf="@+id/icon_conversation"
android:ellipsize="end"
android:gravity="center|start"
android:singleLine="true"
android:background="#FFFFFF"
android:text="@string/more_conversation_label"
android:textColor="@color/black_font_color"
android:textSize="16.3sp" />
<ImageView
android:id="@+id/more_conversation_arrow"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_alignParentEnd="true"
android:gravity="center|end"
android:background="#FFFFFF"
android:layout_marginEnd="14.85dp"
android:src="@drawable/common_arrow_right"
android:textSize="11.14sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/conversation_title"
android:layout_gravity="center"
android:orientation="vertical"
android:background="@color/transparent"
android:paddingTop="12dp">
<View
android:id="@+id/view_line_one"
android:layout_width="match_parent"
android:layout_height="4dp"
android:background="@color/split_lint_color" />
<TextView
android:id="@+id/conversation_tip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_marginStart="20dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="20dp"
android:ellipsize="end"
android:singleLine="true"
android:text="@string/chat_record_reference"
android:textColor="@color/list_bottom_text_bg"
android:textSize="12.86sp" />
<View
android:id="@+id/view_line_three"
android:layout_width="match_parent"
android:layout_height="0.3dp"
android:layout_marginTop="4dp"
android:background="@color/split_lint_color" />
</LinearLayout>
</RelativeLayout>
@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:paddingTop="12dp"
android:paddingStart="14.85dp"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="@dimen/search_avatar_height" >
<ImageView
android:id="@+id/ivAvatar"
android:layout_width="@dimen/search_avatar_width"
android:layout_height="@dimen/search_avatar_height"
android:clickable="false"
android:focusable="false"
android:background="?attr/core_default_user_icon"/>
<RelativeLayout
android:layout_toEndOf="@id/ivAvatar"
android:layout_width="match_parent"
android:paddingTop="1.37dp"
android:paddingStart="11.43dp"
android:paddingEnd="18.11dp"
android:layout_height="match_parent">
<TextView
android:id="@+id/conversation_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:textAlignment="viewStart"
android:textColor="@color/black_font_color"
android:text="aaa"
android:textSize="16.3sp" />
<TextView
android:id="@+id/conversation_sub_title_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="2dp"
android:ellipsize="end"
android:singleLine="true"
android:textAlignment="viewStart"
android:textDirection="locale"
android:text="aaa"
android:textColor="@color/list_bottom_text_bg"
android:textSize="12.86sp" />
<TextView
android:id="@+id/conversation_sub_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toEndOf="@id/conversation_sub_title_label"
android:layout_alignTop="@id/conversation_sub_title_label"
android:ellipsize="end"
android:singleLine="true"
android:textAlignment="viewStart"
android:layout_marginEnd="48dp"
android:text="aaa"
android:textColor="@color/list_bottom_text_bg"
android:textSize="12.86sp" />
</RelativeLayout>
</RelativeLayout>
<View
android:id="@+id/view_line"
android:layout_marginTop="12dp"
android:layout_marginStart="60dp"
android:layout_width="match_parent"
android:layout_height="0.3dp"
android:background="@color/split_lint_color" />
</LinearLayout>
@@ -0,0 +1,349 @@
<?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:orientation="vertical"
android:background="@color/status_bar_color">
<!-- search-->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center" >
<TextView
android:id="@+id/cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/font_blue"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="10dp"
android:text="@string/cancle"
android:textSize="16sp" />
<LinearLayout
android:focusable="true"
android:layout_toStartOf="@+id/cancel_button"
android:focusableInTouchMode="true"
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_gravity="center"
android:layout_marginStart="10dp"
android:layout_marginEnd="5dp"
android:background="@drawable/search_search_box_bg"
android:orientation="horizontal">
<ImageView
android:layout_marginStart="5dp"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center"
android:scaleType="fitCenter"
android:src="@drawable/core_search_icon" />
<EditText
android:id="@+id/edt_search"
android:layout_width="0dp"
android:layout_height="28dp"
android:layout_gravity="center"
android:layout_weight="1"
android:layout_marginStart="10dp"
android:background="@null"
android:imeOptions="actionSearch"
android:textAlignment="viewStart"
android:hint="@string/search"
android:lines="1"
android:textSize="16sp"
android:singleLine="true" />
<ImageView
android:layout_marginEnd="3dp"
android:id="@+id/imgv_delete"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="center"
android:scaleType="centerInside"
android:src="@drawable/core_delete_icon"
android:visibility="gone" />
</LinearLayout>
</RelativeLayout>
<!-- ScrollView-->
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<View
android:id="@+id/view_blank_zero"
android:layout_width="match_parent"
android:layout_height="5dp"
android:background="@color/status_bar_color" />
<!-- contact_layout-->
<RelativeLayout
android:id="@+id/contact_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:background="@drawable/search_search_box_bg">
<TextView
android:id="@+id/contact_title"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_alignParentStart="true"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/list_bottom_text_bg"
android:textSize="12.86sp"
android:text="@string/contact_subtitle" />
<View
android:id="@+id/view_line_one"
android:layout_below="@+id/contact_title"
android:layout_marginTop="4dp"
android:layout_width="match_parent"
android:layout_height="0.3dp"
android:background="@color/split_lint_color" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/friend_rc_search"
android:layout_below="@+id/view_line_one"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<!-- more_contact_layout-->
<RelativeLayout
android:id="@+id/more_contact_layout"
android:layout_below="@+id/friend_rc_search"
android:layout_width="match_parent"
android:layout_height="@dimen/item_height"
android:background="#FFFFFF"
android:paddingTop="12dp"
android:paddingStart="14.85dp"
android:paddingEnd="14.85dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/search_icon_contact"
android:layout_marginStart="3dp"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center"
android:layout_alignParentStart="true"
android:scaleType="fitCenter"
android:src="@drawable/core_search_icon" />
<TextView
android:id="@+id/more_contact_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/btn_margin_left"
android:layout_toEndOf="@+id/search_icon_contact"
android:gravity="center|start"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/black_font_color"
android:text="@string/more_contact_label"
android:textSize="16.3sp" />
<ImageView
android:id="@+id/more_contact_arrow"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_alignParentEnd="true"
android:src="@drawable/common_arrow_right"
android:textSize="11.14sp"
android:gravity="center|end" />
</RelativeLayout>
</RelativeLayout>
<View
android:id="@+id/view_blank_one"
android:layout_width="match_parent"
android:layout_height="5dp"
android:background="@color/status_bar_color" />
<!-- group_layout-->
<RelativeLayout
android:id="@+id/group_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:background="@drawable/search_search_box_bg">
<TextView
android:id="@+id/group_title"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_alignParentStart="true"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/list_bottom_text_bg"
android:textSize="12.86sp"
android:text="@string/group_subtitle"/>
<View
android:id="@+id/view_line_two"
android:layout_below="@+id/group_title"
android:layout_marginTop="4dp"
android:layout_width="match_parent"
android:layout_height="0.3dp"
android:background="@color/split_lint_color" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/group_rc_search"
android:layout_below="@+id/view_line_two"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<!-- more_contact_layout-->
<RelativeLayout
android:id="@+id/more_group_layout"
android:layout_below="@+id/group_rc_search"
android:layout_width="match_parent"
android:layout_height="@dimen/item_height"
android:background="#FFFFFF"
android:paddingTop="12dp"
android:paddingStart="14.85dp"
android:paddingEnd="14.85dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/search_icon_group"
android:layout_marginStart="3dp"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center"
android:layout_alignParentStart="true"
android:scaleType="fitCenter"
android:src="@drawable/core_search_icon" />
<TextView
android:id="@+id/more_group_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/btn_margin_left"
android:layout_toEndOf="@+id/search_icon_group"
android:gravity="center|start"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/black_font_color"
android:text="@string/more_group_label"
android:textSize="16.3sp" />
<ImageView
android:id="@+id/more_group_arrow"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_alignParentEnd="true"
android:src="@drawable/common_arrow_right"
android:textSize="11.14sp"
android:gravity="center|end" />
</RelativeLayout>
</RelativeLayout>
<View
android:id="@+id/view_blank_two"
android:layout_width="match_parent"
android:layout_height="5dp"
android:background="@color/status_bar_color" />
<!-- conversation_layout-->
<RelativeLayout
android:id="@+id/conversation_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:background="@drawable/search_search_box_bg">
<TextView
android:id="@+id/conversation_title"
android:layout_marginStart="20dp"
android:layout_marginEnd="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_alignParentStart="true"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/list_bottom_text_bg"
android:textSize="12.86sp"
android:text="@string/chat_record" />
<View
android:id="@+id/view_line_three"
android:layout_below="@+id/conversation_title"
android:layout_marginTop="4dp"
android:layout_width="match_parent"
android:layout_height="0.3dp"
android:background="@color/split_lint_color" />
<com.tencent.qcloud.tuikit.tuisearch.classicui.widget.PageRecycleView
android:id="@+id/conversation_rc_search"
android:layout_below="@+id/view_line_three"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<!-- more_contact_layout-->
<RelativeLayout
android:id="@+id/more_conversation_layout"
android:layout_below="@+id/conversation_rc_search"
android:layout_width="match_parent"
android:layout_height="@dimen/item_height"
android:background="#FFFFFF"
android:paddingTop="12dp"
android:paddingStart="14.85dp"
android:paddingEnd="14.85dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/search_icon_conversation"
android:layout_marginStart="3dp"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center"
android:layout_alignParentStart="true"
android:scaleType="fitCenter"
android:src="@drawable/core_search_icon" />
<TextView
android:id="@+id/more_conversation_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="@dimen/btn_margin_left"
android:layout_toEndOf="@+id/search_icon_conversation"
android:gravity="center|start"
android:ellipsize="end"
android:singleLine="true"
android:textColor="@color/black_font_color"
android:text="@string/more_conversation_label"
android:textSize="16.3sp" />
<ImageView
android:id="@+id/more_conversation_arrow"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_alignParentEnd="true"
android:src="@drawable/common_arrow_right"
android:textSize="11.14sp"
android:gravity="center|end" />
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
@@ -0,0 +1,91 @@
<?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/status_bar_color"
android:orientation="vertical">
<!-- search-->
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center" >
<TextView
android:id="@+id/cancel_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/font_blue"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:layout_marginEnd="10dp"
android:text="@string/cancle"
android:textSize="16sp" />
<LinearLayout
android:focusable="true"
android:layout_toStartOf="@+id/cancel_button"
android:focusableInTouchMode="true"
android:layout_marginTop="5dp"
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_gravity="center"
android:layout_marginStart="10dp"
android:layout_marginEnd="5dp"
android:background="@drawable/search_search_box_bg"
android:orientation="horizontal">
<ImageView
android:layout_marginStart="5dp"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center"
android:scaleType="fitCenter"
android:src="@drawable/core_search_icon" />
<EditText
android:id="@+id/edt_search"
android:layout_width="0dp"
android:layout_height="28dp"
android:layout_gravity="center"
android:layout_weight="1"
android:layout_marginStart="10dp"
android:background="@null"
android:textAlignment="viewStart"
android:imeOptions="actionSearch"
android:hint="@string/search"
android:lines="1"
android:textSize="16sp"
android:singleLine="true" />
<ImageView
android:layout_marginEnd="3dp"
android:id="@+id/imgv_delete"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="center"
android:scaleType="centerInside"
android:src="@drawable/core_search_icon"
android:visibility="gone" />
</LinearLayout>
</RelativeLayout>
<View
android:id="@+id/view_blank_zero"
android:layout_width="match_parent"
android:layout_height="5dp"
android:background="@color/status_bar_color" />
<!-- conversation_layout-->
<RelativeLayout
android:id="@+id/message_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/search_search_box_bg"
android:visibility="visible">
<com.tencent.qcloud.tuikit.tuisearch.classicui.widget.PageRecycleView
android:id="@+id/message_rc_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/view_line_three" />
</RelativeLayout>
</LinearLayout>
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="contact_subtitle">جهات الاتصال</string>
<string name="group_subtitle">المجموعات</string>
<string name="chat_record">سجل الدردشة</string>
<string name="more_contact_label">المزيد من جهات الاتصال</string>
<string name="more_group_label">المزيد من المجموعات</string>
<string name="more_conversation_label">المزيد من سجل الدردشة</string>
<string name="chat_record_reference">سجل الدردشة ذو الصلة</string>
<string name="chat_records">سجلات الدردشة ذات الصلة</string>
<string name="search_more_label">المزيد</string>
<string name="search_ID_label">المعرف: </string>
<string name="nick_name">الاسم المستعار: </string>
<string name="include_group_id">تتضمن معرف المجموعة: </string>
<string name="include_group_member">تتضمن أعضاء المجموعة: </string>
<string name="ui_at_all">[@الجميع]</string>
<string name="ui_at_me">[شخص ما @ لي]</string>
<string name="ui_at_all_me">[@الجميع][شخص ما @ لي]</string>
<string name="custom_msg">[رسالة مخصصة]</string>
<string name="custom_emoji">[رمز تعبيري متحرك]</string>
<string name="picture_extra">[صورة]</string>
<string name="video_extra">[فيديو]</string>
<string name="audio_extra">[صوت]</string>
<string name="file_extra">[ملف]</string>
<string name="forward_extra">[سجل المحادثة]</string>
<string name="revoke_tips_you">لقد قمت بسحب رسالة</string>
<string name="revoke_tips">تم سحب رسالة</string>
<string name="revoke_tips_other">قام الطرف الآخر بسحب رسالة</string>
<string name="create_group">إنشاء مجموعة</string>
<string name="etc">إلخ</string>
<string name="join_group">%s انضم إلى المجموعة</string>
<string name="invite_joined_group">%s دعا %s للانضمام إلى المجموعة</string>
<string name="quit_group">%s غادر المجموعة</string>
<string name="kick_group_tip">%s قام بإزالة %s من المجموعة</string>
<string name="be_group_manager">%s تم تعيينه مديرًا للمجموعة</string>
<string name="cancle_group_manager">%s تم إزالة صلاحياته كمدير للمجموعة</string>
<string name="modify_group_name_is">%s قام بتغيير اسم المجموعة إلى %s</string>
<string name="modify_notice">%s قام بتغيير إعلان المجموعة إلى %s</string>
<string name="modify_introduction">%s قام بتغيير وصف المجموعة إلى %s</string>
<string name="modify_shut_up_all">%s قام بحظر الدردشة لجميع أعضاء المجموعة</string>
<string name="modify_cancel_shut_up_all">%s قام بإلغاء حظر الدردشة لجميع أعضاء المجموعة</string>
<string name="move_owner">%s قام بنقل ملكية المجموعة إلى %s</string>
<string name="modify_group_avatar">%s قام بتغيير صورة المجموعة</string>
<string name="banned">%s تم حظره لمدة %s</string>
<string name="cancle_banned">%s تم إلغاء حظر الدردشة له في المجموعة</string>
<!-- البحث -->
<string name="search">البحث</string>
<string name="cancle">إلغاء</string>
<string name="search_not_found_info">لا توجد محادثات أو جهات اتصال أو سجلات مطابقة</string>
<string name="live">مباشر</string>
<string name="start_group_call">بدء مكالمة جماعية</string>
<string name="start_call">بدء مكالمة</string>
<string name="cancle_group_call">إلغاء مكالمة جماعية</string>
<string name="cancle_call">إلغاء المكالمة</string>
<string name="other_line_busy">الخط مشغول لدى الطرف الآخر</string>
<string name="reject_group_calls">رفض مكالمة جماعية</string>
<string name="no_response_call">لا يوجد رد</string>
<string name="accept_call">تم الرد</string>
<string name="stop_group_call">إنهاء مكالمة جماعية</string>
<string name="stop_call_tip">إنهاء المكالمة، مدة المكالمة:</string>
<string name="line_busy">الخط مشغول</string>
<string name="reject_call">رفض المكالمة</string>
<string name="invalid_command">أمر المكالمة غير معروف</string>
<string name="reject_calls">رفض المكالمات</string>
<string name="search_i_know">أنا أعلم</string>
<string name="search_no_more_reminders">لا تذكرني مرة أخرى</string>
<string name="search_im_flagship">نسخة الرائد</string>
<string name="search_buying_guidelines">توضيح الأسعار</string>
<string name="search_im_flagship_edition_update_tip">الوظيفة %s هي وظيفة نسخة الرائد لـ Tencent Cloud Chat، يمكن استخدامها بعد شراء باقة نسخة الرائد، يرجى الرجوع إلى توضيح الأسعار للحصول على مزيد من المعلومات.</string>
</resources>
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="contact_subtitle">聯絡人</string>
<string name="group_subtitle">群組</string>
<string name="chat_record">聊天記錄</string>
<string name="more_contact_label">更多聯絡人</string>
<string name="more_group_label">更多群聊</string>
<string name="more_conversation_label">更多聊天記錄</string>
<string name="chat_record_reference">相關聊天記錄</string>
<string name="chat_records">條相關聊天記錄</string>
<string name="search_more_label">更多</string>
<string name="search_ID_label">ID: </string>
<string name="nick_name">暱稱: </string>
<string name="include_group_id">包含群 ID: </string>
<string name="include_group_member">包含群成員: </string>
<string name="ui_at_all">[@所有人]</string>
<string name="ui_at_me">[有人@我]</string>
<string name="ui_at_all_me">[@所有人][有人@我]</string>
<string name="custom_msg">[自定義消息]</string>
<string name="custom_emoji">[動畫表情]</string>
<string name="picture_extra">[圖片]</string>
<string name="video_extra">[視頻]</string>
<string name="audio_extra">[語音]</string>
<string name="file_extra">[文件]</string>
<string name="forward_extra">[聊天記錄]</string>
<string name="revoke_tips_you">您撤回了一條消息</string>
<string name="revoke_tips">撤回了一條消息</string>
<string name="revoke_tips_other">對方撤回了一條消息</string>
<string name="create_group">創建群組</string>
<string name="etc"></string>
<string name="join_group">%s加入群組</string>
<string name="invite_joined_group">%s邀請%s加入群組</string>
<string name="quit_group">%s退出群組</string>
<string name="kick_group_tip">%s將%s踢出群組</string>
<string name="be_group_manager">%s被設置為管理員</string>
<string name="cancle_group_manager">%s被取消管理員</string>
<string name="modify_group_name_is">%s把群名稱修改為%s</string>
<string name="modify_notice">%s把群公告修改為%s</string>
<string name="modify_introduction">%s把群簡介修改為%s</string>
<string name="modify_shut_up_all">%s禁言全員</string>
<string name="modify_cancel_shut_up_all">%s取消禁言全員</string>
<string name="move_owner">%s轉讓群主給%s</string>
<string name="modify_group_avatar">%s修改了群頭像</string>
<string name="banned">%s被禁言%s</string>
<string name="cancle_banned">%s被取消禁言</string>
<string name="search">搜索</string>
<string name="cancle">取消</string>
<string name="search_not_found_info">無相關會話、聯絡人或消息記錄</string>
<string name="live">的直播</string>
<string name="start_group_call">發起群通話</string>
<string name="start_call">發起通話</string>
<string name="cancle_group_call">取消群通話</string>
<string name="cancle_call">取消通話</string>
<string name="other_line_busy">對方忙線</string>
<string name="reject_group_calls">拒絕群通話</string>
<string name="no_response_call">無應答</string>
<string name="accept_call">已接聽</string>
<string name="stop_group_call">結束群通話</string>
<string name="stop_call_tip">結束通話,通話時長:</string>
<string name="line_busy">忙線</string>
<string name="reject_call">拒絕通話</string>
<string name="invalid_command">不能識別的通話指令</string>
<string name="reject_calls">拒絕通話</string>
<string name="search_i_know">我知道了</string>
<string name="search_no_more_reminders">不再提醒</string>
<string name="search_im_flagship">旗艦版</string>
<string name="search_buying_guidelines">價格說明</string>
<string name="search_im_flagship_edition_update_tip">%s功能為IM旗艦版功能,購買旗艦版套餐包後可使用,詳見價格說明。</string>
</resources>
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="contact_subtitle">联系人</string>
<string name="group_subtitle">群组</string>
<string name="chat_record">聊天记录</string>
<string name="more_contact_label">更多联系人</string>
<string name="more_group_label">更多群聊</string>
<string name="more_conversation_label">更多聊天记录</string>
<string name="chat_record_reference">相关聊天记录</string>
<string name="chat_records">条相关聊天记录</string>
<string name="search_more_label">更多</string>
<string name="search_ID_label">ID: </string>
<string name="nick_name">昵称: </string>
<string name="include_group_id">包含群 ID: </string>
<string name="include_group_member">包含群成员: </string>
<string name="ui_at_all">[@所有人]</string>
<string name="ui_at_me">[有人@我]</string>
<string name="ui_at_all_me">[@所有人][有人@我]</string>
<string name="custom_msg">[自定义消息]</string>
<string name="custom_emoji">[动画表情]</string>
<string name="picture_extra">[图片]</string>
<string name="video_extra">[视频]</string>
<string name="audio_extra">[语音]</string>
<string name="file_extra">[文件]</string>
<string name="forward_extra">[聊天记录]</string>
<string name="revoke_tips_you">您撤回了一条消息</string>
<string name="revoke_tips">撤回了一条消息</string>
<string name="revoke_tips_other">对方撤回了一条消息</string>
<string name="create_group">创建群组</string>
<string name="etc"></string>
<string name="join_group">%s加入群组</string>
<string name="invite_joined_group">%s邀请%s加入群组</string>
<string name="quit_group">%s退出群组</string>
<string name="kick_group_tip">%s将%s踢出群组</string>
<string name="be_group_manager">%s被设置管理员</string>
<string name="cancle_group_manager">%s被取消管理员</string>
<string name="modify_group_name_is">%s把群名称修改为%s</string>
<string name="modify_notice">%s把群公告修改为%s</string>
<string name="modify_introduction">%s把群简介修改为%s</string>
<string name="modify_shut_up_all">%s禁言全员</string>
<string name="modify_cancel_shut_up_all">%s取消禁言全员</string>
<string name="move_owner">%s转让群主给%s</string>
<string name="modify_group_avatar">%s修改了群头像</string>
<string name="banned">%s被禁言%s</string>
<string name="cancle_banned">%s被取消禁言</string>
<string name="search">搜索</string>
<string name="cancle">取消</string>
<string name="search_not_found_info">无相关会话、联系人或消息记录</string>
<string name="live">的直播</string>
<string name="start_group_call">发起群通话</string>
<string name="start_call">发起通话</string>
<string name="cancle_group_call">取消群通话</string>
<string name="cancle_call">取消通话</string>
<string name="other_line_busy">对方忙线</string>
<string name="reject_group_calls">拒绝群通话</string>
<string name="no_response_call">无应答</string>
<string name="accept_call">已接听</string>
<string name="stop_group_call">结束群通话</string>
<string name="stop_call_tip">结束通话,通话时长:</string>
<string name="line_busy">忙线</string>
<string name="reject_call">拒绝通话</string>
<string name="invalid_command">不能识别的通话指令</string>
<string name="reject_calls">拒绝通话</string>
<string name="search_i_know">我知道了</string>
<string name="search_no_more_reminders">不再提醒</string>
<string name="search_im_flagship">旗舰版</string>
<string name="search_buying_guidelines">价格说明</string>
<string name="search_im_flagship_edition_update_tip">%s功能为IM旗舰版功能,购买旗舰版套餐包后可使用,详见价格说明。</string>
</resources>
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="transparent">#00000000</color>
<color name="list_bottom_text_bg">#999999</color>
<color name="font_blue">#066fff</color>
<color name="white">#FFFFFF</color>
<color name="black_font_color">#181818</color>
<color name="split_lint_color">#D9D9D9</color>
<color name="black">#000000</color>
<color name="search_tip_text_color">#CCCCCC</color>
</resources>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="search_avatar_width">49.35dp</dimen>
<dimen name="search_avatar_height">49.35dp</dimen>
<dimen name="page_title_height">45dp</dimen>
<dimen name="page_margin">10dp</dimen>
<dimen name="btn_margin_left">12dp</dimen>
<dimen name="item_height">49.35dp</dimen>
<dimen name="search_bar_height">38.4dp</dimen>
<dimen name="search_bar_margin">15.36dp</dimen>
</resources>
@@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="contact_subtitle">Contact</string>
<string name="group_subtitle">Group</string>
<string name="chat_record">Chat Record</string>
<string name="more_contact_label">More Contacts</string>
<string name="more_group_label">More Group Chat</string>
<string name="more_conversation_label">More Conversations</string>
<string name="chat_record_reference">Chat Record</string>
<string name="search_more_label">More</string>
<string name="search_ID_label">ID: </string>
<string name="chat_records">message(s)</string>
<string name="nick_name">nick name: </string>
<string name="include_group_id">Contains group ID: </string>
<string name="include_group_member">Contains group members: </string>
<string name="ui_at_all">[@All]</string>
<string name="ui_at_me">[Someone @ me]</string>
<string name="ui_at_all_me">[@All][Someone @ me]</string>
<string name="custom_msg">[Custom Messages]</string>
<string name="custom_emoji">[Animated Sticker]</string>
<string name="picture_extra">[Image]</string>
<string name="video_extra">[Video]</string>
<string name="audio_extra">[Voice]</string>
<string name="file_extra">[File]</string>
<string name="forward_extra">[Chat Record]</string>
<string name="revoke_tips_you">You recalled a message.</string>
<string name="revoke_tips">recalled a message.</string>
<string name="revoke_tips_other">A message is recalled.</string>
<string name="create_group">Create Group</string>
<string name="etc">, etc.</string>
<string name="join_group">%s joined the group</string>
<string name="invite_joined_group">%s invited %s to join the group</string>
<string name="quit_group">%s left the group</string>
<string name="kick_group_tip">%s has removed %s from the group</string>
<string name="be_group_manager">%s was promoted to group manager</string>
<string name="cancle_group_manager">%s was demoted from group manager</string>
<string name="modify_group_name_is">%s changed the group name to %s</string>
<string name="modify_notice">%s changed the group notice to %s</string>
<string name="modify_introduction">%s changed the group introduction to %s</string>
<string name="modify_shut_up_all">%s muted all members</string>
<string name="modify_cancel_shut_up_all">%s unmuted all members</string>
<string name="move_owner">%s transferred group ownership to %s</string>
<string name="modify_group_avatar">%s changed the group avatar</string>
<string name="banned">%s was muted for %s</string>
<string name="cancle_banned">%s was unmuted</string>
<string name="search">Search</string>
<string name="cancle">Cancle</string>
<string name="search_not_found_info">No conversations, contacts, or messages found</string>
<string name="live">\'s live stream</string>
<string name="start_group_call">Start Group Call</string>
<string name="start_call">Start Call</string>
<string name="cancle_group_call">Cancel Group Call</string>
<string name="cancle_call">Cancel Call</string>
<string name="other_line_busy">Line busy</string>
<string name="reject_group_calls">Decline Group Call</string>
<string name="no_response_call">No answer</string>
<string name="accept_call">Answered</string>
<string name="line_busy">Line busy</string>
<string name="reject_call">reject</string>
<string name="invalid_command">invalid command</string>
<string name="stop_group_call">End Group Call</string>
<string name="stop_call_tip">Call ended. Duration:</string>
<string name="reject_calls">Decline Call</string>
<string name="search_i_know">I got it</string>
<string name="search_no_more_reminders">No more reminders</string>
<string name="search_im_flagship">Premium Edition</string>
<string name="search_buying_guidelines">price description</string>
<string name="search_im_flagship_edition_update_tip">%s function is the Tencent Cloud Chat Premium Edition function, which can be used after purchasing the Premium Edition package. Please refer to the price description for details.</string>
</resources>