parent
b37f25335c
commit
e087b594ff
|
@ -1,9 +1,10 @@
|
||||||
package eu.siacs.conversations.ui.widget;
|
package eu.siacs.conversations.ui.widget;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import androidx.emoji.widget.EmojiAppCompatEditText;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
|
||||||
|
import androidx.emoji.widget.EmojiAppCompatEditText;
|
||||||
|
|
||||||
public class EmojiWrapperEditText extends EmojiAppCompatEditText {
|
public class EmojiWrapperEditText extends EmojiAppCompatEditText {
|
||||||
|
|
||||||
public EmojiWrapperEditText(Context context) {
|
public EmojiWrapperEditText(Context context) {
|
||||||
|
|
|
@ -9,6 +9,8 @@ import android.os.Build;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -20,7 +22,7 @@ import io.michaelrocks.libphonenumber.android.NumberParseException;
|
||||||
|
|
||||||
public class PhoneNumberContact extends AbstractPhoneContact {
|
public class PhoneNumberContact extends AbstractPhoneContact {
|
||||||
|
|
||||||
private String phoneNumber;
|
private final String phoneNumber;
|
||||||
|
|
||||||
public String getPhoneNumber() {
|
public String getPhoneNumber() {
|
||||||
return phoneNumber;
|
return phoneNumber;
|
||||||
|
@ -35,9 +37,9 @@ public class PhoneNumberContact extends AbstractPhoneContact {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, PhoneNumberContact> load(Context context) {
|
public static ImmutableMap<String, PhoneNumberContact> load(Context context) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && context.checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
|
||||||
return Collections.emptyMap();
|
return ImmutableMap.of();
|
||||||
}
|
}
|
||||||
final String[] PROJECTION = new String[]{ContactsContract.Data._ID,
|
final String[] PROJECTION = new String[]{ContactsContract.Data._ID,
|
||||||
ContactsContract.Data.DISPLAY_NAME,
|
ContactsContract.Data.DISPLAY_NAME,
|
||||||
|
@ -47,8 +49,8 @@ public class PhoneNumberContact extends AbstractPhoneContact {
|
||||||
final Cursor cursor;
|
final Cursor cursor;
|
||||||
try {
|
try {
|
||||||
cursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null);
|
cursor = context.getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, PROJECTION, null, null, null);
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
return Collections.emptyMap();
|
return ImmutableMap.of();
|
||||||
}
|
}
|
||||||
final HashMap<String, PhoneNumberContact> contacts = new HashMap<>();
|
final HashMap<String, PhoneNumberContact> contacts = new HashMap<>();
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
|
@ -58,14 +60,14 @@ public class PhoneNumberContact extends AbstractPhoneContact {
|
||||||
if (preexisting == null || preexisting.rating() < contact.rating()) {
|
if (preexisting == null || preexisting.rating() < contact.rating()) {
|
||||||
contacts.put(contact.getPhoneNumber(), contact);
|
contacts.put(contact.getPhoneNumber(), contact);
|
||||||
}
|
}
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (final IllegalArgumentException e) {
|
||||||
Log.d(Config.LOGTAG, "unable to create phone contact");
|
Log.d(Config.LOGTAG, e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cursor != null) {
|
if (cursor != null) {
|
||||||
cursor.close();
|
cursor.close();
|
||||||
}
|
}
|
||||||
return contacts;
|
return ImmutableMap.copyOf(contacts);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static PhoneNumberContact findByUri(Collection<PhoneNumberContact> haystack, Uri needle) {
|
public static PhoneNumberContact findByUri(Collection<PhoneNumberContact> haystack, Uri needle) {
|
||||||
|
|
|
@ -9,6 +9,8 @@ import android.os.SystemClock;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
import java.io.BufferedWriter;
|
import java.io.BufferedWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
@ -24,6 +26,7 @@ import java.security.cert.CertificateException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -350,8 +353,12 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
||||||
|
|
||||||
|
|
||||||
private void considerSync(boolean forced) {
|
private void considerSync(boolean forced) {
|
||||||
Map<String, PhoneNumberContact> contacts = PhoneNumberContact.load(service);
|
final ImmutableMap<String, PhoneNumberContact> allContacts = PhoneNumberContact.load(service);
|
||||||
for (Account account : service.getAccounts()) {
|
for (final Account account : service.getAccounts()) {
|
||||||
|
final Map<String, PhoneNumberContact> contacts = filtered(allContacts, account.getJid().getLocal());
|
||||||
|
if (contacts.size() < allContacts.size()) {
|
||||||
|
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": found own phone number in address book. ignoring...");
|
||||||
|
}
|
||||||
refresh(account, contacts.values());
|
refresh(account, contacts.values());
|
||||||
if (!considerSync(account, contacts, forced)) {
|
if (!considerSync(account, contacts, forced)) {
|
||||||
service.syncRoster(account);
|
service.syncRoster(account);
|
||||||
|
@ -359,6 +366,15 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SafeVarargs
|
||||||
|
private static <A, B> Map<A, B> filtered(final Map<A, B> input, final A... filters) {
|
||||||
|
final HashMap<A, B> result = new HashMap<>(input);
|
||||||
|
for (final A filtered : filters) {
|
||||||
|
result.remove(filtered);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private void refresh(Account account, Collection<PhoneNumberContact> contacts) {
|
private void refresh(Account account, Collection<PhoneNumberContact> contacts) {
|
||||||
for (Contact contact : account.getRoster().getWithSystemAccounts(PhoneNumberContact.class)) {
|
for (Contact contact : account.getRoster().getWithSystemAccounts(PhoneNumberContact.class)) {
|
||||||
final Uri uri = contact.getSystemAccount();
|
final Uri uri = contact.getSystemAccount();
|
||||||
|
@ -379,7 +395,7 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean considerSync(Account account, final Map<String, PhoneNumberContact> contacts, final boolean forced) {
|
private boolean considerSync(final Account account, final Map<String, PhoneNumberContact> contacts, final boolean forced) {
|
||||||
final int hash = contacts.keySet().hashCode();
|
final int hash = contacts.keySet().hashCode();
|
||||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": consider sync of " + hash);
|
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": consider sync of " + hash);
|
||||||
if (!mLastSyncAttempt.retry(hash) && !forced) {
|
if (!mLastSyncAttempt.retry(hash) && !forced) {
|
||||||
|
@ -389,14 +405,14 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
||||||
mRunningSyncJobs.incrementAndGet();
|
mRunningSyncJobs.incrementAndGet();
|
||||||
final Jid syncServer = Jid.of(API_DOMAIN);
|
final Jid syncServer = Jid.of(API_DOMAIN);
|
||||||
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": sending phone list to " + syncServer);
|
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": sending phone list to " + syncServer);
|
||||||
List<Element> entries = new ArrayList<>();
|
final List<Element> entries = new ArrayList<>();
|
||||||
for (PhoneNumberContact c : contacts.values()) {
|
for (final PhoneNumberContact c : contacts.values()) {
|
||||||
entries.add(new Element("entry").setAttribute("number", c.getPhoneNumber()));
|
entries.add(new Element("entry").setAttribute("number", c.getPhoneNumber()));
|
||||||
}
|
}
|
||||||
IqPacket query = new IqPacket(IqPacket.TYPE.GET);
|
final IqPacket query = new IqPacket(IqPacket.TYPE.GET);
|
||||||
query.setTo(syncServer);
|
query.setTo(syncServer);
|
||||||
Element book = new Element("phone-book", Namespace.SYNCHRONIZATION).setChildren(entries);
|
final Element book = new Element("phone-book", Namespace.SYNCHRONIZATION).setChildren(entries);
|
||||||
String statusQuo = Entry.statusQuo(contacts.values(), account.getRoster().getWithSystemAccounts(PhoneNumberContact.class));
|
final String statusQuo = Entry.statusQuo(contacts.values(), account.getRoster().getWithSystemAccounts(PhoneNumberContact.class));
|
||||||
book.setAttribute("ver", statusQuo);
|
book.setAttribute("ver", statusQuo);
|
||||||
query.addChild(book);
|
query.addChild(book);
|
||||||
mLastSyncAttempt = Attempt.create(hash);
|
mLastSyncAttempt = Attempt.create(hash);
|
||||||
|
@ -404,14 +420,14 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
||||||
if (response.getType() == IqPacket.TYPE.RESULT) {
|
if (response.getType() == IqPacket.TYPE.RESULT) {
|
||||||
final Element phoneBook = response.findChild("phone-book", Namespace.SYNCHRONIZATION);
|
final Element phoneBook = response.findChild("phone-book", Namespace.SYNCHRONIZATION);
|
||||||
if (phoneBook != null) {
|
if (phoneBook != null) {
|
||||||
List<Contact> withSystemAccounts = account.getRoster().getWithSystemAccounts(PhoneNumberContact.class);
|
final List<Contact> withSystemAccounts = account.getRoster().getWithSystemAccounts(PhoneNumberContact.class);
|
||||||
for (Entry entry : Entry.ofPhoneBook(phoneBook)) {
|
for (Entry entry : Entry.ofPhoneBook(phoneBook)) {
|
||||||
PhoneNumberContact phoneContact = contacts.get(entry.getNumber());
|
final PhoneNumberContact phoneContact = contacts.get(entry.getNumber());
|
||||||
if (phoneContact == null) {
|
if (phoneContact == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (Jid jid : entry.getJids()) {
|
for (final Jid jid : entry.getJids()) {
|
||||||
Contact contact = account.getRoster().getContact(jid);
|
final Contact contact = account.getRoster().getContact(jid);
|
||||||
final boolean needsCacheClean = contact.setPhoneContact(phoneContact);
|
final boolean needsCacheClean = contact.setPhoneContact(phoneContact);
|
||||||
if (needsCacheClean) {
|
if (needsCacheClean) {
|
||||||
service.getAvatarService().clear(contact);
|
service.getAvatarService().clear(contact);
|
||||||
|
@ -419,7 +435,7 @@ public class QuickConversationsService extends AbstractQuickConversationsService
|
||||||
withSystemAccounts.remove(contact);
|
withSystemAccounts.remove(contact);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (Contact contact : withSystemAccounts) {
|
for (final Contact contact : withSystemAccounts) {
|
||||||
final boolean needsCacheClean = contact.unsetPhoneContact(PhoneNumberContact.class);
|
final boolean needsCacheClean = contact.unsetPhoneContact(PhoneNumberContact.class);
|
||||||
if (needsCacheClean) {
|
if (needsCacheClean) {
|
||||||
service.getAvatarService().clear(contact);
|
service.getAvatarService().clear(contact);
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class PhoneNumberUtilWrapper {
|
||||||
public static String normalize(Context context, String input) throws IllegalArgumentException, NumberParseException {
|
public static String normalize(Context context, String input) throws IllegalArgumentException, NumberParseException {
|
||||||
final Phonenumber.PhoneNumber number = getInstance(context).parse(input, LocationProvider.getUserCountry(context));
|
final Phonenumber.PhoneNumber number = getInstance(context).parse(input, LocationProvider.getUserCountry(context));
|
||||||
if (!getInstance(context).isValidNumber(number)) {
|
if (!getInstance(context).isValidNumber(number)) {
|
||||||
throw new IllegalArgumentException("Not a valid phone number");
|
throw new IllegalArgumentException(String.format("%s is not a valid phone number", input));
|
||||||
}
|
}
|
||||||
return normalize(context, number);
|
return normalize(context, number);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue