mirror of https://github.com/NekoX-Dev/NekoX.git
2703 lines
127 KiB
Java
2703 lines
127 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.messenger;
|
|
|
|
import android.accounts.Account;
|
|
import android.accounts.AccountManager;
|
|
import android.content.ContentProviderOperation;
|
|
import android.content.ContentProviderResult;
|
|
import android.content.ContentResolver;
|
|
import android.content.ContentValues;
|
|
import android.content.SharedPreferences;
|
|
import android.content.pm.PackageManager;
|
|
import android.database.ContentObserver;
|
|
import android.database.Cursor;
|
|
import android.database.DatabaseUtils;
|
|
import android.net.Uri;
|
|
import android.os.Build;
|
|
import android.provider.BaseColumns;
|
|
import android.provider.ContactsContract;
|
|
import android.text.TextUtils;
|
|
import android.util.SparseArray;
|
|
|
|
import org.telegram.PhoneFormat.PhoneFormat;
|
|
import org.telegram.tgnet.ConnectionsManager;
|
|
import org.telegram.tgnet.TLRPC;
|
|
import org.telegram.ui.Components.Bulletin;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
import androidx.collection.LongSparseArray;
|
|
|
|
public class ContactsController extends BaseController {
|
|
|
|
private Account systemAccount;
|
|
private boolean loadingContacts;
|
|
private final Object loadContactsSync = new Object();
|
|
private boolean ignoreChanges;
|
|
private boolean contactsSyncInProgress;
|
|
private final Object observerLock = new Object();
|
|
public boolean contactsLoaded;
|
|
public boolean doneLoadingContacts;
|
|
private boolean contactsBookLoaded;
|
|
private boolean migratingContacts;
|
|
private String lastContactsVersions = "";
|
|
private ArrayList<Long> delayedContactsUpdate = new ArrayList<>();
|
|
private String inviteLink;
|
|
private boolean updatingInviteLink;
|
|
private HashMap<String, String> sectionsToReplace = new HashMap<>();
|
|
|
|
private int loadingGlobalSettings;
|
|
private int loadingDeleteInfo;
|
|
private int deleteAccountTTL;
|
|
private int[] loadingPrivacyInfo = new int[PRIVACY_RULES_TYPE_COUNT];
|
|
private ArrayList<TLRPC.PrivacyRule> lastseenPrivacyRules;
|
|
private ArrayList<TLRPC.PrivacyRule> groupPrivacyRules;
|
|
private ArrayList<TLRPC.PrivacyRule> callPrivacyRules;
|
|
private ArrayList<TLRPC.PrivacyRule> p2pPrivacyRules;
|
|
private ArrayList<TLRPC.PrivacyRule> profilePhotoPrivacyRules;
|
|
private ArrayList<TLRPC.PrivacyRule> forwardsPrivacyRules;
|
|
private ArrayList<TLRPC.PrivacyRule> phonePrivacyRules;
|
|
private ArrayList<TLRPC.PrivacyRule> addedByPhonePrivacyRules;
|
|
private TLRPC.TL_globalPrivacySettings globalPrivacySettings;
|
|
|
|
public final static int PRIVACY_RULES_TYPE_LASTSEEN = 0;
|
|
public final static int PRIVACY_RULES_TYPE_INVITE = 1;
|
|
public final static int PRIVACY_RULES_TYPE_CALLS = 2;
|
|
public final static int PRIVACY_RULES_TYPE_P2P = 3;
|
|
public final static int PRIVACY_RULES_TYPE_PHOTO = 4;
|
|
public final static int PRIVACY_RULES_TYPE_FORWARDS = 5;
|
|
public final static int PRIVACY_RULES_TYPE_PHONE = 6;
|
|
public final static int PRIVACY_RULES_TYPE_ADDED_BY_PHONE = 7;
|
|
|
|
public final static int PRIVACY_RULES_TYPE_COUNT = 8;
|
|
|
|
private class MyContentObserver extends ContentObserver {
|
|
|
|
private Runnable checkRunnable = () -> {
|
|
for (int a = 0; a < UserConfig.MAX_ACCOUNT_COUNT; a++) {
|
|
if (UserConfig.getInstance(a).isClientActivated()) {
|
|
ConnectionsManager.getInstance(a).resumeNetworkMaybe();
|
|
ContactsController.getInstance(a).checkContacts();
|
|
}
|
|
}
|
|
};
|
|
|
|
public MyContentObserver() {
|
|
super(null);
|
|
}
|
|
|
|
@Override
|
|
public void onChange(boolean selfChange) {
|
|
super.onChange(selfChange);
|
|
synchronized (observerLock) {
|
|
if (ignoreChanges) {
|
|
return;
|
|
}
|
|
}
|
|
Utilities.globalQueue.cancelRunnable(checkRunnable);
|
|
Utilities.globalQueue.postRunnable(checkRunnable, 500);
|
|
}
|
|
|
|
@Override
|
|
public boolean deliverSelfNotifications() {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static class Contact {
|
|
public int contact_id;
|
|
public String key;
|
|
public String provider;
|
|
public boolean isGoodProvider;
|
|
public ArrayList<String> phones = new ArrayList<>(4);
|
|
public ArrayList<String> phoneTypes = new ArrayList<>(4);
|
|
public ArrayList<String> shortPhones = new ArrayList<>(4);
|
|
public ArrayList<Integer> phoneDeleted = new ArrayList<>(4);
|
|
public String first_name;
|
|
public String last_name;
|
|
public boolean namesFilled;
|
|
public int imported;
|
|
public TLRPC.User user;
|
|
|
|
public String getLetter() {
|
|
return getLetter(first_name, last_name);
|
|
}
|
|
|
|
public static String getLetter(String first_name, String last_name) {
|
|
String key;
|
|
if (!TextUtils.isEmpty(first_name)) {
|
|
return first_name.substring(0, 1);
|
|
} else if (!TextUtils.isEmpty(last_name)) {
|
|
return last_name.substring(0, 1);
|
|
} else {
|
|
return "#";
|
|
}
|
|
}
|
|
}
|
|
|
|
private String[] projectionPhones = {
|
|
ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY,
|
|
ContactsContract.CommonDataKinds.Phone.NUMBER,
|
|
ContactsContract.CommonDataKinds.Phone.TYPE,
|
|
ContactsContract.CommonDataKinds.Phone.LABEL,
|
|
ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
|
|
ContactsContract.RawContacts.ACCOUNT_TYPE,
|
|
};
|
|
private String[] projectionNames = {
|
|
ContactsContract.CommonDataKinds.StructuredName.LOOKUP_KEY,
|
|
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
|
|
ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME,
|
|
ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME,
|
|
};
|
|
|
|
public HashMap<String, Contact> contactsBook = new HashMap<>();
|
|
public HashMap<String, Contact> contactsBookSPhones = new HashMap<>();
|
|
public ArrayList<Contact> phoneBookContacts = new ArrayList<>();
|
|
public HashMap<String, ArrayList<Object>> phoneBookSectionsDict = new HashMap<>();
|
|
public ArrayList<String> phoneBookSectionsArray = new ArrayList<>();
|
|
|
|
public ArrayList<TLRPC.TL_contact> contacts = new ArrayList<>();
|
|
public ConcurrentHashMap<Long, TLRPC.TL_contact> contactsDict = new ConcurrentHashMap<>(20, 1.0f, 2);
|
|
public HashMap<String, ArrayList<TLRPC.TL_contact>> usersSectionsDict = new HashMap<>();
|
|
public ArrayList<String> sortedUsersSectionsArray = new ArrayList<>();
|
|
|
|
public HashMap<String, ArrayList<TLRPC.TL_contact>> usersMutualSectionsDict = new HashMap<>();
|
|
public ArrayList<String> sortedUsersMutualSectionsArray = new ArrayList<>();
|
|
|
|
public HashMap<String, TLRPC.TL_contact> contactsByPhone = new HashMap<>();
|
|
public HashMap<String, TLRPC.TL_contact> contactsByShortPhone = new HashMap<>();
|
|
|
|
private int completedRequestsCount;
|
|
|
|
private static volatile ContactsController[] Instance = new ContactsController[UserConfig.MAX_ACCOUNT_COUNT];
|
|
public static ContactsController getInstance(int num) {
|
|
ContactsController localInstance = Instance[num];
|
|
if (localInstance == null) {
|
|
synchronized (ContactsController.class) {
|
|
localInstance = Instance[num];
|
|
if (localInstance == null) {
|
|
Instance[num] = localInstance = new ContactsController(num);
|
|
}
|
|
}
|
|
}
|
|
return localInstance;
|
|
}
|
|
|
|
public ContactsController(int instance) {
|
|
super(instance);
|
|
SharedPreferences preferences = MessagesController.getMainSettings(currentAccount);
|
|
if (preferences.getBoolean("needGetStatuses", false)) {
|
|
reloadContactsStatuses();
|
|
}
|
|
|
|
sectionsToReplace.put("À", "A");
|
|
sectionsToReplace.put("Á", "A");
|
|
sectionsToReplace.put("Ä", "A");
|
|
sectionsToReplace.put("Ù", "U");
|
|
sectionsToReplace.put("Ú", "U");
|
|
sectionsToReplace.put("Ü", "U");
|
|
sectionsToReplace.put("Ì", "I");
|
|
sectionsToReplace.put("Í", "I");
|
|
sectionsToReplace.put("Ï", "I");
|
|
sectionsToReplace.put("È", "E");
|
|
sectionsToReplace.put("É", "E");
|
|
sectionsToReplace.put("Ê", "E");
|
|
sectionsToReplace.put("Ë", "E");
|
|
sectionsToReplace.put("Ò", "O");
|
|
sectionsToReplace.put("Ó", "O");
|
|
sectionsToReplace.put("Ö", "O");
|
|
sectionsToReplace.put("Ç", "C");
|
|
sectionsToReplace.put("Ñ", "N");
|
|
sectionsToReplace.put("Ÿ", "Y");
|
|
sectionsToReplace.put("Ý", "Y");
|
|
sectionsToReplace.put("Ţ", "Y");
|
|
|
|
if (instance == 0) {
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
try {
|
|
if (hasContactsPermission()) {
|
|
ApplicationLoader.applicationContext.getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, new MyContentObserver());
|
|
}
|
|
} catch (Throwable ignore) {
|
|
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
public void cleanup() {
|
|
contactsBook.clear();
|
|
contactsBookSPhones.clear();
|
|
phoneBookContacts.clear();
|
|
contacts.clear();
|
|
contactsDict.clear();
|
|
usersSectionsDict.clear();
|
|
usersMutualSectionsDict.clear();
|
|
sortedUsersSectionsArray.clear();
|
|
sortedUsersMutualSectionsArray.clear();
|
|
delayedContactsUpdate.clear();
|
|
contactsByPhone.clear();
|
|
contactsByShortPhone.clear();
|
|
phoneBookSectionsDict.clear();
|
|
phoneBookSectionsArray.clear();
|
|
|
|
loadingContacts = false;
|
|
contactsSyncInProgress = false;
|
|
doneLoadingContacts = false;
|
|
contactsLoaded = false;
|
|
contactsBookLoaded = false;
|
|
lastContactsVersions = "";
|
|
loadingGlobalSettings = 0;
|
|
loadingDeleteInfo = 0;
|
|
deleteAccountTTL = 0;
|
|
Arrays.fill(loadingPrivacyInfo, 0);
|
|
lastseenPrivacyRules = null;
|
|
groupPrivacyRules = null;
|
|
callPrivacyRules = null;
|
|
p2pPrivacyRules = null;
|
|
profilePhotoPrivacyRules = null;
|
|
forwardsPrivacyRules = null;
|
|
phonePrivacyRules = null;
|
|
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
migratingContacts = false;
|
|
completedRequestsCount = 0;
|
|
});
|
|
}
|
|
|
|
public void checkInviteText() {
|
|
SharedPreferences preferences = MessagesController.getMainSettings(currentAccount);
|
|
inviteLink = preferences.getString("invitelink", null);
|
|
int time = preferences.getInt("invitelinktime", 0);
|
|
if (!updatingInviteLink && (inviteLink == null || Math.abs(System.currentTimeMillis() / 1000 - time) >= 86400)) {
|
|
updatingInviteLink = true;
|
|
TLRPC.TL_help_getInviteText req = new TLRPC.TL_help_getInviteText();
|
|
getConnectionsManager().sendRequest(req, (response, error) -> {
|
|
if (response != null) {
|
|
final TLRPC.TL_help_inviteText res = (TLRPC.TL_help_inviteText) response;
|
|
if (res.message.length() != 0) {
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
updatingInviteLink = false;
|
|
SharedPreferences preferences1 = MessagesController.getMainSettings(currentAccount);
|
|
SharedPreferences.Editor editor = preferences1.edit();
|
|
editor.putString("invitelink", inviteLink = res.message);
|
|
editor.putInt("invitelinktime", (int) (System.currentTimeMillis() / 1000));
|
|
editor.commit();
|
|
});
|
|
}
|
|
}
|
|
}, ConnectionsManager.RequestFlagFailOnServerErrors);
|
|
}
|
|
}
|
|
|
|
public String getInviteText(int contacts) {
|
|
String link = inviteLink == null ? "https://telegram.org/dl" : inviteLink;
|
|
if (contacts <= 1) {
|
|
return LocaleController.formatString("InviteText2", R.string.InviteText2, link);
|
|
} else {
|
|
try {
|
|
return String.format(LocaleController.getPluralString("InviteTextNum", contacts), contacts, link);
|
|
} catch (Exception e) {
|
|
return LocaleController.formatString("InviteText2", R.string.InviteText2, link);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void checkAppAccount() {
|
|
AccountManager am = AccountManager.get(ApplicationLoader.applicationContext);
|
|
try {
|
|
Account[] accounts = am.getAccountsByType("org.telegram.messenger");
|
|
systemAccount = null;
|
|
for (int a = 0; a < accounts.length; a++) {
|
|
Account acc = accounts[a];
|
|
boolean found = false;
|
|
for (int b = 0; b < UserConfig.MAX_ACCOUNT_COUNT; b++) {
|
|
TLRPC.User user = UserConfig.getInstance(b).getCurrentUser();
|
|
if (user != null) {
|
|
if (acc.name.equals("" + user.id)) {
|
|
if (b == currentAccount) {
|
|
systemAccount = acc;
|
|
}
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!found) {
|
|
try {
|
|
am.removeAccount(accounts[a], null, null);
|
|
} catch (Exception ignore) {
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
} catch (Throwable ignore) {
|
|
|
|
}
|
|
if (getUserConfig().isClientActivated()) {
|
|
readContacts();
|
|
if (systemAccount == null) {
|
|
try {
|
|
systemAccount = new Account("" + getUserConfig().getClientUserId(), "org.telegram.messenger");
|
|
am.addAccountExplicitly(systemAccount, "", null);
|
|
} catch (Exception ignore) {
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void deleteUnknownAppAccounts() {
|
|
try {
|
|
systemAccount = null;
|
|
AccountManager am = AccountManager.get(ApplicationLoader.applicationContext);
|
|
Account[] accounts = am.getAccountsByType("org.telegram.messenger");
|
|
for (int a = 0; a < accounts.length; a++) {
|
|
Account acc = accounts[a];
|
|
boolean found = false;
|
|
for (int b = 0; b < UserConfig.MAX_ACCOUNT_COUNT; b++) {
|
|
TLRPC.User user = UserConfig.getInstance(b).getCurrentUser();
|
|
if (user != null) {
|
|
if (acc.name.equals("" + user.id)) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!found) {
|
|
try {
|
|
am.removeAccount(accounts[a], null, null);
|
|
} catch (Exception ignore) {
|
|
|
|
}
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
e.printStackTrace();
|
|
}
|
|
}
|
|
|
|
public void checkContacts() {
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
if (checkContactsInternal()) {
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("detected contacts change");
|
|
}
|
|
performSyncPhoneBook(getContactsCopy(contactsBook), true, false, true, false, true, false);
|
|
}
|
|
});
|
|
}
|
|
|
|
public void forceImportContacts() {
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("force import contacts");
|
|
}
|
|
performSyncPhoneBook(new HashMap<>(), true, true, true, true, false, false);
|
|
});
|
|
}
|
|
|
|
public void syncPhoneBookByAlert(final HashMap<String, Contact> contacts, final boolean first, final boolean schedule, final boolean cancel) {
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("sync contacts by alert");
|
|
}
|
|
performSyncPhoneBook(contacts, true, first, schedule, false, false, cancel);
|
|
});
|
|
}
|
|
|
|
public void deleteAllContacts(final Runnable runnable) {
|
|
resetImportedContacts();
|
|
TLRPC.TL_contacts_deleteContacts req = new TLRPC.TL_contacts_deleteContacts();
|
|
for (int a = 0, size = contacts.size(); a < size; a++) {
|
|
TLRPC.TL_contact contact = contacts.get(a);
|
|
req.id.add(getMessagesController().getInputUser(contact.user_id));
|
|
}
|
|
getConnectionsManager().sendRequest(req, (response, error) -> {
|
|
if (error == null) {
|
|
contactsBookSPhones.clear();
|
|
contactsBook.clear();
|
|
completedRequestsCount = 0;
|
|
migratingContacts = false;
|
|
contactsSyncInProgress = false;
|
|
contactsLoaded = false;
|
|
loadingContacts = false;
|
|
contactsBookLoaded = false;
|
|
lastContactsVersions = "";
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
AccountManager am = AccountManager.get(ApplicationLoader.applicationContext);
|
|
try {
|
|
Account[] accounts = am.getAccountsByType("org.telegram.messenger");
|
|
systemAccount = null;
|
|
for (int a = 0; a < accounts.length; a++) {
|
|
Account acc = accounts[a];
|
|
for (int b = 0; b < UserConfig.MAX_ACCOUNT_COUNT; b++) {
|
|
TLRPC.User user = UserConfig.getInstance(b).getCurrentUser();
|
|
if (user != null) {
|
|
if (acc.name.equals("" + user.id)) {
|
|
am.removeAccount(acc, null, null);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} catch (Throwable ignore) {
|
|
|
|
}
|
|
try {
|
|
systemAccount = new Account("" + getUserConfig().getClientUserId(), "org.telegram.messenger");
|
|
am.addAccountExplicitly(systemAccount, "", null);
|
|
} catch (Exception ignore) {
|
|
|
|
}
|
|
getMessagesStorage().putCachedPhoneBook(new HashMap<>(), false, true);
|
|
getMessagesStorage().putContacts(new ArrayList<>(), true);
|
|
phoneBookContacts.clear();
|
|
contacts.clear();
|
|
contactsDict.clear();
|
|
usersSectionsDict.clear();
|
|
usersMutualSectionsDict.clear();
|
|
sortedUsersSectionsArray.clear();
|
|
phoneBookSectionsDict.clear();
|
|
phoneBookSectionsArray.clear();
|
|
delayedContactsUpdate.clear();
|
|
sortedUsersMutualSectionsArray.clear();
|
|
contactsByPhone.clear();
|
|
contactsByShortPhone.clear();
|
|
getNotificationCenter().postNotificationName(NotificationCenter.contactsDidLoad);
|
|
loadContacts(false, 0);
|
|
runnable.run();
|
|
});
|
|
} else {
|
|
AndroidUtilities.runOnUIThread(runnable);
|
|
}
|
|
});
|
|
}
|
|
|
|
public void resetImportedContacts() {
|
|
TLRPC.TL_contacts_resetSaved req = new TLRPC.TL_contacts_resetSaved();
|
|
getConnectionsManager().sendRequest(req, (response, error) -> {
|
|
|
|
});
|
|
}
|
|
|
|
private boolean checkContactsInternal() {
|
|
boolean reload = false;
|
|
try {
|
|
if (!hasContactsPermission()) {
|
|
return false;
|
|
}
|
|
ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver();
|
|
try (Cursor pCur = cr.query(ContactsContract.RawContacts.CONTENT_URI, new String[]{ContactsContract.RawContacts.VERSION}, null, null, null)) {
|
|
if (pCur != null) {
|
|
StringBuilder currentVersion = new StringBuilder();
|
|
while (pCur.moveToNext()) {
|
|
currentVersion.append(pCur.getString(pCur.getColumnIndex(ContactsContract.RawContacts.VERSION)));
|
|
}
|
|
String newContactsVersion = currentVersion.toString();
|
|
if (lastContactsVersions.length() != 0 && !lastContactsVersions.equals(newContactsVersion)) {
|
|
reload = true;
|
|
}
|
|
lastContactsVersions = newContactsVersion;
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e(e);
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e(e);
|
|
}
|
|
return reload;
|
|
}
|
|
|
|
public void readContacts() {
|
|
synchronized (loadContactsSync) {
|
|
if (loadingContacts) {
|
|
return;
|
|
}
|
|
loadingContacts = true;
|
|
}
|
|
|
|
Utilities.stageQueue.postRunnable(() -> {
|
|
if (!contacts.isEmpty() || contactsLoaded) {
|
|
synchronized (loadContactsSync) {
|
|
loadingContacts = false;
|
|
}
|
|
return;
|
|
}
|
|
loadContacts(true, 0);
|
|
});
|
|
}
|
|
|
|
private boolean isNotValidNameString(String src) {
|
|
if (TextUtils.isEmpty(src)) {
|
|
return true;
|
|
}
|
|
int count = 0;
|
|
for (int a = 0, len = src.length(); a < len; a++) {
|
|
char c = src.charAt(a);
|
|
if (c >= '0' && c <= '9') {
|
|
count++;
|
|
}
|
|
}
|
|
return count > 3;
|
|
}
|
|
|
|
private HashMap<String, Contact> readContactsFromPhoneBook() {
|
|
if (!getUserConfig().syncContacts) {
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("contacts sync disabled");
|
|
}
|
|
return new HashMap<>();
|
|
}
|
|
if (!hasContactsPermission()) {
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("app has no contacts permissions");
|
|
}
|
|
return new HashMap<>();
|
|
}
|
|
Cursor pCur = null;
|
|
HashMap<String, Contact> contactsMap = null;
|
|
try {
|
|
StringBuilder escaper = new StringBuilder();
|
|
|
|
ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver();
|
|
|
|
HashMap<String, Contact> shortContacts = new HashMap<>();
|
|
ArrayList<String> idsArr = new ArrayList<>();
|
|
pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projectionPhones, null, null, null);
|
|
|
|
int lastContactId = 1;
|
|
if (pCur != null) {
|
|
int count = pCur.getCount();
|
|
if (count > 0) {
|
|
contactsMap = new HashMap<>(count);
|
|
while (pCur.moveToNext()) {
|
|
String number = pCur.getString(1);
|
|
String accountType = pCur.getString(5);
|
|
if (accountType == null) {
|
|
accountType = "";
|
|
}
|
|
boolean isGoodAccountType = accountType.indexOf(".sim") != 0;
|
|
if (TextUtils.isEmpty(number)) {
|
|
continue;
|
|
}
|
|
number = PhoneFormat.stripExceptNumbers(number, true);
|
|
if (TextUtils.isEmpty(number)) {
|
|
continue;
|
|
}
|
|
|
|
String shortNumber = number;
|
|
|
|
if (number.startsWith("+")) {
|
|
shortNumber = number.substring(1);
|
|
}
|
|
|
|
String lookup_key = pCur.getString(0);
|
|
escaper.setLength(0);
|
|
DatabaseUtils.appendEscapedSQLString(escaper, lookup_key);
|
|
String key = escaper.toString();
|
|
|
|
Contact existingContact = shortContacts.get(shortNumber);
|
|
if (existingContact != null) {
|
|
if (!existingContact.isGoodProvider && !accountType.equals(existingContact.provider)) {
|
|
escaper.setLength(0);
|
|
DatabaseUtils.appendEscapedSQLString(escaper, existingContact.key);
|
|
idsArr.remove(escaper.toString());
|
|
idsArr.add(key);
|
|
existingContact.key = lookup_key;
|
|
existingContact.isGoodProvider = isGoodAccountType;
|
|
existingContact.provider = accountType;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (!idsArr.contains(key)) {
|
|
idsArr.add(key);
|
|
}
|
|
|
|
int type = pCur.getInt(2);
|
|
Contact contact = contactsMap.get(lookup_key);
|
|
if (contact == null) {
|
|
contact = new Contact();
|
|
String displayName = pCur.getString(4);
|
|
if (displayName == null) {
|
|
displayName = "";
|
|
} else {
|
|
displayName = displayName.trim();
|
|
}
|
|
if (isNotValidNameString(displayName)) {
|
|
contact.first_name = displayName;
|
|
contact.last_name = "";
|
|
} else {
|
|
int spaceIndex = displayName.lastIndexOf(' ');
|
|
if (spaceIndex != -1) {
|
|
contact.first_name = displayName.substring(0, spaceIndex).trim();
|
|
contact.last_name = displayName.substring(spaceIndex + 1).trim();
|
|
} else {
|
|
contact.first_name = displayName;
|
|
contact.last_name = "";
|
|
}
|
|
}
|
|
contact.provider = accountType;
|
|
contact.isGoodProvider = isGoodAccountType;
|
|
contact.key = lookup_key;
|
|
contact.contact_id = lastContactId++;
|
|
contactsMap.put(lookup_key, contact);
|
|
}
|
|
|
|
contact.shortPhones.add(shortNumber);
|
|
contact.phones.add(number);
|
|
contact.phoneDeleted.add(0);
|
|
|
|
if (type == ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM) {
|
|
String custom = pCur.getString(3);
|
|
contact.phoneTypes.add(custom != null ? custom : LocaleController.getString("PhoneMobile", R.string.PhoneMobile));
|
|
} else if (type == ContactsContract.CommonDataKinds.Phone.TYPE_HOME) {
|
|
contact.phoneTypes.add(LocaleController.getString("PhoneHome", R.string.PhoneHome));
|
|
} else if (type == ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE) {
|
|
contact.phoneTypes.add(LocaleController.getString("PhoneMobile", R.string.PhoneMobile));
|
|
} else if (type == ContactsContract.CommonDataKinds.Phone.TYPE_WORK) {
|
|
contact.phoneTypes.add(LocaleController.getString("PhoneWork", R.string.PhoneWork));
|
|
} else if (type == ContactsContract.CommonDataKinds.Phone.TYPE_MAIN) {
|
|
contact.phoneTypes.add(LocaleController.getString("PhoneMain", R.string.PhoneMain));
|
|
} else {
|
|
contact.phoneTypes.add(LocaleController.getString("PhoneOther", R.string.PhoneOther));
|
|
}
|
|
shortContacts.put(shortNumber, contact);
|
|
}
|
|
}
|
|
try {
|
|
pCur.close();
|
|
} catch (Exception ignore) {
|
|
|
|
}
|
|
pCur = null;
|
|
}
|
|
String ids = TextUtils.join(",", idsArr);
|
|
|
|
pCur = cr.query(ContactsContract.Data.CONTENT_URI, projectionNames, ContactsContract.CommonDataKinds.StructuredName.LOOKUP_KEY + " IN (" + ids + ") AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'", null, null);
|
|
if (pCur != null) {
|
|
while (pCur.moveToNext()) {
|
|
String lookup_key = pCur.getString(0);
|
|
String fname = pCur.getString(1);
|
|
String sname = pCur.getString(2);
|
|
String mname = pCur.getString(3);
|
|
Contact contact = contactsMap != null ? contactsMap.get(lookup_key) : null;
|
|
if (contact != null && !contact.namesFilled) {
|
|
if (contact.isGoodProvider) {
|
|
if (fname != null) {
|
|
contact.first_name = fname;
|
|
} else {
|
|
contact.first_name = "";
|
|
}
|
|
if (sname != null) {
|
|
contact.last_name = sname;
|
|
} else {
|
|
contact.last_name = "";
|
|
}
|
|
if (!TextUtils.isEmpty(mname)) {
|
|
if (!TextUtils.isEmpty(contact.first_name)) {
|
|
contact.first_name += " " + mname;
|
|
} else {
|
|
contact.first_name = mname;
|
|
}
|
|
}
|
|
} else {
|
|
if (!isNotValidNameString(fname) && (contact.first_name.contains(fname) || fname.contains(contact.first_name)) ||
|
|
!isNotValidNameString(sname) && (contact.last_name.contains(sname) || fname.contains(contact.last_name))) {
|
|
if (fname != null) {
|
|
contact.first_name = fname;
|
|
} else {
|
|
contact.first_name = "";
|
|
}
|
|
if (!TextUtils.isEmpty(mname)) {
|
|
if (!TextUtils.isEmpty(contact.first_name)) {
|
|
contact.first_name += " " + mname;
|
|
} else {
|
|
contact.first_name = mname;
|
|
}
|
|
}
|
|
if (sname != null) {
|
|
contact.last_name = sname;
|
|
} else {
|
|
contact.last_name = "";
|
|
}
|
|
}
|
|
}
|
|
contact.namesFilled = true;
|
|
}
|
|
}
|
|
try {
|
|
pCur.close();
|
|
} catch (Exception ignore) {
|
|
|
|
}
|
|
pCur = null;
|
|
}
|
|
} catch (Throwable e) {
|
|
FileLog.e(e);
|
|
if (contactsMap != null) {
|
|
contactsMap.clear();
|
|
}
|
|
} finally {
|
|
try {
|
|
if (pCur != null) {
|
|
pCur.close();
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e(e);
|
|
}
|
|
}
|
|
/*if (BuildVars.LOGS_ENABLED && contactsMap != null) {
|
|
for (HashMap.Entry<String, Contact> entry : contactsMap.entrySet()) {
|
|
Contact contact = entry.getValue();
|
|
FileLog.e("contact = " + contact.first_name + " " + contact.last_name);
|
|
if (contact.first_name.length() == 0 && contact.last_name.length() == 0 && contact.phones.size() > 0) {
|
|
FileLog.e("warning, empty name for contact = " + contact.key);
|
|
}
|
|
FileLog.e("phones:");
|
|
for (String s : contact.phones) {
|
|
FileLog.e("phone = " + s);
|
|
}
|
|
FileLog.e("short phones:");
|
|
for (String s : contact.shortPhones) {
|
|
FileLog.e("short phone = " + s);
|
|
}
|
|
}
|
|
}*/
|
|
return contactsMap != null ? contactsMap : new HashMap<>();
|
|
}
|
|
|
|
public HashMap<String, Contact> getContactsCopy(HashMap<String, Contact> original) {
|
|
HashMap<String, Contact> ret = new HashMap<>();
|
|
for (HashMap.Entry<String, Contact> entry : original.entrySet()) {
|
|
Contact copyContact = new Contact();
|
|
Contact originalContact = entry.getValue();
|
|
copyContact.phoneDeleted.addAll(originalContact.phoneDeleted);
|
|
copyContact.phones.addAll(originalContact.phones);
|
|
copyContact.phoneTypes.addAll(originalContact.phoneTypes);
|
|
copyContact.shortPhones.addAll(originalContact.shortPhones);
|
|
copyContact.first_name = originalContact.first_name;
|
|
copyContact.last_name = originalContact.last_name;
|
|
copyContact.contact_id = originalContact.contact_id;
|
|
copyContact.key = originalContact.key;
|
|
ret.put(copyContact.key, copyContact);
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
protected void migratePhoneBookToV7(final SparseArray<Contact> contactHashMap) {
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
if (migratingContacts) {
|
|
return;
|
|
}
|
|
migratingContacts = true;
|
|
HashMap<String, Contact> migratedMap = new HashMap<>();
|
|
HashMap<String, Contact> contactsMap = readContactsFromPhoneBook();
|
|
final HashMap<String, String> contactsBookShort = new HashMap<>();
|
|
for (HashMap.Entry<String, Contact> entry : contactsMap.entrySet()) {
|
|
Contact value = entry.getValue();
|
|
for (int a = 0; a < value.shortPhones.size(); a++) {
|
|
contactsBookShort.put(value.shortPhones.get(a), value.key);
|
|
}
|
|
}
|
|
for (int b = 0; b < contactHashMap.size(); b++) {
|
|
Contact value = contactHashMap.valueAt(b);
|
|
for (int a = 0; a < value.shortPhones.size(); a++) {
|
|
String sphone = value.shortPhones.get(a);
|
|
String key = contactsBookShort.get(sphone);
|
|
if (key != null) {
|
|
value.key = key;
|
|
migratedMap.put(key, value);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("migrated contacts " + migratedMap.size() + " of " + contactHashMap.size());
|
|
}
|
|
getMessagesStorage().putCachedPhoneBook(migratedMap, true, false);
|
|
});
|
|
}
|
|
|
|
protected void performSyncPhoneBook(final HashMap<String, Contact> contactHashMap, final boolean request, final boolean first, final boolean schedule, final boolean force, final boolean checkCount, final boolean canceled) {
|
|
if (!first && !contactsBookLoaded) {
|
|
return;
|
|
}
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
int newPhonebookContacts = 0;
|
|
int serverContactsInPhonebook = 0;
|
|
boolean disableDeletion = true; //disable contacts deletion, because phone numbers can't be compared due to different numbers format
|
|
/*if (schedule) {
|
|
try {
|
|
AccountManager am = AccountManager.get(ApplicationLoader.applicationContext);
|
|
Account[] accounts = am.getAccountsByType("org.telegram.account");
|
|
boolean recreateAccount = false;
|
|
if (getUserConfig().isClientActivated()) {
|
|
if (accounts.length != 1) {
|
|
FileLog.e("detected account deletion!");
|
|
currentAccount = new Account(getUserConfig().getCurrentUser().phone, "org.telegram.account");
|
|
am.addAccountExplicitly(currentAccount, "", null);
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
performWriteContactsToPhoneBook();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e(e);
|
|
}
|
|
}*/
|
|
|
|
HashMap<String, Contact> contactShortHashMap = new HashMap<>();
|
|
for (HashMap.Entry<String, Contact> entry : contactHashMap.entrySet()) {
|
|
Contact c = entry.getValue();
|
|
for (int a = 0; a < c.shortPhones.size(); a++) {
|
|
contactShortHashMap.put(c.shortPhones.get(a), c);
|
|
}
|
|
}
|
|
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("start read contacts from phone");
|
|
}
|
|
if (!schedule) {
|
|
checkContactsInternal();
|
|
}
|
|
final HashMap<String, Contact> contactsMap = readContactsFromPhoneBook();
|
|
final HashMap<String, ArrayList<Object>> phoneBookSectionsDictFinal = new HashMap<>();
|
|
final HashMap<String, Contact> phoneBookByShortPhonesFinal = new HashMap<>();
|
|
final ArrayList<String> phoneBookSectionsArrayFinal = new ArrayList<>();
|
|
|
|
for (HashMap.Entry<String, Contact> entry : contactsMap.entrySet()) {
|
|
Contact contact = entry.getValue();
|
|
for (int a = 0, size = contact.shortPhones.size(); a < size; a++) {
|
|
String phone = contact.shortPhones.get(a);
|
|
phoneBookByShortPhonesFinal.put(phone.substring(Math.max(0, phone.length() - 7)), contact);
|
|
}
|
|
|
|
String key = contact.getLetter();
|
|
ArrayList<Object> arrayList = phoneBookSectionsDictFinal.get(key);
|
|
if (arrayList == null) {
|
|
arrayList = new ArrayList<>();
|
|
phoneBookSectionsDictFinal.put(key, arrayList);
|
|
phoneBookSectionsArrayFinal.add(key);
|
|
}
|
|
arrayList.add(contact);
|
|
}
|
|
|
|
final HashMap<String, Contact> contactsBookShort = new HashMap<>();
|
|
int alreadyImportedContacts = contactHashMap.size();
|
|
|
|
ArrayList<TLRPC.TL_inputPhoneContact> toImport = new ArrayList<>();
|
|
if (!contactHashMap.isEmpty()) {
|
|
for (HashMap.Entry<String, Contact> pair : contactsMap.entrySet()) {
|
|
String id = pair.getKey();
|
|
Contact value = pair.getValue();
|
|
Contact existing = contactHashMap.get(id);
|
|
if (existing == null) {
|
|
for (int a = 0; a < value.shortPhones.size(); a++) {
|
|
Contact c = contactShortHashMap.get(value.shortPhones.get(a));
|
|
if (c != null) {
|
|
existing = c;
|
|
id = existing.key;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (existing != null) {
|
|
value.imported = existing.imported;
|
|
}
|
|
|
|
boolean nameChanged = existing != null && (!TextUtils.isEmpty(value.first_name) && !existing.first_name.equals(value.first_name) || !TextUtils.isEmpty(value.last_name) && !existing.last_name.equals(value.last_name));
|
|
if (existing == null || nameChanged) {
|
|
for (int a = 0; a < value.phones.size(); a++) {
|
|
String sphone = value.shortPhones.get(a);
|
|
String sphone9 = sphone.substring(Math.max(0, sphone.length() - 7));
|
|
contactsBookShort.put(sphone, value);
|
|
if (existing != null) {
|
|
int index = existing.shortPhones.indexOf(sphone);
|
|
if (index != -1) {
|
|
Integer deleted = existing.phoneDeleted.get(index);
|
|
value.phoneDeleted.set(a, deleted);
|
|
if (deleted == 1) {
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
if (request) {
|
|
if (!nameChanged) {
|
|
if (contactsByPhone.containsKey(sphone)) {
|
|
serverContactsInPhonebook++;
|
|
continue;
|
|
}
|
|
newPhonebookContacts++;
|
|
}
|
|
|
|
TLRPC.TL_inputPhoneContact imp = new TLRPC.TL_inputPhoneContact();
|
|
imp.client_id = value.contact_id;
|
|
imp.client_id |= ((long) a) << 32;
|
|
imp.first_name = value.first_name;
|
|
imp.last_name = value.last_name;
|
|
imp.phone = value.phones.get(a);
|
|
toImport.add(imp);
|
|
}
|
|
}
|
|
if (existing != null) {
|
|
contactHashMap.remove(id);
|
|
}
|
|
} else {
|
|
for (int a = 0; a < value.phones.size(); a++) {
|
|
String sphone = value.shortPhones.get(a);
|
|
String sphone9 = sphone.substring(Math.max(0, sphone.length() - 7));
|
|
contactsBookShort.put(sphone, value);
|
|
int index = existing.shortPhones.indexOf(sphone);
|
|
boolean emptyNameReimport = false;
|
|
if (request) {
|
|
TLRPC.TL_contact contact = contactsByPhone.get(sphone);
|
|
if (contact != null) {
|
|
TLRPC.User user = getMessagesController().getUser(contact.user_id);
|
|
if (user != null) {
|
|
serverContactsInPhonebook++;
|
|
if (TextUtils.isEmpty(user.first_name) && TextUtils.isEmpty(user.last_name) && (!TextUtils.isEmpty(value.first_name) || !TextUtils.isEmpty(value.last_name))) {
|
|
index = -1;
|
|
emptyNameReimport = true;
|
|
}
|
|
}
|
|
} else if (contactsByShortPhone.containsKey(sphone9)) {
|
|
serverContactsInPhonebook++;
|
|
}
|
|
}
|
|
if (index == -1) {
|
|
if (request) {
|
|
if (!emptyNameReimport) {
|
|
TLRPC.TL_contact contact = contactsByPhone.get(sphone);
|
|
if (contact != null) {
|
|
TLRPC.User user = getMessagesController().getUser(contact.user_id);
|
|
if (user != null) {
|
|
serverContactsInPhonebook++;
|
|
String firstName = user.first_name != null ? user.first_name : "";
|
|
String lastName = user.last_name != null ? user.last_name : "";
|
|
if (firstName.equals(value.first_name) && lastName.equals(value.last_name) || TextUtils.isEmpty(value.first_name) && TextUtils.isEmpty(value.last_name)) {
|
|
continue;
|
|
}
|
|
} else {
|
|
newPhonebookContacts++;
|
|
}
|
|
} else if (contactsByShortPhone.containsKey(sphone9)) {
|
|
serverContactsInPhonebook++;
|
|
}
|
|
}
|
|
|
|
TLRPC.TL_inputPhoneContact imp = new TLRPC.TL_inputPhoneContact();
|
|
imp.client_id = value.contact_id;
|
|
imp.client_id |= ((long) a) << 32;
|
|
imp.first_name = value.first_name;
|
|
imp.last_name = value.last_name;
|
|
imp.phone = value.phones.get(a);
|
|
toImport.add(imp);
|
|
}
|
|
} else {
|
|
value.phoneDeleted.set(a, existing.phoneDeleted.get(index));
|
|
existing.phones.remove(index);
|
|
existing.shortPhones.remove(index);
|
|
existing.phoneDeleted.remove(index);
|
|
existing.phoneTypes.remove(index);
|
|
}
|
|
}
|
|
if (existing.phones.isEmpty()) {
|
|
contactHashMap.remove(id);
|
|
}
|
|
}
|
|
}
|
|
if (!first && contactHashMap.isEmpty() && toImport.isEmpty() && alreadyImportedContacts == contactsMap.size()) {
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("contacts not changed!");
|
|
}
|
|
return;
|
|
}
|
|
if (request && !contactHashMap.isEmpty() && !contactsMap.isEmpty()) {
|
|
if (toImport.isEmpty()) {
|
|
getMessagesStorage().putCachedPhoneBook(contactsMap, false, false);
|
|
}
|
|
if (!disableDeletion && !contactHashMap.isEmpty()) {
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
/*if (BuildVars.DEBUG_VERSION) {
|
|
FileLog.e("need delete contacts");
|
|
for (HashMap.Entry<Integer, Contact> c : contactHashMap.entrySet()) {
|
|
Contact contact = c.getValue();
|
|
FileLog.e("delete contact " + contact.first_name + " " + contact.last_name);
|
|
for (String phone : contact.phones) {
|
|
FileLog.e(phone);
|
|
}
|
|
}
|
|
}*/
|
|
|
|
final ArrayList<TLRPC.User> toDelete = new ArrayList<>();
|
|
if (contactHashMap != null && !contactHashMap.isEmpty()) {
|
|
try {
|
|
final HashMap<String, TLRPC.User> contactsPhonesShort = new HashMap<>();
|
|
|
|
for (int a = 0; a < contacts.size(); a++) {
|
|
TLRPC.TL_contact value = contacts.get(a);
|
|
TLRPC.User user = getMessagesController().getUser(value.user_id);
|
|
if (user == null || TextUtils.isEmpty(user.phone)) {
|
|
continue;
|
|
}
|
|
contactsPhonesShort.put(user.phone, user);
|
|
}
|
|
int removed = 0;
|
|
for (HashMap.Entry<String, Contact> entry : contactHashMap.entrySet()) {
|
|
Contact contact = entry.getValue();
|
|
boolean was = false;
|
|
for (int a = 0; a < contact.shortPhones.size(); a++) {
|
|
String phone = contact.shortPhones.get(a);
|
|
TLRPC.User user = contactsPhonesShort.get(phone);
|
|
if (user != null) {
|
|
was = true;
|
|
toDelete.add(user);
|
|
contact.shortPhones.remove(a);
|
|
a--;
|
|
}
|
|
}
|
|
if (!was || contact.shortPhones.size() == 0) {
|
|
removed++;
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e(e);
|
|
}
|
|
}
|
|
|
|
if (!toDelete.isEmpty()) {
|
|
deleteContact(toDelete, false);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
} else if (request) {
|
|
for (HashMap.Entry<String, Contact> pair : contactsMap.entrySet()) {
|
|
Contact value = pair.getValue();
|
|
String key = pair.getKey();
|
|
for (int a = 0; a < value.phones.size(); a++) {
|
|
if (!force) {
|
|
String sphone = value.shortPhones.get(a);
|
|
String sphone9 = sphone.substring(Math.max(0, sphone.length() - 7));
|
|
TLRPC.TL_contact contact = contactsByPhone.get(sphone);
|
|
if (contact != null) {
|
|
TLRPC.User user = getMessagesController().getUser(contact.user_id);
|
|
if (user != null) {
|
|
serverContactsInPhonebook++;
|
|
String firstName = user.first_name != null ? user.first_name : "";
|
|
String lastName = user.last_name != null ? user.last_name : "";
|
|
if (firstName.equals(value.first_name) && lastName.equals(value.last_name) || TextUtils.isEmpty(value.first_name) && TextUtils.isEmpty(value.last_name)) {
|
|
continue;
|
|
}
|
|
}
|
|
} else if (contactsByShortPhone.containsKey(sphone9)) {
|
|
serverContactsInPhonebook++;
|
|
}
|
|
}
|
|
TLRPC.TL_inputPhoneContact imp = new TLRPC.TL_inputPhoneContact();
|
|
imp.client_id = value.contact_id;
|
|
imp.client_id |= ((long) a) << 32;
|
|
imp.first_name = value.first_name;
|
|
imp.last_name = value.last_name;
|
|
imp.phone = value.phones.get(a);
|
|
toImport.add(imp);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("done processing contacts");
|
|
}
|
|
|
|
if (request) {
|
|
if (!toImport.isEmpty()) {
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.e("start import contacts");
|
|
/*for (TLRPC.TL_inputPhoneContact contact : toImport) {
|
|
FileLog.e("add contact " + contact.first_name + " " + contact.last_name + " " + contact.phone);
|
|
}*/
|
|
}
|
|
|
|
final int checkType;
|
|
if (checkCount && newPhonebookContacts != 0) {
|
|
if (newPhonebookContacts >= 30) {
|
|
checkType = 1;
|
|
} else if (first && alreadyImportedContacts == 0 && contactsByPhone.size() - serverContactsInPhonebook > contactsByPhone.size() / 3 * 2) {
|
|
checkType = 2;
|
|
} else {
|
|
checkType = 0;
|
|
}
|
|
} else {
|
|
checkType = 0;
|
|
}
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("new phone book contacts " + newPhonebookContacts + " serverContactsInPhonebook " + serverContactsInPhonebook + " totalContacts " + contactsByPhone.size());
|
|
}
|
|
if (checkType != 0) {
|
|
AndroidUtilities.runOnUIThread(() -> getNotificationCenter().postNotificationName(NotificationCenter.hasNewContactsToImport, checkType, contactHashMap, first, schedule));
|
|
return;
|
|
} else if (canceled) {
|
|
Utilities.stageQueue.postRunnable(() -> {
|
|
contactsBookSPhones = contactsBookShort;
|
|
contactsBook = contactsMap;
|
|
contactsSyncInProgress = false;
|
|
contactsBookLoaded = true;
|
|
if (first) {
|
|
contactsLoaded = true;
|
|
}
|
|
if (!delayedContactsUpdate.isEmpty() && contactsLoaded) {
|
|
applyContactsUpdates(delayedContactsUpdate, null, null, null);
|
|
delayedContactsUpdate.clear();
|
|
}
|
|
getMessagesStorage().putCachedPhoneBook(contactsMap, false, false);
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
mergePhonebookAndTelegramContacts(phoneBookSectionsDictFinal, phoneBookSectionsArrayFinal, phoneBookByShortPhonesFinal);
|
|
updateUnregisteredContacts();
|
|
getNotificationCenter().postNotificationName(NotificationCenter.contactsDidLoad);
|
|
getNotificationCenter().postNotificationName(NotificationCenter.contactsImported);
|
|
});
|
|
});
|
|
return;
|
|
}
|
|
|
|
final boolean[] hasErrors = new boolean[]{false};
|
|
final HashMap<String, Contact> contactsMapToSave = new HashMap<>(contactsMap);
|
|
final SparseArray<String> contactIdToKey = new SparseArray<>();
|
|
for (HashMap.Entry<String, Contact> entry : contactsMapToSave.entrySet()) {
|
|
Contact value = entry.getValue();
|
|
contactIdToKey.put(value.contact_id, value.key);
|
|
}
|
|
completedRequestsCount = 0;
|
|
final int count = (int) Math.ceil(toImport.size() / 500.0);
|
|
for (int a = 0; a < count; a++) {
|
|
final TLRPC.TL_contacts_importContacts req = new TLRPC.TL_contacts_importContacts();
|
|
int start = a * 500;
|
|
int end = Math.min(start + 500, toImport.size());
|
|
req.contacts = new ArrayList<>(toImport.subList(start, end));
|
|
getConnectionsManager().sendRequest(req, (response, error) -> {
|
|
completedRequestsCount++;
|
|
if (error == null) {
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("contacts imported");
|
|
}
|
|
final TLRPC.TL_contacts_importedContacts res = (TLRPC.TL_contacts_importedContacts) response;
|
|
if (!res.retry_contacts.isEmpty()) {
|
|
for (int a1 = 0; a1 < res.retry_contacts.size(); a1++) {
|
|
long id = res.retry_contacts.get(a1);
|
|
contactsMapToSave.remove(contactIdToKey.get((int) id));
|
|
}
|
|
hasErrors[0] = true;
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("result has retry contacts");
|
|
}
|
|
}
|
|
for (int a1 = 0; a1 < res.popular_invites.size(); a1++) {
|
|
TLRPC.TL_popularContact popularContact = res.popular_invites.get(a1);
|
|
Contact contact = contactsMap.get(contactIdToKey.get((int) popularContact.client_id));
|
|
if (contact != null) {
|
|
contact.imported = popularContact.importers;
|
|
}
|
|
}
|
|
|
|
/*if (BuildVars.LOGS_ENABLED) {
|
|
for (TLRPC.User user : res.users) {
|
|
FileLog.e("received user " + user.first_name + " " + user.last_name + " " + user.phone);
|
|
}
|
|
}*/
|
|
getMessagesStorage().putUsersAndChats(res.users, null, true, true);
|
|
ArrayList<TLRPC.TL_contact> cArr = new ArrayList<>();
|
|
for (int a1 = 0; a1 < res.imported.size(); a1++) {
|
|
TLRPC.TL_contact contact = new TLRPC.TL_contact();
|
|
contact.user_id = res.imported.get(a1).user_id;
|
|
cArr.add(contact);
|
|
}
|
|
processLoadedContacts(cArr, res.users, 2);
|
|
} else {
|
|
for (int a1 = 0; a1 < req.contacts.size(); a1++) {
|
|
TLRPC.TL_inputPhoneContact contact = req.contacts.get(a1);
|
|
contactsMapToSave.remove(contactIdToKey.get((int) contact.client_id));
|
|
}
|
|
hasErrors[0] = true;
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("import contacts error " + error.text);
|
|
}
|
|
}
|
|
if (completedRequestsCount == count) {
|
|
if (!contactsMapToSave.isEmpty()) {
|
|
getMessagesStorage().putCachedPhoneBook(contactsMapToSave, false, false);
|
|
}
|
|
Utilities.stageQueue.postRunnable(() -> {
|
|
contactsBookSPhones = contactsBookShort;
|
|
contactsBook = contactsMap;
|
|
contactsSyncInProgress = false;
|
|
contactsBookLoaded = true;
|
|
if (first) {
|
|
contactsLoaded = true;
|
|
}
|
|
if (!delayedContactsUpdate.isEmpty() && contactsLoaded) {
|
|
applyContactsUpdates(delayedContactsUpdate, null, null, null);
|
|
delayedContactsUpdate.clear();
|
|
}
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
mergePhonebookAndTelegramContacts(phoneBookSectionsDictFinal, phoneBookSectionsArrayFinal, phoneBookByShortPhonesFinal);
|
|
getNotificationCenter().postNotificationName(NotificationCenter.contactsImported);
|
|
});
|
|
if (hasErrors[0]) {
|
|
Utilities.globalQueue.postRunnable(() -> getMessagesStorage().getCachedPhoneBook(true), 60000 * 5);
|
|
}
|
|
});
|
|
}
|
|
}, ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagCanCompress);
|
|
}
|
|
} else {
|
|
Utilities.stageQueue.postRunnable(() -> {
|
|
contactsBookSPhones = contactsBookShort;
|
|
contactsBook = contactsMap;
|
|
contactsSyncInProgress = false;
|
|
contactsBookLoaded = true;
|
|
if (first) {
|
|
contactsLoaded = true;
|
|
}
|
|
if (!delayedContactsUpdate.isEmpty() && contactsLoaded) {
|
|
applyContactsUpdates(delayedContactsUpdate, null, null, null);
|
|
delayedContactsUpdate.clear();
|
|
}
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
mergePhonebookAndTelegramContacts(phoneBookSectionsDictFinal, phoneBookSectionsArrayFinal, phoneBookByShortPhonesFinal);
|
|
updateUnregisteredContacts();
|
|
getNotificationCenter().postNotificationName(NotificationCenter.contactsDidLoad);
|
|
getNotificationCenter().postNotificationName(NotificationCenter.contactsImported);
|
|
});
|
|
});
|
|
}
|
|
} else {
|
|
Utilities.stageQueue.postRunnable(() -> {
|
|
contactsBookSPhones = contactsBookShort;
|
|
contactsBook = contactsMap;
|
|
contactsSyncInProgress = false;
|
|
contactsBookLoaded = true;
|
|
if (first) {
|
|
contactsLoaded = true;
|
|
}
|
|
if (!delayedContactsUpdate.isEmpty() && contactsLoaded) {
|
|
applyContactsUpdates(delayedContactsUpdate, null, null, null);
|
|
delayedContactsUpdate.clear();
|
|
}
|
|
AndroidUtilities.runOnUIThread(() -> mergePhonebookAndTelegramContacts(phoneBookSectionsDictFinal, phoneBookSectionsArrayFinal, phoneBookByShortPhonesFinal));
|
|
});
|
|
if (!contactsMap.isEmpty()) {
|
|
getMessagesStorage().putCachedPhoneBook(contactsMap, false, false);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
public boolean isLoadingContacts() {
|
|
synchronized (loadContactsSync) {
|
|
return loadingContacts;
|
|
}
|
|
}
|
|
|
|
private long getContactsHash(ArrayList<TLRPC.TL_contact> contacts) {
|
|
long acc = 0;
|
|
contacts = new ArrayList<>(contacts);
|
|
Collections.sort(contacts, (tl_contact, tl_contact2) -> {
|
|
if (tl_contact.user_id > tl_contact2.user_id) {
|
|
return 1;
|
|
} else if (tl_contact.user_id < tl_contact2.user_id) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
});
|
|
int count = contacts.size();
|
|
for (int a = -1; a < count; a++) {
|
|
if (a == -1) {
|
|
acc = MediaDataController.calcHash(acc, getUserConfig().contactsSavedCount);
|
|
} else {
|
|
TLRPC.TL_contact set = contacts.get(a);
|
|
acc = MediaDataController.calcHash(acc, set.user_id);
|
|
}
|
|
}
|
|
return acc;
|
|
}
|
|
|
|
public void loadContacts(boolean fromCache, final long hash) {
|
|
synchronized (loadContactsSync) {
|
|
loadingContacts = true;
|
|
}
|
|
if (fromCache) {
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("load contacts from cache");
|
|
}
|
|
getMessagesStorage().getContacts();
|
|
} else {
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("load contacts from server");
|
|
}
|
|
|
|
TLRPC.TL_contacts_getContacts req = new TLRPC.TL_contacts_getContacts();
|
|
req.hash = hash;
|
|
getConnectionsManager().sendRequest(req, (response, error) -> {
|
|
if (error == null) {
|
|
TLRPC.contacts_Contacts res = (TLRPC.contacts_Contacts) response;
|
|
if (hash != 0 && res instanceof TLRPC.TL_contacts_contactsNotModified) {
|
|
contactsLoaded = true;
|
|
if (!delayedContactsUpdate.isEmpty() && contactsBookLoaded) {
|
|
applyContactsUpdates(delayedContactsUpdate, null, null, null);
|
|
delayedContactsUpdate.clear();
|
|
}
|
|
getUserConfig().lastContactsSyncTime = (int) (System.currentTimeMillis() / 1000);
|
|
getUserConfig().saveConfig(false);
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
synchronized (loadContactsSync) {
|
|
loadingContacts = false;
|
|
}
|
|
getNotificationCenter().postNotificationName(NotificationCenter.contactsDidLoad);
|
|
});
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("load contacts don't change");
|
|
}
|
|
return;
|
|
} else {
|
|
getUserConfig().contactsSavedCount = res.saved_count;
|
|
getUserConfig().saveConfig(false);
|
|
}
|
|
processLoadedContacts(res.contacts, res.users, 0);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
public void processLoadedContacts(final ArrayList<TLRPC.TL_contact> contactsArr, final ArrayList<TLRPC.User> usersArr, final int from) {
|
|
//from: 0 - from server, 1 - from db, 2 - from imported contacts
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
getMessagesController().putUsers(usersArr, from == 1);
|
|
|
|
final LongSparseArray<TLRPC.User> usersDict = new LongSparseArray<>();
|
|
|
|
final boolean isEmpty = contactsArr.isEmpty();
|
|
|
|
if (from == 2 && !contacts.isEmpty()) {
|
|
for (int a = 0; a < contactsArr.size(); a++) {
|
|
TLRPC.TL_contact contact = contactsArr.get(a);
|
|
if (contactsDict.get(contact.user_id) != null) {
|
|
contactsArr.remove(a);
|
|
a--;
|
|
}
|
|
}
|
|
contactsArr.addAll(contacts);
|
|
}
|
|
|
|
for (int a = 0; a < contactsArr.size(); a++) {
|
|
TLRPC.User user = getMessagesController().getUser(contactsArr.get(a).user_id);
|
|
if (user != null) {
|
|
usersDict.put(user.id, user);
|
|
//if (BuildVars.DEBUG_VERSION) {
|
|
// FileLog.e("loaded user contact " + user.first_name + " " + user.last_name + " " + user.phone);
|
|
//}
|
|
}
|
|
}
|
|
|
|
Utilities.stageQueue.postRunnable(() -> {
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("done loading contacts");
|
|
}
|
|
if (from == 1 && (contactsArr.isEmpty() || Math.abs(System.currentTimeMillis() / 1000 - getUserConfig().lastContactsSyncTime) >= 24 * 60 * 60)) {
|
|
loadContacts(false, getContactsHash(contactsArr));
|
|
if (contactsArr.isEmpty()) {
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
doneLoadingContacts = true;
|
|
getNotificationCenter().postNotificationName(NotificationCenter.contactsDidLoad);
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
if (from == 0) {
|
|
getUserConfig().lastContactsSyncTime = (int) (System.currentTimeMillis() / 1000);
|
|
getUserConfig().saveConfig(false);
|
|
}
|
|
|
|
for (int a = 0; a < contactsArr.size(); a++) {
|
|
TLRPC.TL_contact contact = contactsArr.get(a);
|
|
if (usersDict.get(contact.user_id) == null && contact.user_id != getUserConfig().getClientUserId()) {
|
|
loadContacts(false, 0);
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("contacts are broken, load from server");
|
|
}
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
doneLoadingContacts = true;
|
|
getNotificationCenter().postNotificationName(NotificationCenter.contactsDidLoad);
|
|
});
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (from != 1) {
|
|
getMessagesStorage().putUsersAndChats(usersArr, null, true, true);
|
|
getMessagesStorage().putContacts(contactsArr, from != 2);
|
|
}
|
|
|
|
Collections.sort(contactsArr, (tl_contact, tl_contact2) -> {
|
|
TLRPC.User user1 = usersDict.get(tl_contact.user_id);
|
|
TLRPC.User user2 = usersDict.get(tl_contact2.user_id);
|
|
String name1 = UserObject.getFirstName(user1);
|
|
String name2 = UserObject.getFirstName(user2);
|
|
return name1.compareTo(name2);
|
|
});
|
|
|
|
final ConcurrentHashMap<Long, TLRPC.TL_contact> contactsDictionary = new ConcurrentHashMap<>(20, 1.0f, 2);
|
|
final HashMap<String, ArrayList<TLRPC.TL_contact>> sectionsDict = new HashMap<>();
|
|
final HashMap<String, ArrayList<TLRPC.TL_contact>> sectionsDictMutual = new HashMap<>();
|
|
final ArrayList<String> sortedSectionsArray = new ArrayList<>();
|
|
final ArrayList<String> sortedSectionsArrayMutual = new ArrayList<>();
|
|
HashMap<String, TLRPC.TL_contact> contactsByPhonesDict = null;
|
|
HashMap<String, TLRPC.TL_contact> contactsByPhonesShortDict = null;
|
|
|
|
if (!contactsBookLoaded) {
|
|
contactsByPhonesDict = new HashMap<>();
|
|
contactsByPhonesShortDict = new HashMap<>();
|
|
}
|
|
|
|
final HashMap<String, TLRPC.TL_contact> contactsByPhonesDictFinal = contactsByPhonesDict;
|
|
final HashMap<String, TLRPC.TL_contact> contactsByPhonesShortDictFinal = contactsByPhonesShortDict;
|
|
|
|
for (int a = 0; a < contactsArr.size(); a++) {
|
|
TLRPC.TL_contact value = contactsArr.get(a);
|
|
TLRPC.User user = usersDict.get(value.user_id);
|
|
if (user == null) {
|
|
continue;
|
|
}
|
|
contactsDictionary.put(value.user_id, value);
|
|
if (contactsByPhonesDict != null && !TextUtils.isEmpty(user.phone)) {
|
|
contactsByPhonesDict.put(user.phone, value);
|
|
contactsByPhonesShortDict.put(user.phone.substring(Math.max(0, user.phone.length() - 7)), value);
|
|
}
|
|
|
|
String key = UserObject.getFirstName(user);
|
|
if (key.length() > 1) {
|
|
key = key.substring(0, 1);
|
|
}
|
|
if (key.length() == 0) {
|
|
key = "#";
|
|
} else {
|
|
key = key.toUpperCase();
|
|
}
|
|
String replace = sectionsToReplace.get(key);
|
|
if (replace != null) {
|
|
key = replace;
|
|
}
|
|
ArrayList<TLRPC.TL_contact> arr = sectionsDict.get(key);
|
|
if (arr == null) {
|
|
arr = new ArrayList<>();
|
|
sectionsDict.put(key, arr);
|
|
sortedSectionsArray.add(key);
|
|
}
|
|
arr.add(value);
|
|
if (user.mutual_contact) {
|
|
arr = sectionsDictMutual.get(key);
|
|
if (arr == null) {
|
|
arr = new ArrayList<>();
|
|
sectionsDictMutual.put(key, arr);
|
|
sortedSectionsArrayMutual.add(key);
|
|
}
|
|
arr.add(value);
|
|
}
|
|
}
|
|
|
|
Collections.sort(sortedSectionsArray, (s, s2) -> {
|
|
char cv1 = s.charAt(0);
|
|
char cv2 = s2.charAt(0);
|
|
if (cv1 == '#') {
|
|
return 1;
|
|
} else if (cv2 == '#') {
|
|
return -1;
|
|
}
|
|
return s.compareTo(s2);
|
|
});
|
|
|
|
Collections.sort(sortedSectionsArrayMutual, (s, s2) -> {
|
|
char cv1 = s.charAt(0);
|
|
char cv2 = s2.charAt(0);
|
|
if (cv1 == '#') {
|
|
return 1;
|
|
} else if (cv2 == '#') {
|
|
return -1;
|
|
}
|
|
return s.compareTo(s2);
|
|
});
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
contacts = contactsArr;
|
|
contactsDict = contactsDictionary;
|
|
usersSectionsDict = sectionsDict;
|
|
usersMutualSectionsDict = sectionsDictMutual;
|
|
sortedUsersSectionsArray = sortedSectionsArray;
|
|
sortedUsersMutualSectionsArray = sortedSectionsArrayMutual;
|
|
doneLoadingContacts = true;
|
|
if (from != 2) {
|
|
synchronized (loadContactsSync) {
|
|
loadingContacts = false;
|
|
}
|
|
}
|
|
performWriteContactsToPhoneBook();
|
|
updateUnregisteredContacts();
|
|
|
|
getNotificationCenter().postNotificationName(NotificationCenter.contactsDidLoad);
|
|
|
|
if (from != 1 && !isEmpty) {
|
|
saveContactsLoadTime();
|
|
} else {
|
|
reloadContactsStatusesMaybe();
|
|
}
|
|
});
|
|
|
|
if (!delayedContactsUpdate.isEmpty() && contactsLoaded && contactsBookLoaded) {
|
|
applyContactsUpdates(delayedContactsUpdate, null, null, null);
|
|
delayedContactsUpdate.clear();
|
|
}
|
|
|
|
if (contactsByPhonesDictFinal != null) {
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
contactsByPhone = contactsByPhonesDictFinal;
|
|
contactsByShortPhone = contactsByPhonesShortDictFinal;
|
|
});
|
|
if (contactsSyncInProgress) {
|
|
return;
|
|
}
|
|
contactsSyncInProgress = true;
|
|
getMessagesStorage().getCachedPhoneBook(false);
|
|
});
|
|
} else {
|
|
contactsLoaded = true;
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
public boolean isContact(long userId) {
|
|
return contactsDict.get(userId) != null;
|
|
}
|
|
|
|
public void reloadContactsStatusesMaybe() {
|
|
try {
|
|
SharedPreferences preferences = MessagesController.getMainSettings(currentAccount);
|
|
long lastReloadStatusTime = preferences.getLong("lastReloadStatusTime", 0);
|
|
if (lastReloadStatusTime < System.currentTimeMillis() - 1000 * 60 * 60 * 3) {
|
|
reloadContactsStatuses();
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e(e);
|
|
}
|
|
}
|
|
|
|
private void saveContactsLoadTime() {
|
|
try {
|
|
SharedPreferences preferences = MessagesController.getMainSettings(currentAccount);
|
|
preferences.edit().putLong("lastReloadStatusTime", System.currentTimeMillis()).commit();
|
|
} catch (Exception e) {
|
|
FileLog.e(e);
|
|
}
|
|
}
|
|
|
|
private void mergePhonebookAndTelegramContacts(final HashMap<String, ArrayList<Object>> phoneBookSectionsDictFinal, final ArrayList<String> phoneBookSectionsArrayFinal, final HashMap<String, Contact> phoneBookByShortPhonesFinal) {
|
|
final ArrayList<TLRPC.TL_contact> contactsCopy = new ArrayList<>(contacts);
|
|
Utilities.globalQueue.postRunnable(() -> {
|
|
for (int a = 0, size = contactsCopy.size(); a < size; a++) {
|
|
TLRPC.TL_contact value = contactsCopy.get(a);
|
|
TLRPC.User user = getMessagesController().getUser(value.user_id);
|
|
if (user == null || TextUtils.isEmpty(user.phone)) {
|
|
continue;
|
|
}
|
|
String phone = user.phone.substring(Math.max(0, user.phone.length() - 7));
|
|
Contact contact = phoneBookByShortPhonesFinal.get(phone);
|
|
if (contact != null) {
|
|
if (contact.user == null) {
|
|
contact.user = user;
|
|
}
|
|
} else {
|
|
String key = Contact.getLetter(user.first_name, user.last_name);
|
|
ArrayList<Object> arrayList = phoneBookSectionsDictFinal.get(key);
|
|
if (arrayList == null) {
|
|
arrayList = new ArrayList<>();
|
|
phoneBookSectionsDictFinal.put(key, arrayList);
|
|
phoneBookSectionsArrayFinal.add(key);
|
|
}
|
|
arrayList.add(user);
|
|
}
|
|
}
|
|
for (ArrayList<Object> arrayList : phoneBookSectionsDictFinal.values()) {
|
|
Collections.sort(arrayList, (o1, o2) -> {
|
|
String name1;
|
|
String name2;
|
|
if (o1 instanceof TLRPC.User) {
|
|
TLRPC.User user = (TLRPC.User) o1;
|
|
name1 = ContactsController.formatName(user.first_name, user.last_name);
|
|
} else if (o1 instanceof Contact) {
|
|
Contact contact = (Contact) o1;
|
|
if (contact.user != null) {
|
|
name1 = ContactsController.formatName(contact.user.first_name, contact.user.last_name);
|
|
} else {
|
|
name1 = ContactsController.formatName(contact.first_name, contact.last_name);
|
|
}
|
|
} else {
|
|
name1 = "";
|
|
}
|
|
|
|
if (o2 instanceof TLRPC.User) {
|
|
TLRPC.User user = (TLRPC.User) o2;
|
|
name2 = ContactsController.formatName(user.first_name, user.last_name);
|
|
} else if (o2 instanceof Contact) {
|
|
Contact contact = (Contact) o2;
|
|
if (contact.user != null) {
|
|
name2 = ContactsController.formatName(contact.user.first_name, contact.user.last_name);
|
|
} else {
|
|
name2 = ContactsController.formatName(contact.first_name, contact.last_name);
|
|
}
|
|
} else {
|
|
name2 = "";
|
|
}
|
|
|
|
return name1.compareTo(name2);
|
|
});
|
|
}
|
|
Collections.sort(phoneBookSectionsArrayFinal, (s, s2) -> {
|
|
char cv1 = s.charAt(0);
|
|
char cv2 = s2.charAt(0);
|
|
if (cv1 == '#') {
|
|
return 1;
|
|
} else if (cv2 == '#') {
|
|
return -1;
|
|
}
|
|
return s.compareTo(s2);
|
|
});
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
phoneBookSectionsArray = phoneBookSectionsArrayFinal;
|
|
phoneBookSectionsDict = phoneBookSectionsDictFinal;
|
|
});
|
|
});
|
|
}
|
|
|
|
private void updateUnregisteredContacts() {
|
|
final HashMap<String, TLRPC.TL_contact> contactsPhonesShort = new HashMap<>();
|
|
|
|
for (int a = 0, size = contacts.size(); a < size; a++) {
|
|
TLRPC.TL_contact value = contacts.get(a);
|
|
TLRPC.User user = getMessagesController().getUser(value.user_id);
|
|
if (user == null || TextUtils.isEmpty(user.phone)) {
|
|
continue;
|
|
}
|
|
contactsPhonesShort.put(user.phone, value);
|
|
}
|
|
|
|
final ArrayList<Contact> sortedPhoneBookContacts = new ArrayList<>();
|
|
for (HashMap.Entry<String, Contact> pair : contactsBook.entrySet()) {
|
|
Contact value = pair.getValue();
|
|
|
|
boolean skip = false;
|
|
for (int a = 0; a < value.phones.size(); a++) {
|
|
String sphone = value.shortPhones.get(a);
|
|
if (contactsPhonesShort.containsKey(sphone) || value.phoneDeleted.get(a) == 1) {
|
|
skip = true;
|
|
break;
|
|
}
|
|
}
|
|
if (skip) {
|
|
continue;
|
|
}
|
|
|
|
sortedPhoneBookContacts.add(value);
|
|
}
|
|
Collections.sort(sortedPhoneBookContacts, (contact, contact2) -> {
|
|
String toComapre1 = contact.first_name;
|
|
if (toComapre1.length() == 0) {
|
|
toComapre1 = contact.last_name;
|
|
}
|
|
String toComapre2 = contact2.first_name;
|
|
if (toComapre2.length() == 0) {
|
|
toComapre2 = contact2.last_name;
|
|
}
|
|
return toComapre1.compareTo(toComapre2);
|
|
});
|
|
|
|
phoneBookContacts = sortedPhoneBookContacts;
|
|
}
|
|
|
|
private void buildContactsSectionsArrays(boolean sort) {
|
|
if (sort) {
|
|
Collections.sort(contacts, (tl_contact, tl_contact2) -> {
|
|
TLRPC.User user1 = getMessagesController().getUser(tl_contact.user_id);
|
|
TLRPC.User user2 = getMessagesController().getUser(tl_contact2.user_id);
|
|
String name1 = UserObject.getFirstName(user1);
|
|
String name2 = UserObject.getFirstName(user2);
|
|
return name1.compareTo(name2);
|
|
});
|
|
}
|
|
|
|
final HashMap<String, ArrayList<TLRPC.TL_contact>> sectionsDict = new HashMap<>();
|
|
final ArrayList<String> sortedSectionsArray = new ArrayList<>();
|
|
|
|
for (int a = 0; a < contacts.size(); a++) {
|
|
TLRPC.TL_contact value = contacts.get(a);
|
|
TLRPC.User user = getMessagesController().getUser(value.user_id);
|
|
if (user == null) {
|
|
continue;
|
|
}
|
|
|
|
String key = UserObject.getFirstName(user);
|
|
if (key.length() > 1) {
|
|
key = key.substring(0, 1);
|
|
}
|
|
if (key.length() == 0) {
|
|
key = "#";
|
|
} else {
|
|
key = key.toUpperCase();
|
|
}
|
|
String replace = sectionsToReplace.get(key);
|
|
if (replace != null) {
|
|
key = replace;
|
|
}
|
|
ArrayList<TLRPC.TL_contact> arr = sectionsDict.get(key);
|
|
if (arr == null) {
|
|
arr = new ArrayList<>();
|
|
sectionsDict.put(key, arr);
|
|
sortedSectionsArray.add(key);
|
|
}
|
|
arr.add(value);
|
|
}
|
|
|
|
Collections.sort(sortedSectionsArray, (s, s2) -> {
|
|
char cv1 = s.charAt(0);
|
|
char cv2 = s2.charAt(0);
|
|
if (cv1 == '#') {
|
|
return 1;
|
|
} else if (cv2 == '#') {
|
|
return -1;
|
|
}
|
|
return s.compareTo(s2);
|
|
});
|
|
|
|
usersSectionsDict = sectionsDict;
|
|
sortedUsersSectionsArray = sortedSectionsArray;
|
|
}
|
|
|
|
private boolean hasContactsPermission() {
|
|
if (Build.VERSION.SDK_INT >= 23) {
|
|
return ApplicationLoader.applicationContext.checkSelfPermission(android.Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED;
|
|
}
|
|
Cursor cursor = null;
|
|
try {
|
|
ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver();
|
|
cursor = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projectionPhones, null, null, null);
|
|
if (cursor == null || cursor.getCount() == 0) {
|
|
return false;
|
|
}
|
|
} catch (Throwable e) {
|
|
FileLog.e(e);
|
|
} finally {
|
|
try {
|
|
if (cursor != null) {
|
|
cursor.close();
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e(e);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
private void performWriteContactsToPhoneBookInternal(ArrayList<TLRPC.TL_contact> contactsArray) {
|
|
Cursor cursor = null;
|
|
try {
|
|
if (!hasContactsPermission()) {
|
|
return;
|
|
}
|
|
final SharedPreferences settings = MessagesController.getMainSettings(currentAccount);
|
|
final boolean forceUpdate = !settings.getBoolean("contacts_updated_v7", false);
|
|
if (forceUpdate) {
|
|
settings.edit().putBoolean("contacts_updated_v7", true).commit();
|
|
}
|
|
final ContentResolver contentResolver = ApplicationLoader.applicationContext.getContentResolver();
|
|
Uri rawContactUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, systemAccount.name).appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, systemAccount.type).build();
|
|
cursor = contentResolver.query(rawContactUri, new String[]{BaseColumns._ID, ContactsContract.RawContacts.SYNC2}, null, null, null);
|
|
LongSparseArray<Long> bookContacts = new LongSparseArray<>();
|
|
if (cursor != null) {
|
|
while (cursor.moveToNext()) {
|
|
bookContacts.put(cursor.getLong(1), cursor.getLong(0));
|
|
}
|
|
cursor.close();
|
|
cursor = null;
|
|
|
|
for (int a = 0; a < contactsArray.size(); a++) {
|
|
TLRPC.TL_contact u = contactsArray.get(a);
|
|
if (forceUpdate || bookContacts.indexOfKey(u.user_id) < 0) {
|
|
addContactToPhoneBook(getMessagesController().getUser(u.user_id), forceUpdate);
|
|
}
|
|
}
|
|
}
|
|
} catch (Exception e) {
|
|
FileLog.e(e);
|
|
} finally {
|
|
if (cursor != null) {
|
|
cursor.close();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void performWriteContactsToPhoneBook() {
|
|
final ArrayList<TLRPC.TL_contact> contactsArray = new ArrayList<>(contacts);
|
|
Utilities.phoneBookQueue.postRunnable(() -> performWriteContactsToPhoneBookInternal(contactsArray));
|
|
}
|
|
|
|
private void applyContactsUpdates(ArrayList<Long> ids, ConcurrentHashMap<Long, TLRPC.User> userDict, ArrayList<TLRPC.TL_contact> newC, ArrayList<Long> contactsTD) {
|
|
if (newC == null || contactsTD == null) {
|
|
newC = new ArrayList<>();
|
|
contactsTD = new ArrayList<>();
|
|
for (int a = 0; a < ids.size(); a++) {
|
|
Long uid = ids.get(a);
|
|
if (uid > 0) {
|
|
TLRPC.TL_contact contact = new TLRPC.TL_contact();
|
|
contact.user_id = uid;
|
|
newC.add(contact);
|
|
} else if (uid < 0) {
|
|
contactsTD.add(-uid);
|
|
}
|
|
}
|
|
}
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("process update - contacts add = " + newC.size() + " delete = " + contactsTD.size());
|
|
}
|
|
|
|
StringBuilder toAdd = new StringBuilder();
|
|
StringBuilder toDelete = new StringBuilder();
|
|
boolean reloadContacts = false;
|
|
|
|
for (int a = 0; a < newC.size(); a++) {
|
|
TLRPC.TL_contact newContact = newC.get(a);
|
|
TLRPC.User user = null;
|
|
if (userDict != null) {
|
|
user = userDict.get(newContact.user_id);
|
|
}
|
|
if (user == null) {
|
|
user = getMessagesController().getUser(newContact.user_id);
|
|
} else {
|
|
getMessagesController().putUser(user, true);
|
|
}
|
|
if (user == null || TextUtils.isEmpty(user.phone)) {
|
|
reloadContacts = true;
|
|
continue;
|
|
}
|
|
|
|
Contact contact = contactsBookSPhones.get(user.phone);
|
|
if (contact != null) {
|
|
int index = contact.shortPhones.indexOf(user.phone);
|
|
if (index != -1) {
|
|
contact.phoneDeleted.set(index, 0);
|
|
}
|
|
}
|
|
if (toAdd.length() != 0) {
|
|
toAdd.append(",");
|
|
}
|
|
toAdd.append(user.phone);
|
|
}
|
|
|
|
for (int a = 0; a < contactsTD.size(); a++) {
|
|
final Long uid = contactsTD.get(a);
|
|
Utilities.phoneBookQueue.postRunnable(() -> deleteContactFromPhoneBook(uid));
|
|
|
|
TLRPC.User user = null;
|
|
if (userDict != null) {
|
|
user = userDict.get(uid);
|
|
}
|
|
if (user == null) {
|
|
user = getMessagesController().getUser(uid);
|
|
} else {
|
|
getMessagesController().putUser(user, true);
|
|
}
|
|
if (user == null) {
|
|
reloadContacts = true;
|
|
continue;
|
|
}
|
|
|
|
if (!TextUtils.isEmpty(user.phone)) {
|
|
Contact contact = contactsBookSPhones.get(user.phone);
|
|
if (contact != null) {
|
|
int index = contact.shortPhones.indexOf(user.phone);
|
|
if (index != -1) {
|
|
contact.phoneDeleted.set(index, 1);
|
|
}
|
|
}
|
|
if (toDelete.length() != 0) {
|
|
toDelete.append(",");
|
|
}
|
|
toDelete.append(user.phone);
|
|
}
|
|
}
|
|
|
|
if (toAdd.length() != 0 || toDelete.length() != 0) {
|
|
getMessagesStorage().applyPhoneBookUpdates(toAdd.toString(), toDelete.toString());
|
|
}
|
|
|
|
if (reloadContacts) {
|
|
Utilities.stageQueue.postRunnable(() -> loadContacts(false, 0));
|
|
} else {
|
|
final ArrayList<TLRPC.TL_contact> newContacts = newC;
|
|
final ArrayList<Long> contactsToDelete = contactsTD;
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
for (int a = 0; a < newContacts.size(); a++) {
|
|
TLRPC.TL_contact contact = newContacts.get(a);
|
|
if (contactsDict.get(contact.user_id) == null) {
|
|
contacts.add(contact);
|
|
contactsDict.put(contact.user_id, contact);
|
|
}
|
|
}
|
|
for (int a = 0; a < contactsToDelete.size(); a++) {
|
|
Long uid = contactsToDelete.get(a);
|
|
TLRPC.TL_contact contact = contactsDict.get(uid);
|
|
if (contact != null) {
|
|
contacts.remove(contact);
|
|
contactsDict.remove(uid);
|
|
}
|
|
}
|
|
if (!newContacts.isEmpty()) {
|
|
updateUnregisteredContacts();
|
|
performWriteContactsToPhoneBook();
|
|
}
|
|
performSyncPhoneBook(getContactsCopy(contactsBook), false, false, false, false, true, false);
|
|
buildContactsSectionsArrays(!newContacts.isEmpty());
|
|
getNotificationCenter().postNotificationName(NotificationCenter.contactsDidLoad);
|
|
});
|
|
}
|
|
}
|
|
|
|
public void processContactsUpdates(ArrayList<Long> ids, ConcurrentHashMap<Long, TLRPC.User> userDict) {
|
|
final ArrayList<TLRPC.TL_contact> newContacts = new ArrayList<>();
|
|
final ArrayList<Long> contactsToDelete = new ArrayList<>();
|
|
for (Long uid : ids) {
|
|
if (uid > 0) {
|
|
TLRPC.TL_contact contact = new TLRPC.TL_contact();
|
|
contact.user_id = uid;
|
|
newContacts.add(contact);
|
|
if (!delayedContactsUpdate.isEmpty()) {
|
|
int idx = delayedContactsUpdate.indexOf(-uid);
|
|
if (idx != -1) {
|
|
delayedContactsUpdate.remove(idx);
|
|
}
|
|
}
|
|
} else if (uid < 0) {
|
|
contactsToDelete.add(-uid);
|
|
if (!delayedContactsUpdate.isEmpty()) {
|
|
int idx = delayedContactsUpdate.indexOf(-uid);
|
|
if (idx != -1) {
|
|
delayedContactsUpdate.remove(idx);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!contactsToDelete.isEmpty()) {
|
|
getMessagesStorage().deleteContacts(contactsToDelete);
|
|
}
|
|
if (!newContacts.isEmpty()) {
|
|
getMessagesStorage().putContacts(newContacts, false);
|
|
}
|
|
if (!contactsLoaded || !contactsBookLoaded) {
|
|
delayedContactsUpdate.addAll(ids);
|
|
if (BuildVars.LOGS_ENABLED) {
|
|
FileLog.d("delay update - contacts add = " + newContacts.size() + " delete = " + contactsToDelete.size());
|
|
}
|
|
} else {
|
|
applyContactsUpdates(ids, userDict, newContacts, contactsToDelete);
|
|
}
|
|
}
|
|
|
|
public long addContactToPhoneBook(TLRPC.User user, boolean check) {
|
|
if (systemAccount == null || user == null) {
|
|
return -1;
|
|
}
|
|
if (!hasContactsPermission()) {
|
|
return -1;
|
|
}
|
|
long res = -1;
|
|
synchronized (observerLock) {
|
|
ignoreChanges = true;
|
|
}
|
|
ContentResolver contentResolver = ApplicationLoader.applicationContext.getContentResolver();
|
|
if (check) {
|
|
try {
|
|
Uri rawContactUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, systemAccount.name).appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, systemAccount.type).build();
|
|
int value = contentResolver.delete(rawContactUri, ContactsContract.RawContacts.SYNC2 + " = " + user.id, null);
|
|
} catch (Exception ignore) {
|
|
|
|
}
|
|
}
|
|
|
|
ArrayList<ContentProviderOperation> query = new ArrayList<>();
|
|
|
|
ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI);
|
|
builder.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, systemAccount.name);
|
|
builder.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, systemAccount.type);
|
|
builder.withValue(ContactsContract.RawContacts.SYNC1, TextUtils.isEmpty(user.phone) ? "" : user.phone);
|
|
builder.withValue(ContactsContract.RawContacts.SYNC2, user.id);
|
|
query.add(builder.build());
|
|
|
|
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
|
|
builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0);
|
|
builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
|
|
builder.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, user.first_name);
|
|
builder.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, user.last_name);
|
|
query.add(builder.build());
|
|
|
|
// builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
|
|
// builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0);
|
|
// builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
|
|
// builder.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, "+" + user.phone);
|
|
// builder.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
|
|
// query.add(builder.build());
|
|
|
|
final String phoneOrName = TextUtils.isEmpty(user.phone) ? ContactsController.formatName(user.first_name, user.last_name) : "+" + user.phone;
|
|
|
|
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
|
|
builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0);
|
|
builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.profile");
|
|
builder.withValue(ContactsContract.Data.DATA1, user.id);
|
|
builder.withValue(ContactsContract.Data.DATA2, "Telegram Profile");
|
|
builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutMessage", R.string.ContactShortcutMessage, phoneOrName));
|
|
builder.withValue(ContactsContract.Data.DATA4, user.id);
|
|
query.add(builder.build());
|
|
|
|
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
|
|
builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0);
|
|
builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.call");
|
|
builder.withValue(ContactsContract.Data.DATA1, user.id);
|
|
builder.withValue(ContactsContract.Data.DATA2, "Telegram Voice Call");
|
|
builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutVoiceCall", R.string.ContactShortcutVoiceCall, phoneOrName));
|
|
builder.withValue(ContactsContract.Data.DATA4, user.id);
|
|
query.add(builder.build());
|
|
|
|
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
|
|
builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0);
|
|
builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.call.video");
|
|
builder.withValue(ContactsContract.Data.DATA1, user.id);
|
|
builder.withValue(ContactsContract.Data.DATA2, "Telegram Video Call");
|
|
builder.withValue(ContactsContract.Data.DATA3, LocaleController.formatString("ContactShortcutVideoCall", R.string.ContactShortcutVideoCall, phoneOrName));
|
|
builder.withValue(ContactsContract.Data.DATA4, user.id);
|
|
query.add(builder.build());
|
|
|
|
try {
|
|
ContentProviderResult[] result = contentResolver.applyBatch(ContactsContract.AUTHORITY, query);
|
|
if (result != null && result.length > 0 && result[0].uri != null) {
|
|
res = Long.parseLong(result[0].uri.getLastPathSegment());
|
|
}
|
|
} catch (Exception ignore) {
|
|
|
|
}
|
|
synchronized (observerLock) {
|
|
ignoreChanges = false;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
private void deleteContactFromPhoneBook(long uid) {
|
|
if (!hasContactsPermission()) {
|
|
return;
|
|
}
|
|
synchronized (observerLock) {
|
|
ignoreChanges = true;
|
|
}
|
|
try {
|
|
ContentResolver contentResolver = ApplicationLoader.applicationContext.getContentResolver();
|
|
Uri rawContactUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, systemAccount.name).appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, systemAccount.type).build();
|
|
int value = contentResolver.delete(rawContactUri, ContactsContract.RawContacts.SYNC2 + " = " + uid, null);
|
|
} catch (Exception e) {
|
|
FileLog.e(e);
|
|
}
|
|
synchronized (observerLock) {
|
|
ignoreChanges = false;
|
|
}
|
|
}
|
|
|
|
protected void markAsContacted(final String contactId) {
|
|
if (contactId == null) {
|
|
return;
|
|
}
|
|
Utilities.phoneBookQueue.postRunnable(() -> {
|
|
Uri uri = Uri.parse(contactId);
|
|
ContentValues values = new ContentValues();
|
|
values.put(ContactsContract.Contacts.LAST_TIME_CONTACTED, System.currentTimeMillis());
|
|
ContentResolver cr = ApplicationLoader.applicationContext.getContentResolver();
|
|
cr.update(uri, values, null, null);
|
|
});
|
|
}
|
|
|
|
public void addContact(TLRPC.User user, boolean exception) {
|
|
if (user == null) {
|
|
return;
|
|
}
|
|
|
|
TLRPC.TL_contacts_addContact req = new TLRPC.TL_contacts_addContact();
|
|
req.id = getMessagesController().getInputUser(user);
|
|
req.first_name = user.first_name;
|
|
req.last_name = user.last_name;
|
|
req.phone = user.phone;
|
|
req.add_phone_privacy_exception = exception;
|
|
if (req.phone == null) {
|
|
req.phone = "";
|
|
} else if (req.phone.length() > 0 && !req.phone.startsWith("+")) {
|
|
req.phone = "+" + req.phone;
|
|
}
|
|
getConnectionsManager().sendRequest(req, (response, error) -> {
|
|
if (error != null) {
|
|
return;
|
|
}
|
|
final TLRPC.Updates res = (TLRPC.Updates) response;
|
|
getMessagesController().processUpdates(res, false);
|
|
|
|
/*if (BuildVars.DEBUG_VERSION) {
|
|
for (TLRPC.User user : res.users) {
|
|
FileLog.e("received user " + user.first_name + " " + user.last_name + " " + user.phone);
|
|
}
|
|
}*/
|
|
|
|
for (int a = 0; a < res.users.size(); a++) {
|
|
final TLRPC.User u = res.users.get(a);
|
|
if (u.id != user.id) {
|
|
continue;
|
|
}
|
|
Utilities.phoneBookQueue.postRunnable(() -> addContactToPhoneBook(u, true));
|
|
TLRPC.TL_contact newContact = new TLRPC.TL_contact();
|
|
newContact.user_id = u.id;
|
|
ArrayList<TLRPC.TL_contact> arrayList = new ArrayList<>();
|
|
arrayList.add(newContact);
|
|
getMessagesStorage().putContacts(arrayList, false);
|
|
|
|
if (!TextUtils.isEmpty(u.phone)) {
|
|
CharSequence name = formatName(u.first_name, u.last_name);
|
|
getMessagesStorage().applyPhoneBookUpdates(u.phone, "");
|
|
Contact contact = contactsBookSPhones.get(u.phone);
|
|
if (contact != null) {
|
|
int index = contact.shortPhones.indexOf(u.phone);
|
|
if (index != -1) {
|
|
contact.phoneDeleted.set(index, 0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
for (int a = 0; a < res.users.size(); a++) {
|
|
TLRPC.User u = res.users.get(a);
|
|
if (!u.contact || contactsDict.get(u.id) != null) {
|
|
continue;
|
|
}
|
|
TLRPC.TL_contact newContact = new TLRPC.TL_contact();
|
|
newContact.user_id = u.id;
|
|
contacts.add(newContact);
|
|
contactsDict.put(newContact.user_id, newContact);
|
|
}
|
|
buildContactsSectionsArrays(true);
|
|
getNotificationCenter().postNotificationName(NotificationCenter.contactsDidLoad);
|
|
});
|
|
}, ConnectionsManager.RequestFlagFailOnServerErrors | ConnectionsManager.RequestFlagCanCompress);
|
|
}
|
|
|
|
public void deleteContact(final ArrayList<TLRPC.User> users, boolean showBulletin) {
|
|
if (users == null || users.isEmpty()) {
|
|
return;
|
|
}
|
|
TLRPC.TL_contacts_deleteContacts req = new TLRPC.TL_contacts_deleteContacts();
|
|
final ArrayList<Long> uids = new ArrayList<>();
|
|
for (int a = 0, N = users.size(); a < N; a++) {
|
|
TLRPC.User user = users.get(a);
|
|
TLRPC.InputUser inputUser = getMessagesController().getInputUser(user);
|
|
if (inputUser == null) {
|
|
continue;
|
|
}
|
|
user.contact = false;
|
|
uids.add(user.id);
|
|
req.id.add(inputUser);
|
|
}
|
|
String userName = users.get(0).first_name;
|
|
getConnectionsManager().sendRequest(req, (response, error) -> {
|
|
if (error != null) {
|
|
return;
|
|
}
|
|
getMessagesController().processUpdates((TLRPC.Updates) response, false);
|
|
getMessagesStorage().deleteContacts(uids);
|
|
Utilities.phoneBookQueue.postRunnable(() -> {
|
|
for (TLRPC.User user : users) {
|
|
deleteContactFromPhoneBook(user.id);
|
|
}
|
|
});
|
|
|
|
for (int a = 0; a < users.size(); a++) {
|
|
TLRPC.User user = users.get(a);
|
|
if (TextUtils.isEmpty(user.phone)) {
|
|
continue;
|
|
}
|
|
getMessagesStorage().applyPhoneBookUpdates(user.phone, "");
|
|
Contact contact = contactsBookSPhones.get(user.phone);
|
|
if (contact != null) {
|
|
int index = contact.shortPhones.indexOf(user.phone);
|
|
if (index != -1) {
|
|
contact.phoneDeleted.set(index, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
boolean remove = false;
|
|
for (TLRPC.User user : users) {
|
|
TLRPC.TL_contact contact = contactsDict.get(user.id);
|
|
if (contact != null) {
|
|
remove = true;
|
|
contacts.remove(contact);
|
|
contactsDict.remove(user.id);
|
|
}
|
|
}
|
|
if (remove) {
|
|
buildContactsSectionsArrays(false);
|
|
}
|
|
getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, MessagesController.UPDATE_MASK_NAME);
|
|
getNotificationCenter().postNotificationName(NotificationCenter.contactsDidLoad);
|
|
if (showBulletin) {
|
|
NotificationCenter.getGlobalInstance().postNotificationName(NotificationCenter.showBulletin, Bulletin.TYPE_ERROR, LocaleController.formatString("DeletedFromYourContacts", R.string.DeletedFromYourContacts, userName));
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
private void reloadContactsStatuses() {
|
|
saveContactsLoadTime();
|
|
getMessagesController().clearFullUsers();
|
|
SharedPreferences preferences = MessagesController.getMainSettings(currentAccount);
|
|
final SharedPreferences.Editor editor = preferences.edit();
|
|
editor.putBoolean("needGetStatuses", true).commit();
|
|
TLRPC.TL_contacts_getStatuses req = new TLRPC.TL_contacts_getStatuses();
|
|
getConnectionsManager().sendRequest(req, (response, error) -> {
|
|
if (error == null) {
|
|
AndroidUtilities.runOnUIThread(() -> {
|
|
editor.remove("needGetStatuses").commit();
|
|
TLRPC.Vector vector = (TLRPC.Vector) response;
|
|
if (!vector.objects.isEmpty()) {
|
|
ArrayList<TLRPC.User> dbUsersStatus = new ArrayList<>();
|
|
for (Object object : vector.objects) {
|
|
TLRPC.User toDbUser = new TLRPC.TL_user();
|
|
TLRPC.TL_contactStatus status = (TLRPC.TL_contactStatus) object;
|
|
|
|
if (status == null) {
|
|
continue;
|
|
}
|
|
if (status.status instanceof TLRPC.TL_userStatusRecently) {
|
|
status.status.expires = -100;
|
|
} else if (status.status instanceof TLRPC.TL_userStatusLastWeek) {
|
|
status.status.expires = -101;
|
|
} else if (status.status instanceof TLRPC.TL_userStatusLastMonth) {
|
|
status.status.expires = -102;
|
|
}
|
|
|
|
TLRPC.User user = getMessagesController().getUser(status.user_id);
|
|
if (user != null) {
|
|
user.status = status.status;
|
|
}
|
|
toDbUser.status = status.status;
|
|
dbUsersStatus.add(toDbUser);
|
|
}
|
|
getMessagesStorage().updateUsers(dbUsersStatus, true, true, true);
|
|
}
|
|
getNotificationCenter().postNotificationName(NotificationCenter.updateInterfaces, MessagesController.UPDATE_MASK_STATUS);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
public void loadPrivacySettings() {
|
|
if (loadingDeleteInfo == 0) {
|
|
loadingDeleteInfo = 1;
|
|
TLRPC.TL_account_getAccountTTL req = new TLRPC.TL_account_getAccountTTL();
|
|
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
|
if (error == null) {
|
|
TLRPC.TL_accountDaysTTL ttl = (TLRPC.TL_accountDaysTTL) response;
|
|
deleteAccountTTL = ttl.days;
|
|
loadingDeleteInfo = 2;
|
|
} else {
|
|
loadingDeleteInfo = 0;
|
|
}
|
|
getNotificationCenter().postNotificationName(NotificationCenter.privacyRulesUpdated);
|
|
}));
|
|
}
|
|
if (loadingGlobalSettings == 0) {
|
|
loadingGlobalSettings = 1;
|
|
TLRPC.TL_account_getGlobalPrivacySettings req = new TLRPC.TL_account_getGlobalPrivacySettings();
|
|
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
|
if (error == null) {
|
|
globalPrivacySettings = (TLRPC.TL_globalPrivacySettings) response;
|
|
loadingGlobalSettings = 2;
|
|
} else {
|
|
loadingGlobalSettings = 0;
|
|
}
|
|
getNotificationCenter().postNotificationName(NotificationCenter.privacyRulesUpdated);
|
|
}));
|
|
}
|
|
for (int a = 0; a < loadingPrivacyInfo.length; a++) {
|
|
if (loadingPrivacyInfo[a] != 0) {
|
|
continue;
|
|
}
|
|
loadingPrivacyInfo[a] = 1;
|
|
final int num = a;
|
|
|
|
TLRPC.TL_account_getPrivacy req = new TLRPC.TL_account_getPrivacy();
|
|
|
|
switch (num) {
|
|
case PRIVACY_RULES_TYPE_LASTSEEN:
|
|
req.key = new TLRPC.TL_inputPrivacyKeyStatusTimestamp();
|
|
break;
|
|
case PRIVACY_RULES_TYPE_INVITE:
|
|
req.key = new TLRPC.TL_inputPrivacyKeyChatInvite();
|
|
break;
|
|
case PRIVACY_RULES_TYPE_CALLS:
|
|
req.key = new TLRPC.TL_inputPrivacyKeyPhoneCall();
|
|
break;
|
|
case PRIVACY_RULES_TYPE_P2P:
|
|
req.key = new TLRPC.TL_inputPrivacyKeyPhoneP2P();
|
|
break;
|
|
case PRIVACY_RULES_TYPE_PHOTO:
|
|
req.key = new TLRPC.TL_inputPrivacyKeyProfilePhoto();
|
|
break;
|
|
case PRIVACY_RULES_TYPE_FORWARDS:
|
|
req.key = new TLRPC.TL_inputPrivacyKeyForwards();
|
|
break;
|
|
case PRIVACY_RULES_TYPE_PHONE:
|
|
req.key = new TLRPC.TL_inputPrivacyKeyPhoneNumber();
|
|
break;
|
|
case PRIVACY_RULES_TYPE_ADDED_BY_PHONE:
|
|
default:
|
|
req.key = new TLRPC.TL_inputPrivacyKeyAddedByPhone();
|
|
break;
|
|
}
|
|
|
|
getConnectionsManager().sendRequest(req, (response, error) -> AndroidUtilities.runOnUIThread(() -> {
|
|
if (error == null) {
|
|
TLRPC.TL_account_privacyRules rules = (TLRPC.TL_account_privacyRules) response;
|
|
getMessagesController().putUsers(rules.users, false);
|
|
getMessagesController().putChats(rules.chats, false);
|
|
|
|
switch (num) {
|
|
case PRIVACY_RULES_TYPE_LASTSEEN:
|
|
lastseenPrivacyRules = rules.rules;
|
|
break;
|
|
case PRIVACY_RULES_TYPE_INVITE:
|
|
groupPrivacyRules = rules.rules;
|
|
break;
|
|
case PRIVACY_RULES_TYPE_CALLS:
|
|
callPrivacyRules = rules.rules;
|
|
break;
|
|
case PRIVACY_RULES_TYPE_P2P:
|
|
p2pPrivacyRules = rules.rules;
|
|
break;
|
|
case PRIVACY_RULES_TYPE_PHOTO:
|
|
profilePhotoPrivacyRules = rules.rules;
|
|
break;
|
|
case PRIVACY_RULES_TYPE_FORWARDS:
|
|
forwardsPrivacyRules = rules.rules;
|
|
break;
|
|
case PRIVACY_RULES_TYPE_PHONE:
|
|
phonePrivacyRules = rules.rules;
|
|
break;
|
|
case PRIVACY_RULES_TYPE_ADDED_BY_PHONE:
|
|
default:
|
|
addedByPhonePrivacyRules = rules.rules;
|
|
break;
|
|
}
|
|
loadingPrivacyInfo[num] = 2;
|
|
} else {
|
|
loadingPrivacyInfo[num] = 0;
|
|
}
|
|
getNotificationCenter().postNotificationName(NotificationCenter.privacyRulesUpdated);
|
|
}));
|
|
}
|
|
getNotificationCenter().postNotificationName(NotificationCenter.privacyRulesUpdated);
|
|
}
|
|
|
|
public void setDeleteAccountTTL(int ttl) {
|
|
deleteAccountTTL = ttl;
|
|
}
|
|
|
|
public int getDeleteAccountTTL() {
|
|
return deleteAccountTTL;
|
|
}
|
|
|
|
public boolean getLoadingDeleteInfo() {
|
|
return loadingDeleteInfo != 2;
|
|
}
|
|
|
|
public boolean getLoadingGlobalSettings() {
|
|
return loadingGlobalSettings != 2;
|
|
}
|
|
|
|
public boolean getLoadingPrivicyInfo(int type) {
|
|
return loadingPrivacyInfo[type] != 2;
|
|
}
|
|
|
|
public TLRPC.TL_globalPrivacySettings getGlobalPrivacySettings() {
|
|
return globalPrivacySettings;
|
|
}
|
|
|
|
public ArrayList<TLRPC.PrivacyRule> getPrivacyRules(int type) {
|
|
switch (type) {
|
|
case PRIVACY_RULES_TYPE_LASTSEEN:
|
|
return lastseenPrivacyRules;
|
|
case PRIVACY_RULES_TYPE_INVITE:
|
|
return groupPrivacyRules;
|
|
case PRIVACY_RULES_TYPE_CALLS:
|
|
return callPrivacyRules;
|
|
case PRIVACY_RULES_TYPE_P2P:
|
|
return p2pPrivacyRules;
|
|
case PRIVACY_RULES_TYPE_PHOTO:
|
|
return profilePhotoPrivacyRules;
|
|
case PRIVACY_RULES_TYPE_FORWARDS:
|
|
return forwardsPrivacyRules;
|
|
case PRIVACY_RULES_TYPE_PHONE:
|
|
return phonePrivacyRules;
|
|
case PRIVACY_RULES_TYPE_ADDED_BY_PHONE:
|
|
return addedByPhonePrivacyRules;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public void setPrivacyRules(ArrayList<TLRPC.PrivacyRule> rules, int type) {
|
|
switch (type) {
|
|
case PRIVACY_RULES_TYPE_LASTSEEN:
|
|
lastseenPrivacyRules = rules;
|
|
break;
|
|
case PRIVACY_RULES_TYPE_INVITE:
|
|
groupPrivacyRules = rules;
|
|
break;
|
|
case PRIVACY_RULES_TYPE_CALLS:
|
|
callPrivacyRules = rules;
|
|
break;
|
|
case PRIVACY_RULES_TYPE_P2P:
|
|
p2pPrivacyRules = rules;
|
|
break;
|
|
case PRIVACY_RULES_TYPE_PHOTO:
|
|
profilePhotoPrivacyRules = rules;
|
|
break;
|
|
case PRIVACY_RULES_TYPE_FORWARDS:
|
|
forwardsPrivacyRules = rules;
|
|
break;
|
|
case PRIVACY_RULES_TYPE_PHONE:
|
|
phonePrivacyRules = rules;
|
|
break;
|
|
case PRIVACY_RULES_TYPE_ADDED_BY_PHONE:
|
|
addedByPhonePrivacyRules = rules;
|
|
break;
|
|
}
|
|
getNotificationCenter().postNotificationName(NotificationCenter.privacyRulesUpdated);
|
|
reloadContactsStatuses();
|
|
}
|
|
|
|
public void createOrUpdateConnectionServiceContact(long id, String firstName, String lastName) {
|
|
if (!hasContactsPermission()) {
|
|
return;
|
|
}
|
|
try {
|
|
ContentResolver resolver = ApplicationLoader.applicationContext.getContentResolver();
|
|
ArrayList<ContentProviderOperation> ops = new ArrayList<>();
|
|
|
|
final Uri groupsURI = ContactsContract.Groups.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();
|
|
final Uri rawContactsURI = ContactsContract.RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build();
|
|
|
|
// 1. Check if we already have the invisible group/label and create it if we don't
|
|
Cursor cursor = resolver.query(groupsURI, new String[]{ContactsContract.Groups._ID},
|
|
ContactsContract.Groups.TITLE + "=? AND " + ContactsContract.Groups.ACCOUNT_TYPE + "=? AND " + ContactsContract.Groups.ACCOUNT_NAME + "=?",
|
|
new String[]{"TelegramConnectionService", systemAccount.type, systemAccount.name}, null);
|
|
int groupID;
|
|
if (cursor != null && cursor.moveToFirst()) {
|
|
groupID = cursor.getInt(0);
|
|
/*ops.add(ContentProviderOperation.newUpdate(groupsURI)
|
|
.withSelection(ContactsContract.Groups._ID+"=?", new String[]{groupID+""})
|
|
.withValue(ContactsContract.Groups.DELETED, 0)
|
|
.build());*/
|
|
} else {
|
|
ContentValues values = new ContentValues();
|
|
values.put(ContactsContract.Groups.ACCOUNT_TYPE, systemAccount.type);
|
|
values.put(ContactsContract.Groups.ACCOUNT_NAME, systemAccount.name);
|
|
values.put(ContactsContract.Groups.GROUP_VISIBLE, 0);
|
|
values.put(ContactsContract.Groups.GROUP_IS_READ_ONLY, 1);
|
|
values.put(ContactsContract.Groups.TITLE, "TelegramConnectionService");
|
|
Uri res = resolver.insert(groupsURI, values);
|
|
groupID = Integer.parseInt(res.getLastPathSegment());
|
|
}
|
|
if (cursor != null)
|
|
cursor.close();
|
|
|
|
// 2. Find the existing ConnectionService contact and update it or create it
|
|
cursor = resolver.query(ContactsContract.Data.CONTENT_URI, new String[]{ContactsContract.Data.RAW_CONTACT_ID},
|
|
ContactsContract.Data.MIMETYPE + "=? AND " + ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID + "=?",
|
|
new String[]{ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE, groupID + ""}, null);
|
|
int backRef = ops.size();
|
|
if (cursor != null && cursor.moveToFirst()) {
|
|
int contactID = cursor.getInt(0);
|
|
ops.add(ContentProviderOperation.newUpdate(rawContactsURI)
|
|
.withSelection(ContactsContract.RawContacts._ID + "=?", new String[]{contactID + ""})
|
|
.withValue(ContactsContract.RawContacts.DELETED, 0)
|
|
.build());
|
|
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
|
|
.withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?",
|
|
new String[]{contactID + "", ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE})
|
|
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, "+99084" + id)
|
|
.build());
|
|
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
|
|
.withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?",
|
|
new String[]{contactID + "", ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE})
|
|
.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, firstName)
|
|
.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, lastName)
|
|
.build());
|
|
} else {
|
|
ops.add(ContentProviderOperation.newInsert(rawContactsURI)
|
|
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, systemAccount.type)
|
|
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, systemAccount.name)
|
|
.withValue(ContactsContract.RawContacts.RAW_CONTACT_IS_READ_ONLY, 1)
|
|
.withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DISABLED)
|
|
.build());
|
|
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
|
|
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, backRef)
|
|
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
|
|
.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, firstName)
|
|
.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, lastName)
|
|
.build());
|
|
// The prefix +990 isn't assigned to anything, so our "phone number" is going to be +990-TG-UserID
|
|
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
|
|
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, backRef)
|
|
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
|
|
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, "+99084" + id)
|
|
.build());
|
|
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
|
|
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, backRef)
|
|
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE)
|
|
.withValue(ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID, groupID)
|
|
.build());
|
|
}
|
|
if (cursor != null)
|
|
cursor.close();
|
|
|
|
resolver.applyBatch(ContactsContract.AUTHORITY, ops);
|
|
|
|
} catch (Exception x) {
|
|
FileLog.e(x);
|
|
}
|
|
}
|
|
|
|
public void deleteConnectionServiceContact() {
|
|
if (!hasContactsPermission())
|
|
return;
|
|
try {
|
|
ContentResolver resolver = ApplicationLoader.applicationContext.getContentResolver();
|
|
|
|
Cursor cursor = resolver.query(ContactsContract.Groups.CONTENT_URI, new String[]{ContactsContract.Groups._ID},
|
|
ContactsContract.Groups.TITLE + "=? AND " + ContactsContract.Groups.ACCOUNT_TYPE + "=? AND " + ContactsContract.Groups.ACCOUNT_NAME + "=?",
|
|
new String[]{"TelegramConnectionService", systemAccount.type, systemAccount.name}, null);
|
|
int groupID;
|
|
if (cursor != null && cursor.moveToFirst()) {
|
|
groupID = cursor.getInt(0);
|
|
cursor.close();
|
|
} else {
|
|
if (cursor != null)
|
|
cursor.close();
|
|
return;
|
|
}
|
|
cursor = resolver.query(ContactsContract.Data.CONTENT_URI, new String[]{ContactsContract.Data.RAW_CONTACT_ID},
|
|
ContactsContract.Data.MIMETYPE + "=? AND " + ContactsContract.CommonDataKinds.GroupMembership.GROUP_ROW_ID + "=?",
|
|
new String[]{ContactsContract.CommonDataKinds.GroupMembership.CONTENT_ITEM_TYPE, groupID + ""}, null);
|
|
int contactID;
|
|
if (cursor != null && cursor.moveToFirst()) {
|
|
contactID = cursor.getInt(0);
|
|
cursor.close();
|
|
} else {
|
|
if (cursor != null)
|
|
cursor.close();
|
|
return;
|
|
}
|
|
resolver.delete(ContactsContract.RawContacts.CONTENT_URI, ContactsContract.RawContacts._ID + "=?", new String[]{contactID + ""});
|
|
//resolver.delete(ContactsContract.Groups.CONTENT_URI, ContactsContract.Groups._ID+"=?", new String[]{groupID+""});
|
|
} catch (Exception x) {
|
|
FileLog.e(x);
|
|
}
|
|
}
|
|
|
|
public static String formatName(String firstName, String lastName) {
|
|
return formatName(firstName, lastName, 0);
|
|
}
|
|
|
|
public static String formatName(String firstName, String lastName, int maxLength) {
|
|
/*if ((firstName == null || firstName.length() == 0) && (lastName == null || lastName.length() == 0)) {
|
|
return LocaleController.getString("HiddenName", R.string.HiddenName);
|
|
}*/
|
|
if (firstName != null) {
|
|
firstName = firstName.trim();
|
|
}
|
|
if (lastName != null) {
|
|
lastName = lastName.trim();
|
|
}
|
|
StringBuilder result = new StringBuilder((firstName != null ? firstName.length() : 0) + (lastName != null ? lastName.length() : 0) + 1);
|
|
if (LocaleController.nameDisplayOrder == 1) {
|
|
if (firstName != null && firstName.length() > 0) {
|
|
if (maxLength > 0 && firstName.length() > maxLength + 2) {
|
|
return firstName.substring(0, maxLength);
|
|
}
|
|
result.append(firstName);
|
|
if (lastName != null && lastName.length() > 0) {
|
|
result.append(" ");
|
|
if (maxLength > 0 && result.length() + lastName.length() > maxLength) {
|
|
result.append(lastName.charAt(0));
|
|
} else {
|
|
result.append(lastName);
|
|
}
|
|
}
|
|
} else if (lastName != null && lastName.length() > 0) {
|
|
if (maxLength > 0 && lastName.length() > maxLength + 2) {
|
|
return lastName.substring(0, maxLength);
|
|
}
|
|
result.append(lastName);
|
|
}
|
|
} else {
|
|
if (lastName != null && lastName.length() > 0) {
|
|
if (maxLength > 0 && lastName.length() > maxLength + 2) {
|
|
return lastName.substring(0, maxLength);
|
|
}
|
|
result.append(lastName);
|
|
if (firstName != null && firstName.length() > 0) {
|
|
result.append(" ");
|
|
if (maxLength > 0 && result.length() + firstName.length() > maxLength) {
|
|
result.append(firstName.charAt(0));
|
|
} else {
|
|
result.append(firstName);
|
|
}
|
|
}
|
|
} else if (firstName != null && firstName.length() > 0) {
|
|
if (maxLength > 0 && firstName.length() > maxLength + 2) {
|
|
return firstName.substring(0, maxLength);
|
|
}
|
|
result.append(firstName);
|
|
}
|
|
}
|
|
return result.toString();
|
|
}
|
|
}
|