NekoX/TMessagesProj/src/main/java/org/telegram/ui/Adapters/SearchAdapter.java

422 lines
17 KiB
Java
Raw Normal View History

/*
* This is the source code of Telegram for Android v. 1.3.x.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
2019-01-23 18:03:33 +01:00
* Copyright Nikolai Kudashov, 2013-2018.
*/
package org.telegram.ui.Adapters;
import android.content.Context;
2017-03-31 01:58:05 +02:00
import android.text.SpannableStringBuilder;
import android.text.Spanned;
2020-12-23 08:48:30 +01:00
import android.text.TextUtils;
2018-07-30 04:07:02 +02:00
import android.util.SparseArray;
import android.view.View;
import android.view.ViewGroup;
2019-07-18 15:01:39 +02:00
import org.telegram.PhoneFormat.PhoneFormat;
2015-09-24 22:52:02 +02:00
import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
2020-09-30 15:48:47 +02:00
import org.telegram.messenger.UserObject;
2015-09-24 22:52:02 +02:00
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
import org.telegram.messenger.ContactsController;
import org.telegram.messenger.FileLog;
2015-09-24 22:52:02 +02:00
import org.telegram.messenger.MessagesController;
import org.telegram.messenger.UserConfig;
import org.telegram.messenger.Utilities;
2017-03-31 01:58:05 +02:00
import org.telegram.ui.ActionBar.Theme;
import org.telegram.ui.Cells.GraySectionCell;
2014-11-10 12:05:22 +01:00
import org.telegram.ui.Cells.ProfileSearchCell;
2019-07-18 15:01:39 +02:00
import org.telegram.ui.Cells.TextCell;
2014-11-13 21:10:14 +01:00
import org.telegram.ui.Cells.UserCell;
2020-10-30 11:26:29 +01:00
import org.telegram.ui.Components.ForegroundColorSpanThemable;
2017-03-31 01:58:05 +02:00
import org.telegram.ui.Components.RecyclerListView;
import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;
2019-05-14 14:08:05 +02:00
import androidx.recyclerview.widget.RecyclerView;
2017-03-31 01:58:05 +02:00
public class SearchAdapter extends RecyclerListView.SelectionAdapter {
2015-09-24 22:52:02 +02:00
private Context mContext;
2018-07-30 04:07:02 +02:00
private SparseArray<TLRPC.User> ignoreUsers;
2021-04-09 15:17:32 +02:00
private ArrayList<Object> searchResult = new ArrayList<>();
2015-01-02 23:15:07 +01:00
private ArrayList<CharSequence> searchResultNames = new ArrayList<>();
2017-03-31 01:58:05 +02:00
private SearchAdapterHelper searchAdapterHelper;
2018-07-30 04:07:02 +02:00
private SparseArray<?> checkedMap;
2014-03-25 01:25:32 +01:00
private Timer searchTimer;
2014-10-23 09:55:32 +02:00
private boolean allowUsernameSearch;
2014-11-13 21:10:14 +01:00
private boolean useUserCell;
2015-09-24 22:52:02 +02:00
private boolean onlyMutual;
private boolean allowChats;
2015-11-26 22:04:02 +01:00
private boolean allowBots;
2019-12-31 14:08:08 +01:00
private boolean allowSelf;
2019-07-18 15:01:39 +02:00
private boolean allowPhoneNumbers;
2017-07-08 18:32:04 +02:00
private int channelId;
2020-12-23 08:48:30 +01:00
private boolean searchInProgress;
private int searchReqId;
private int searchPointer;
2019-12-31 14:08:08 +01:00
public SearchAdapter(Context context, SparseArray<TLRPC.User> arg1, boolean usernameSearch, boolean mutual, boolean chats, boolean bots, boolean self, boolean phones, int searchChannelId) {
mContext = context;
ignoreUsers = arg1;
2015-09-24 22:52:02 +02:00
onlyMutual = mutual;
2014-10-23 09:55:32 +02:00
allowUsernameSearch = usernameSearch;
2015-09-24 22:52:02 +02:00
allowChats = chats;
2015-11-26 22:04:02 +01:00
allowBots = bots;
2017-07-08 18:32:04 +02:00
channelId = searchChannelId;
2019-12-31 14:08:08 +01:00
allowSelf = self;
2019-07-18 15:01:39 +02:00
allowPhoneNumbers = phones;
2018-07-30 04:07:02 +02:00
searchAdapterHelper = new SearchAdapterHelper(true);
2017-03-31 01:58:05 +02:00
searchAdapterHelper.setDelegate(new SearchAdapterHelper.SearchAdapterHelperDelegate() {
@Override
2020-01-23 07:15:40 +01:00
public void onDataSetChanged(int searchId) {
2017-03-31 01:58:05 +02:00
notifyDataSetChanged();
2020-12-23 08:48:30 +01:00
if (searchId != 0) {
onSearchProgressChanged();
}
2017-03-31 01:58:05 +02:00
}
2019-01-23 18:03:33 +01:00
@Override
public SparseArray<TLRPC.User> getExcludeUsers() {
return ignoreUsers;
}
2017-03-31 01:58:05 +02:00
});
}
2018-07-30 04:07:02 +02:00
public void setCheckedMap(SparseArray<?> map) {
2014-11-14 16:40:15 +01:00
checkedMap = map;
}
2014-11-13 21:10:14 +01:00
public void setUseUserCell(boolean value) {
useUserCell = value;
}
public void searchDialogs(final String query) {
2014-10-31 20:02:29 +01:00
try {
if (searchTimer != null) {
searchTimer.cancel();
}
} catch (Exception e) {
2017-03-31 01:58:05 +02:00
FileLog.e(e);
2014-10-31 20:02:29 +01:00
}
2020-12-23 08:48:30 +01:00
searchResult.clear();
searchResultNames.clear();
if (allowUsernameSearch) {
searchAdapterHelper.queryServerSearch(null, true, allowChats, allowBots, allowSelf, false, channelId, allowPhoneNumbers, 0, 0);
}
notifyDataSetChanged();
if (!TextUtils.isEmpty(query)) {
2014-03-25 01:25:32 +01:00
searchTimer = new Timer();
searchTimer.schedule(new TimerTask() {
@Override
public void run() {
try {
2014-03-25 01:25:32 +01:00
searchTimer.cancel();
searchTimer = null;
} catch (Exception e) {
2017-03-31 01:58:05 +02:00
FileLog.e(e);
}
processSearch(query);
}
}, 200, 300);
}
}
private void processSearch(final String query) {
2018-08-27 10:33:11 +02:00
AndroidUtilities.runOnUIThread(() -> {
if (allowUsernameSearch) {
2020-12-23 08:48:30 +01:00
searchAdapterHelper.queryServerSearch(query, true, allowChats, allowBots, allowSelf, false, channelId, allowPhoneNumbers, -1, 1);
2018-08-27 10:33:11 +02:00
}
final int currentAccount = UserConfig.selectedAccount;
final ArrayList<TLRPC.TL_contact> contactsCopy = new ArrayList<>(ContactsController.getInstance(currentAccount).contacts);
2020-12-23 08:48:30 +01:00
searchInProgress = true;
searchReqId = searchPointer++;
int searchReqIdFinal = searchReqId;
2018-08-27 10:33:11 +02:00
Utilities.searchQueue.postRunnable(() -> {
String search1 = query.trim().toLowerCase();
if (search1.length() == 0) {
2020-12-23 08:48:30 +01:00
updateSearchResults(searchReqIdFinal, new ArrayList<>(), new ArrayList<>());
2018-08-27 10:33:11 +02:00
return;
}
String search2 = LocaleController.getInstance().getTranslitString(search1);
if (search1.equals(search2) || search2.length() == 0) {
search2 = null;
}
2019-05-14 14:08:05 +02:00
String[] search = new String[1 + (search2 != null ? 1 : 0)];
2018-08-27 10:33:11 +02:00
search[0] = search1;
if (search2 != null) {
search[1] = search2;
2014-10-23 09:55:32 +02:00
}
2015-02-01 19:51:02 +01:00
2021-04-09 15:17:32 +02:00
ArrayList<Object> resultArray = new ArrayList<>();
2018-08-27 10:33:11 +02:00
ArrayList<CharSequence> resultArrayNames = new ArrayList<>();
2018-08-27 10:33:11 +02:00
for (int a = 0; a < contactsCopy.size(); a++) {
TLRPC.TL_contact contact = contactsCopy.get(a);
TLRPC.User user = MessagesController.getInstance(currentAccount).getUser(contact.user_id);
2019-12-31 14:08:08 +01:00
if (!allowSelf && user.self || onlyMutual && !user.mutual_contact || ignoreUsers != null && ignoreUsers.indexOfKey(contact.user_id) >= 0) {
2018-08-27 10:33:11 +02:00
continue;
}
2014-10-23 17:30:35 +02:00
2019-12-31 14:08:08 +01:00
final String[] names = new String[3];
names[0] = ContactsController.formatName(user.first_name, user.last_name).toLowerCase();
names[1] = LocaleController.getInstance().getTranslitString(names[0]);
if (names[0].equals(names[1])) {
names[1] = null;
}
2020-09-30 15:48:47 +02:00
if (UserObject.isReplyUser(user)) {
names[2] = LocaleController.getString("RepliesTitle", R.string.RepliesTitle).toLowerCase();
} else if (user.self) {
2019-12-31 14:08:08 +01:00
names[2] = LocaleController.getString("SavedMessages", R.string.SavedMessages).toLowerCase();
2018-08-27 10:33:11 +02:00
}
2014-10-23 17:30:35 +02:00
2018-08-27 10:33:11 +02:00
int found = 0;
for (String q : search) {
2019-12-31 14:08:08 +01:00
for (int i = 0; i < names.length; i++) {
final String name = names[i];
if (name != null && (name.startsWith(q) || name.contains(" " + q))) {
found = 1;
break;
}
}
if (found == 0 && user.username != null && user.username.startsWith(q)) {
2018-08-27 10:33:11 +02:00
found = 2;
}
2018-08-27 10:33:11 +02:00
if (found != 0) {
if (found == 1) {
resultArrayNames.add(AndroidUtilities.generateSearchName(user.first_name, user.last_name, q));
} else {
resultArrayNames.add(AndroidUtilities.generateSearchName("@" + user.username, null, "@" + q));
}
resultArray.add(user);
break;
}
2014-03-10 10:27:49 +01:00
}
2018-08-27 10:33:11 +02:00
}
2020-12-23 08:48:30 +01:00
updateSearchResults(searchReqIdFinal, resultArray, resultArrayNames);
2018-08-27 10:33:11 +02:00
});
});
}
2021-04-09 15:17:32 +02:00
private void updateSearchResults(int searchReqIdFinal, final ArrayList<Object> users, final ArrayList<CharSequence> names) {
2018-08-27 10:33:11 +02:00
AndroidUtilities.runOnUIThread(() -> {
2020-12-23 08:48:30 +01:00
if (searchReqIdFinal == searchReqId) {
searchResult = users;
searchResultNames = names;
searchAdapterHelper.mergeResults(users);
searchInProgress = false;
notifyDataSetChanged();
onSearchProgressChanged();
}
});
}
2020-12-23 08:48:30 +01:00
protected void onSearchProgressChanged() {
}
public boolean searchInProgress() {
return searchInProgress || searchAdapterHelper.isSearchInProgress();
}
@Override
2017-03-31 01:58:05 +02:00
public boolean isEnabled(RecyclerView.ViewHolder holder) {
2019-07-18 15:01:39 +02:00
int type = holder.getItemViewType();
return type == 0 || type == 2;
}
@Override
2017-03-31 01:58:05 +02:00
public int getItemCount() {
2014-10-23 09:55:32 +02:00
int count = searchResult.size();
2017-03-31 01:58:05 +02:00
int globalCount = searchAdapterHelper.getGlobalSearch().size();
if (globalCount != 0) {
count += globalCount + 1;
}
2019-07-18 15:01:39 +02:00
int phoneCount = searchAdapterHelper.getPhoneSearch().size();
if (phoneCount != 0) {
count += phoneCount;
}
return count;
}
public boolean isGlobalSearch(int i) {
2014-10-23 09:55:32 +02:00
int localCount = searchResult.size();
2017-03-31 01:58:05 +02:00
int globalCount = searchAdapterHelper.getGlobalSearch().size();
2019-07-18 15:01:39 +02:00
int phoneCount = searchAdapterHelper.getPhoneSearch().size();
if (i >= 0 && i < localCount) {
return false;
2019-07-18 15:01:39 +02:00
} else if (i > localCount && i < localCount + phoneCount) {
return false;
} else if (i > localCount + phoneCount && i <= globalCount + phoneCount + localCount) {
return true;
}
return false;
}
2019-07-18 15:01:39 +02:00
public Object getItem(int i) {
2014-10-23 09:55:32 +02:00
int localCount = searchResult.size();
2017-03-31 01:58:05 +02:00
int globalCount = searchAdapterHelper.getGlobalSearch().size();
2019-07-18 15:01:39 +02:00
int phoneCount = searchAdapterHelper.getPhoneSearch().size();
if (i >= 0 && i < localCount) {
return searchResult.get(i);
2019-07-18 15:01:39 +02:00
} else {
i -= localCount;
if (i >= 0 && i < phoneCount) {
return searchAdapterHelper.getPhoneSearch().get(i);
} else {
i -= phoneCount;
if (i > 0 && i <= globalCount) {
return searchAdapterHelper.getGlobalSearch().get(i - 1);
}
}
}
return null;
}
@Override
2017-03-31 01:58:05 +02:00
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view;
switch (viewType) {
case 0:
2014-11-13 21:10:14 +01:00
if (useUserCell) {
2016-03-16 13:26:32 +01:00
view = new UserCell(mContext, 1, 1, false);
2014-11-21 20:36:21 +01:00
if (checkedMap != null) {
((UserCell) view).setChecked(false, false);
}
2014-11-13 21:10:14 +01:00
} else {
view = new ProfileSearchCell(mContext);
}
2017-03-31 01:58:05 +02:00
break;
case 1:
view = new GraySectionCell(mContext);
2019-07-18 15:01:39 +02:00
break;
case 2:
default:
2019-12-31 14:08:08 +01:00
view = new TextCell(mContext, 16, false);
2017-03-31 01:58:05 +02:00
break;
}
return new RecyclerListView.Holder(view);
}
2017-03-31 01:58:05 +02:00
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
2019-07-18 15:01:39 +02:00
switch (holder.getItemViewType()) {
case 0: {
TLObject object = (TLObject) getItem(position);
if (object != null) {
int id = 0;
String un = null;
2019-12-31 14:08:08 +01:00
boolean self = false;
2019-07-18 15:01:39 +02:00
if (object instanceof TLRPC.User) {
un = ((TLRPC.User) object).username;
id = ((TLRPC.User) object).id;
2019-12-31 14:08:08 +01:00
self = ((TLRPC.User) object).self;
2019-07-18 15:01:39 +02:00
} else if (object instanceof TLRPC.Chat) {
un = ((TLRPC.Chat) object).username;
id = ((TLRPC.Chat) object).id;
}
2015-09-24 22:52:02 +02:00
2019-07-18 15:01:39 +02:00
CharSequence username = null;
CharSequence name = null;
if (position < searchResult.size()) {
name = searchResultNames.get(position);
if (name != null && un != null && un.length() > 0) {
if (name.toString().startsWith("@" + un)) {
username = name;
name = null;
}
2014-10-23 17:30:35 +02:00
}
2019-07-18 15:01:39 +02:00
} else if (position > searchResult.size() && un != null) {
String foundUserName = searchAdapterHelper.getLastFoundUsername();
2020-10-30 13:41:45 +01:00
if (foundUserName != null && foundUserName.startsWith("@")) {
2019-07-18 15:01:39 +02:00
foundUserName = foundUserName.substring(1);
}
try {
int index;
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
spannableStringBuilder.append("@");
spannableStringBuilder.append(un);
2020-10-30 13:41:45 +01:00
if (foundUserName != null && (index = AndroidUtilities.indexOfIgnoreCase(un, foundUserName)) != -1) {
2019-07-18 15:01:39 +02:00
int len = foundUserName.length();
if (index == 0) {
len++;
} else {
index++;
}
2020-10-30 11:26:29 +01:00
spannableStringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4), index, index + len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
2018-07-30 04:07:02 +02:00
}
2019-07-18 15:01:39 +02:00
username = spannableStringBuilder;
} catch (Exception e) {
username = un;
FileLog.e(e);
2018-07-30 04:07:02 +02:00
}
2014-10-23 09:55:32 +02:00
}
2014-10-21 22:35:16 +02:00
2019-07-18 15:01:39 +02:00
if (useUserCell) {
UserCell userCell = (UserCell) holder.itemView;
userCell.setData(object, name, username, 0);
if (checkedMap != null) {
userCell.setChecked(checkedMap.indexOfKey(id) >= 0, false);
}
} else {
ProfileSearchCell profileSearchCell = (ProfileSearchCell) holder.itemView;
2019-12-31 14:08:08 +01:00
if (self) {
name = LocaleController.getString("SavedMessages", R.string.SavedMessages);
}
profileSearchCell.setData(object, null, name, username, false, self);
2019-07-18 15:01:39 +02:00
profileSearchCell.useSeparator = (position != getItemCount() - 1 && position != searchResult.size() - 1);
/*if (ignoreUsers != null) {
if (ignoreUsers.containsKey(id)) {
profileSearchCell.drawAlpha = 0.5f;
} else {
profileSearchCell.drawAlpha = 1.0f;
}
}*/
2014-11-14 16:40:15 +01:00
}
2019-07-18 15:01:39 +02:00
}
break;
}
case 1: {
GraySectionCell cell = (GraySectionCell) holder.itemView;
if (getItem(position) == null) {
cell.setText(LocaleController.getString("GlobalSearch", R.string.GlobalSearch));
2014-11-13 21:10:14 +01:00
} else {
2019-07-18 15:01:39 +02:00
cell.setText(LocaleController.getString("PhoneNumberSearch", R.string.PhoneNumberSearch));
}
2019-07-18 15:01:39 +02:00
break;
}
case 2: {
String str = (String) getItem(position);
TextCell cell = (TextCell) holder.itemView;
cell.setColors(null, Theme.key_windowBackgroundWhiteBlueText2);
cell.setText(LocaleController.formatString("AddContactByPhone", R.string.AddContactByPhone, PhoneFormat.getInstance().format("+" + str)), false);
break;
}
}
}
@Override
public int getItemViewType(int i) {
2019-07-18 15:01:39 +02:00
Object item = getItem(i);
if (item == null) {
return 1;
2019-07-18 15:01:39 +02:00
} else if (item instanceof String) {
String str = (String) item;
if ("section".equals(str)) {
return 1;
} else {
return 2;
}
}
return 0;
}
}