mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-24 16:57:50 +00:00
parent
1e0f691a56
commit
b769c7d9b6
@ -19,6 +19,7 @@ package org.thoughtcrime.securesms.contacts;
|
|||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.ContentProviderOperation;
|
import android.content.ContentProviderOperation;
|
||||||
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.OperationApplicationException;
|
import android.content.OperationApplicationException;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
@ -101,22 +102,27 @@ public class ContactsDatabase {
|
|||||||
boolean remove)
|
boolean remove)
|
||||||
throws RemoteException, OperationApplicationException
|
throws RemoteException, OperationApplicationException
|
||||||
{
|
{
|
||||||
Set<Address> registeredAddressSet = new HashSet<>();
|
Set<Address> registeredAddressSet = new HashSet<>(registeredAddressList);
|
||||||
ArrayList<ContentProviderOperation> operations = new ArrayList<>();
|
ArrayList<ContentProviderOperation> operations = new ArrayList<>();
|
||||||
Map<Address, SignalContact> currentContacts = getSignalRawContacts(account);
|
Map<Address, SignalContact> currentContacts = getSignalRawContacts(account);
|
||||||
|
List<List<Address>> registeredChunks = Util.chunk(registeredAddressList, 50);
|
||||||
|
|
||||||
for (Address registeredAddress : registeredAddressList) {
|
for (List<Address> registeredChunk : registeredChunks) {
|
||||||
registeredAddressSet.add(registeredAddress);
|
for (Address registeredAddress : registeredChunk) {
|
||||||
|
if (!currentContacts.containsKey(registeredAddress)) {
|
||||||
|
Optional<SystemContactInfo> systemContactInfo = getSystemContactInfo(registeredAddress);
|
||||||
|
|
||||||
if (!currentContacts.containsKey(registeredAddress)) {
|
if (systemContactInfo.isPresent()) {
|
||||||
Optional<SystemContactInfo> systemContactInfo = getSystemContactInfo(registeredAddress);
|
Log.i(TAG, "Adding number: " + registeredAddress);
|
||||||
|
addTextSecureRawContact(operations, account, systemContactInfo.get().number,
|
||||||
if (systemContactInfo.isPresent()) {
|
systemContactInfo.get().name, systemContactInfo.get().id);
|
||||||
Log.i(TAG, "Adding number: " + registeredAddress);
|
}
|
||||||
addTextSecureRawContact(operations, account, systemContactInfo.get().number,
|
|
||||||
systemContactInfo.get().name, systemContactInfo.get().id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!operations.isEmpty()) {
|
||||||
|
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operations);
|
||||||
|
operations.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Map.Entry<Address, SignalContact> currentContactEntry : currentContacts.entrySet()) {
|
for (Map.Entry<Address, SignalContact> currentContactEntry : currentContacts.entrySet()) {
|
||||||
@ -137,7 +143,7 @@ public class ContactsDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!operations.isEmpty()) {
|
if (!operations.isEmpty()) {
|
||||||
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operations);
|
applyOperationsInBatches(context.getContentResolver(), ContactsContract.AUTHORITY, operations, 50);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -532,6 +538,18 @@ public class ContactsDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void applyOperationsInBatches(@NonNull ContentResolver contentResolver,
|
||||||
|
@NonNull String authority,
|
||||||
|
@NonNull List<ContentProviderOperation> operations,
|
||||||
|
int batchSize)
|
||||||
|
throws OperationApplicationException, RemoteException
|
||||||
|
{
|
||||||
|
List<List<ContentProviderOperation>> batches = Util.chunk(operations, batchSize);
|
||||||
|
for (List<ContentProviderOperation> batch : batches) {
|
||||||
|
contentResolver.applyBatch(authority, new ArrayList<>(batch));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class ProjectionMappingCursor extends CursorWrapper {
|
private static class ProjectionMappingCursor extends CursorWrapper {
|
||||||
|
|
||||||
private final Map<String, String> projectionMap;
|
private final Map<String, String> projectionMap;
|
||||||
|
@ -218,7 +218,7 @@ public class DirectoryHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (RemoteException | OperationApplicationException e) {
|
} catch (RemoteException | OperationApplicationException e) {
|
||||||
Log.w(TAG, e);
|
Log.w(TAG, "Failed to update contacts.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ import java.io.UnsupportedEncodingException;
|
|||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -77,7 +78,7 @@ import java.util.concurrent.TimeUnit;
|
|||||||
public class Util {
|
public class Util {
|
||||||
private static final String TAG = Util.class.getSimpleName();
|
private static final String TAG = Util.class.getSimpleName();
|
||||||
|
|
||||||
public static Handler handler = new Handler(Looper.getMainLooper());
|
private static volatile Handler handler;
|
||||||
|
|
||||||
public static <T> List<T> asList(T... elements) {
|
public static <T> List<T> asList(T... elements) {
|
||||||
List<T> result = new LinkedList<>();
|
List<T> result = new LinkedList<>();
|
||||||
@ -141,6 +142,17 @@ public class Util {
|
|||||||
return map.containsKey(key) ? map.get(key) : defaultValue;
|
return map.containsKey(key) ? map.get(key) : defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <E> List<List<E>> chunk(@NonNull List<E> list, int chunkSize) {
|
||||||
|
List<List<E>> chunks = new ArrayList<>(list.size() / chunkSize);
|
||||||
|
|
||||||
|
for (int i = 0; i < list.size(); i += chunkSize) {
|
||||||
|
List<E> chunk = list.subList(i, Math.min(list.size(), i + chunkSize));
|
||||||
|
chunks.add(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunks;
|
||||||
|
}
|
||||||
|
|
||||||
public static CharSequence getBoldedString(String value) {
|
public static CharSequence getBoldedString(String value) {
|
||||||
SpannableString spanned = new SpannableString(value);
|
SpannableString spanned = new SpannableString(value);
|
||||||
spanned.setSpan(new StyleSpan(Typeface.BOLD), 0,
|
spanned.setSpan(new StyleSpan(Typeface.BOLD), 0,
|
||||||
@ -394,20 +406,20 @@ public class Util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void postToMain(final @NonNull Runnable runnable) {
|
public static void postToMain(final @NonNull Runnable runnable) {
|
||||||
handler.post(runnable);
|
getHandler().post(runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void runOnMain(final @NonNull Runnable runnable) {
|
public static void runOnMain(final @NonNull Runnable runnable) {
|
||||||
if (isMainThread()) runnable.run();
|
if (isMainThread()) runnable.run();
|
||||||
else handler.post(runnable);
|
else getHandler().post(runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void runOnMainDelayed(final @NonNull Runnable runnable, long delayMillis) {
|
public static void runOnMainDelayed(final @NonNull Runnable runnable, long delayMillis) {
|
||||||
handler.postDelayed(runnable, delayMillis);
|
getHandler().postDelayed(runnable, delayMillis);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void cancelRunnableOnMain(@NonNull Runnable runnable) {
|
public static void cancelRunnableOnMain(@NonNull Runnable runnable) {
|
||||||
handler.removeCallbacks(runnable);
|
getHandler().removeCallbacks(runnable);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void runOnMainSync(final @NonNull Runnable runnable) {
|
public static void runOnMainSync(final @NonNull Runnable runnable) {
|
||||||
@ -510,4 +522,15 @@ public class Util {
|
|||||||
|
|
||||||
return new DecimalFormat("#,##0.#").format(sizeBytes/Math.pow(1024, digitGroups)) + " " + units[digitGroups];
|
return new DecimalFormat("#,##0.#").format(sizeBytes/Math.pow(1024, digitGroups)) + " " + units[digitGroups];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Handler getHandler() {
|
||||||
|
if (handler == null) {
|
||||||
|
synchronized (Util.class) {
|
||||||
|
if (handler == null) {
|
||||||
|
handler = new Handler(Looper.getMainLooper());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return handler;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,52 @@
|
|||||||
|
package org.thoughtcrime.securesms.util;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class UtilTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void chunk_oneChunk() {
|
||||||
|
List<String> input = Arrays.asList("A", "B", "C");
|
||||||
|
|
||||||
|
List<List<String>> output = Util.chunk(input, 3);
|
||||||
|
assertEquals(1, output.size());
|
||||||
|
assertEquals(input, output.get(0));
|
||||||
|
|
||||||
|
output = Util.chunk(input, 4);
|
||||||
|
assertEquals(1, output.size());
|
||||||
|
assertEquals(input, output.get(0));
|
||||||
|
|
||||||
|
output = Util.chunk(input, 100);
|
||||||
|
assertEquals(1, output.size());
|
||||||
|
assertEquals(input, output.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void chunk_multipleChunks() {
|
||||||
|
List<String> input = Arrays.asList("A", "B", "C", "D", "E");
|
||||||
|
|
||||||
|
List<List<String>> output = Util.chunk(input, 4);
|
||||||
|
assertEquals(2, output.size());
|
||||||
|
assertEquals(Arrays.asList("A", "B", "C", "D"), output.get(0));
|
||||||
|
assertEquals(Arrays.asList("E"), output.get(1));
|
||||||
|
|
||||||
|
output = Util.chunk(input, 2);
|
||||||
|
assertEquals(3, output.size());
|
||||||
|
assertEquals(Arrays.asList("A", "B"), output.get(0));
|
||||||
|
assertEquals(Arrays.asList("C", "D"), output.get(1));
|
||||||
|
assertEquals(Arrays.asList("E"), output.get(2));
|
||||||
|
|
||||||
|
output = Util.chunk(input, 1);
|
||||||
|
assertEquals(5, output.size());
|
||||||
|
assertEquals(Arrays.asList("A"), output.get(0));
|
||||||
|
assertEquals(Arrays.asList("B"), output.get(1));
|
||||||
|
assertEquals(Arrays.asList("C"), output.get(2));
|
||||||
|
assertEquals(Arrays.asList("D"), output.get(3));
|
||||||
|
assertEquals(Arrays.asList("E"), output.get(4));
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user