mirror of https://github.com/NekoX-Dev/NekoX.git
422 lines
17 KiB
Java
422 lines
17 KiB
Java
/*
|
|
* 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).
|
|
*
|
|
* Copyright Nikolai Kudashov, 2013-2018.
|
|
*/
|
|
|
|
package org.telegram.ui.Adapters;
|
|
|
|
import android.content.Context;
|
|
import android.text.SpannableStringBuilder;
|
|
import android.text.Spanned;
|
|
import android.text.TextUtils;
|
|
import android.util.SparseArray;
|
|
import android.view.View;
|
|
import android.view.ViewGroup;
|
|
|
|
import org.telegram.PhoneFormat.PhoneFormat;
|
|
import org.telegram.messenger.AndroidUtilities;
|
|
import org.telegram.messenger.LocaleController;
|
|
import org.telegram.messenger.R;
|
|
import org.telegram.messenger.UserObject;
|
|
import org.telegram.tgnet.TLObject;
|
|
import org.telegram.tgnet.TLRPC;
|
|
import org.telegram.messenger.ContactsController;
|
|
import org.telegram.messenger.FileLog;
|
|
import org.telegram.messenger.MessagesController;
|
|
import org.telegram.messenger.UserConfig;
|
|
import org.telegram.messenger.Utilities;
|
|
import org.telegram.ui.ActionBar.Theme;
|
|
import org.telegram.ui.Cells.GraySectionCell;
|
|
import org.telegram.ui.Cells.ProfileSearchCell;
|
|
import org.telegram.ui.Cells.TextCell;
|
|
import org.telegram.ui.Cells.UserCell;
|
|
import org.telegram.ui.Components.ForegroundColorSpanThemable;
|
|
import org.telegram.ui.Components.RecyclerListView;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Timer;
|
|
import java.util.TimerTask;
|
|
|
|
import androidx.recyclerview.widget.RecyclerView;
|
|
|
|
public class SearchAdapter extends RecyclerListView.SelectionAdapter {
|
|
|
|
private Context mContext;
|
|
private SparseArray<TLRPC.User> ignoreUsers;
|
|
private ArrayList<Object> searchResult = new ArrayList<>();
|
|
private ArrayList<CharSequence> searchResultNames = new ArrayList<>();
|
|
private SearchAdapterHelper searchAdapterHelper;
|
|
private SparseArray<?> checkedMap;
|
|
private Timer searchTimer;
|
|
private boolean allowUsernameSearch;
|
|
private boolean useUserCell;
|
|
private boolean onlyMutual;
|
|
private boolean allowChats;
|
|
private boolean allowBots;
|
|
private boolean allowSelf;
|
|
private boolean allowPhoneNumbers;
|
|
private int channelId;
|
|
private boolean searchInProgress;
|
|
private int searchReqId;
|
|
private int searchPointer;
|
|
|
|
|
|
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;
|
|
onlyMutual = mutual;
|
|
allowUsernameSearch = usernameSearch;
|
|
allowChats = chats;
|
|
allowBots = bots;
|
|
channelId = searchChannelId;
|
|
allowSelf = self;
|
|
allowPhoneNumbers = phones;
|
|
searchAdapterHelper = new SearchAdapterHelper(true);
|
|
searchAdapterHelper.setDelegate(new SearchAdapterHelper.SearchAdapterHelperDelegate() {
|
|
@Override
|
|
public void onDataSetChanged(int searchId) {
|
|
notifyDataSetChanged();
|
|
if (searchId != 0) {
|
|
onSearchProgressChanged();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public SparseArray<TLRPC.User> getExcludeUsers() {
|
|
return ignoreUsers;
|
|
}
|
|
});
|
|
}
|
|
|
|
public void setCheckedMap(SparseArray<?> map) {
|
|
checkedMap = map;
|
|
}
|
|
|
|
public void setUseUserCell(boolean value) {
|
|
useUserCell = value;
|
|
}
|
|
|
|
public void searchDialogs(final String query) {
|
|
try {
|
|
if (searchTimer != null) {
|
|
searchTimer.cancel();
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e(e);
|
|
}
|
|
searchResult.clear();
|
|
searchResultNames.clear();
|
|
if (allowUsernameSearch) {
|
|
searchAdapterHelper.queryServerSearch(null, true, allowChats, allowBots, allowSelf, false, channelId, allowPhoneNumbers, 0, 0);
|
|
}
|
|
notifyDataSetChanged();
|
|
if (!TextUtils.isEmpty(query)) {
|
|
searchTimer = new Timer();
|
|
searchTimer.schedule(new TimerTask() {
|
|
@Override
|
|
public void run() {
|
|
try {
|
|
searchTimer.cancel();
|
|
searchTimer = null;
|
|
} catch (Exception e) {
|
|
FileLog.e(e);
|
|
}
|
|
processSearch(query);
|
|
}
|
|
}, 200, 300);
|
|
}
|
|
}
|
|
|
|
private void processSearch(final String query) {
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
if (allowUsernameSearch) {
|
|
searchAdapterHelper.queryServerSearch(query, true, allowChats, allowBots, allowSelf, false, channelId, allowPhoneNumbers, -1, 1);
|
|
}
|
|
final int currentAccount = UserConfig.selectedAccount;
|
|
final ArrayList<TLRPC.TL_contact> contactsCopy = new ArrayList<>(ContactsController.getInstance(currentAccount).contacts);
|
|
searchInProgress = true;
|
|
searchReqId = searchPointer++;
|
|
int searchReqIdFinal = searchReqId;
|
|
Utilities.searchQueue.postRunnable(() -> {
|
|
String search1 = query.trim().toLowerCase();
|
|
if (search1.length() == 0) {
|
|
updateSearchResults(searchReqIdFinal, new ArrayList<>(), new ArrayList<>());
|
|
return;
|
|
}
|
|
String search2 = LocaleController.getInstance().getTranslitString(search1);
|
|
if (search1.equals(search2) || search2.length() == 0) {
|
|
search2 = null;
|
|
}
|
|
String[] search = new String[1 + (search2 != null ? 1 : 0)];
|
|
search[0] = search1;
|
|
if (search2 != null) {
|
|
search[1] = search2;
|
|
}
|
|
|
|
ArrayList<Object> resultArray = new ArrayList<>();
|
|
ArrayList<CharSequence> resultArrayNames = new ArrayList<>();
|
|
|
|
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);
|
|
if (!allowSelf && user.self || onlyMutual && !user.mutual_contact || ignoreUsers != null && ignoreUsers.indexOfKey(contact.user_id) >= 0) {
|
|
continue;
|
|
}
|
|
|
|
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;
|
|
}
|
|
if (UserObject.isReplyUser(user)) {
|
|
names[2] = LocaleController.getString("RepliesTitle", R.string.RepliesTitle).toLowerCase();
|
|
} else if (user.self) {
|
|
names[2] = LocaleController.getString("SavedMessages", R.string.SavedMessages).toLowerCase();
|
|
}
|
|
|
|
int found = 0;
|
|
for (String q : search) {
|
|
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)) {
|
|
found = 2;
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
updateSearchResults(searchReqIdFinal, resultArray, resultArrayNames);
|
|
});
|
|
});
|
|
}
|
|
|
|
private void updateSearchResults(int searchReqIdFinal, final ArrayList<Object> users, final ArrayList<CharSequence> names) {
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
if (searchReqIdFinal == searchReqId) {
|
|
searchResult = users;
|
|
searchResultNames = names;
|
|
searchAdapterHelper.mergeResults(users);
|
|
searchInProgress = false;
|
|
notifyDataSetChanged();
|
|
onSearchProgressChanged();
|
|
}
|
|
});
|
|
}
|
|
|
|
protected void onSearchProgressChanged() {
|
|
|
|
}
|
|
|
|
public boolean searchInProgress() {
|
|
return searchInProgress || searchAdapterHelper.isSearchInProgress();
|
|
}
|
|
|
|
@Override
|
|
public boolean isEnabled(RecyclerView.ViewHolder holder) {
|
|
int type = holder.getItemViewType();
|
|
return type == 0 || type == 2;
|
|
}
|
|
|
|
@Override
|
|
public int getItemCount() {
|
|
int count = searchResult.size();
|
|
int globalCount = searchAdapterHelper.getGlobalSearch().size();
|
|
if (globalCount != 0) {
|
|
count += globalCount + 1;
|
|
}
|
|
int phoneCount = searchAdapterHelper.getPhoneSearch().size();
|
|
if (phoneCount != 0) {
|
|
count += phoneCount;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
public boolean isGlobalSearch(int i) {
|
|
int localCount = searchResult.size();
|
|
int globalCount = searchAdapterHelper.getGlobalSearch().size();
|
|
int phoneCount = searchAdapterHelper.getPhoneSearch().size();
|
|
if (i >= 0 && i < localCount) {
|
|
return false;
|
|
} else if (i > localCount && i < localCount + phoneCount) {
|
|
return false;
|
|
} else if (i > localCount + phoneCount && i <= globalCount + phoneCount + localCount) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public Object getItem(int i) {
|
|
int localCount = searchResult.size();
|
|
int globalCount = searchAdapterHelper.getGlobalSearch().size();
|
|
int phoneCount = searchAdapterHelper.getPhoneSearch().size();
|
|
if (i >= 0 && i < localCount) {
|
|
return searchResult.get(i);
|
|
} 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
|
|
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
|
View view;
|
|
switch (viewType) {
|
|
case 0:
|
|
if (useUserCell) {
|
|
view = new UserCell(mContext, 1, 1, false);
|
|
if (checkedMap != null) {
|
|
((UserCell) view).setChecked(false, false);
|
|
}
|
|
} else {
|
|
view = new ProfileSearchCell(mContext);
|
|
}
|
|
break;
|
|
case 1:
|
|
view = new GraySectionCell(mContext);
|
|
break;
|
|
case 2:
|
|
default:
|
|
view = new TextCell(mContext, 16, false);
|
|
break;
|
|
}
|
|
return new RecyclerListView.Holder(view);
|
|
}
|
|
|
|
@Override
|
|
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
|
|
switch (holder.getItemViewType()) {
|
|
case 0: {
|
|
TLObject object = (TLObject) getItem(position);
|
|
if (object != null) {
|
|
int id = 0;
|
|
String un = null;
|
|
boolean self = false;
|
|
if (object instanceof TLRPC.User) {
|
|
un = ((TLRPC.User) object).username;
|
|
id = ((TLRPC.User) object).id;
|
|
self = ((TLRPC.User) object).self;
|
|
} else if (object instanceof TLRPC.Chat) {
|
|
un = ((TLRPC.Chat) object).username;
|
|
id = ((TLRPC.Chat) object).id;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
} else if (position > searchResult.size() && un != null) {
|
|
String foundUserName = searchAdapterHelper.getLastFoundUsername();
|
|
if (foundUserName != null && foundUserName.startsWith("@")) {
|
|
foundUserName = foundUserName.substring(1);
|
|
}
|
|
try {
|
|
int index;
|
|
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
|
|
spannableStringBuilder.append("@");
|
|
spannableStringBuilder.append(un);
|
|
if (foundUserName != null && (index = AndroidUtilities.indexOfIgnoreCase(un, foundUserName)) != -1) {
|
|
int len = foundUserName.length();
|
|
if (index == 0) {
|
|
len++;
|
|
} else {
|
|
index++;
|
|
}
|
|
spannableStringBuilder.setSpan(new ForegroundColorSpanThemable(Theme.key_windowBackgroundWhiteBlueText4), index, index + len, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
|
}
|
|
username = spannableStringBuilder;
|
|
} catch (Exception e) {
|
|
username = un;
|
|
FileLog.e(e);
|
|
}
|
|
}
|
|
|
|
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;
|
|
if (self) {
|
|
name = LocaleController.getString("SavedMessages", R.string.SavedMessages);
|
|
}
|
|
profileSearchCell.setData(object, null, name, username, false, self);
|
|
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;
|
|
}
|
|
}*/
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 1: {
|
|
GraySectionCell cell = (GraySectionCell) holder.itemView;
|
|
if (getItem(position) == null) {
|
|
cell.setText(LocaleController.getString("GlobalSearch", R.string.GlobalSearch));
|
|
} else {
|
|
cell.setText(LocaleController.getString("PhoneNumberSearch", R.string.PhoneNumberSearch));
|
|
}
|
|
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) {
|
|
Object item = getItem(i);
|
|
if (item == null) {
|
|
return 1;
|
|
} else if (item instanceof String) {
|
|
String str = (String) item;
|
|
if ("section".equals(str)) {
|
|
return 1;
|
|
} else {
|
|
return 2;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
}
|