mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-27 12:05:22 +00:00
Don't invalidate entire recipient cache when contact data changes
This commit is contained in:
parent
8f6440ce17
commit
66e1be1aeb
@ -105,7 +105,6 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.DraftDatabase;
|
||||
import org.thoughtcrime.securesms.database.DraftDatabase.Draft;
|
||||
import org.thoughtcrime.securesms.database.DraftDatabase.Drafts;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
|
||||
@ -235,7 +234,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private AttachmentManager attachmentManager;
|
||||
private AudioRecorder audioRecorder;
|
||||
private BroadcastReceiver securityUpdateReceiver;
|
||||
private BroadcastReceiver recipientsStaleReceiver;
|
||||
private Stub<EmojiDrawer> emojiDrawerStub;
|
||||
protected HidingLinearLayout quickAttachmentToggle;
|
||||
private QuickAttachmentDrawer quickAttachmentDrawer;
|
||||
@ -386,7 +384,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
saveDraft();
|
||||
if (recipient != null) recipient.removeListener(this);
|
||||
if (securityUpdateReceiver != null) unregisterReceiver(securityUpdateReceiver);
|
||||
if (recipientsStaleReceiver != null) unregisterReceiver(recipientsStaleReceiver);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@ -1345,29 +1342,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
};
|
||||
|
||||
recipientsStaleReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Log.w(TAG, "Group update received...");
|
||||
if (recipient != null) {
|
||||
Log.w(TAG, "Looking up new recipients...");
|
||||
recipient = Recipient.from(context, recipient.getAddress(), true);
|
||||
recipient.addListener(ConversationActivity.this);
|
||||
onModified(recipient);
|
||||
fragment.reloadList();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
IntentFilter staleFilter = new IntentFilter();
|
||||
staleFilter.addAction(GroupDatabase.DATABASE_UPDATE_ACTION);
|
||||
staleFilter.addAction(Recipient.RECIPIENT_CLEAR_ACTION);
|
||||
|
||||
registerReceiver(securityUpdateReceiver,
|
||||
new IntentFilter(SecurityEvent.SECURITY_UPDATE_EVENT),
|
||||
KeyCachingService.KEY_PERMISSION, null);
|
||||
|
||||
registerReceiver(recipientsStaleReceiver, staleFilter);
|
||||
}
|
||||
|
||||
//////// Helper Methods
|
||||
|
@ -20,14 +20,11 @@ import android.annotation.SuppressLint;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.ContentObserver;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
@ -53,13 +50,13 @@ import java.util.List;
|
||||
public class ConversationListActivity extends PassphraseRequiredActionBarActivity
|
||||
implements ConversationListFragment.ConversationSelectedListener
|
||||
{
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = ConversationListActivity.class.getSimpleName();
|
||||
|
||||
private final DynamicTheme dynamicTheme = new DynamicNoActionBarTheme();
|
||||
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
||||
|
||||
private ConversationListFragment fragment;
|
||||
private ContentObserver observer;
|
||||
private MasterSecret masterSecret;
|
||||
private SearchToolbar searchToolbar;
|
||||
private ImageView searchAction;
|
||||
@ -83,7 +80,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
searchAction = findViewById(R.id.search_action);
|
||||
fragment = initFragment(R.id.fragment_container, new ConversationListFragment(), masterSecret, dynamicLanguage.getCurrentLocale());
|
||||
|
||||
initializeContactUpdatesReceiver();
|
||||
initializeSearchListener();
|
||||
|
||||
RatingManager.showRatingDialogIfNecessary(this);
|
||||
@ -98,7 +94,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
if (observer != null) getContentResolver().unregisterContentObserver(observer);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@ -225,19 +220,4 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
Toast.makeText(this, R.string.ConversationListActivity_there_is_no_browser_installed_on_your_device, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeContactUpdatesReceiver() {
|
||||
observer = new ContentObserver(null) {
|
||||
@Override
|
||||
public void onChange(boolean selfChange) {
|
||||
super.onChange(selfChange);
|
||||
Log.w(TAG, "Detected android contact data changed, refreshing cache");
|
||||
Recipient.clearCache(ConversationListActivity.this);
|
||||
ConversationListActivity.this.runOnUiThread(() -> fragment.getListAdapter().notifyDataSetChanged());
|
||||
}
|
||||
};
|
||||
|
||||
getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI,
|
||||
true, observer);
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Color;
|
||||
import android.media.Ringtone;
|
||||
@ -42,7 +41,6 @@ import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
@ -93,7 +91,6 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
private TextView threadPhotoRailLabel;
|
||||
private ThreadPhotoRailView threadPhotoRailView;
|
||||
private CollapsingToolbarLayout toolbarLayout;
|
||||
private BroadcastReceiver staleReceiver;
|
||||
|
||||
@Override
|
||||
public void onPreCreate() {
|
||||
@ -111,7 +108,6 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
Recipient recipient = Recipient.from(this, address, true);
|
||||
|
||||
initializeToolbar();
|
||||
initializeReceivers();
|
||||
setHeader(recipient);
|
||||
recipient.addListener(this);
|
||||
|
||||
@ -125,12 +121,6 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
dynamicLanguage.onResume(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
unregisterReceiver(staleReceiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
@ -192,23 +182,6 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeReceivers() {
|
||||
this.staleReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Recipient recipient = Recipient.from(context, (Address)getIntent().getParcelableExtra(ADDRESS_EXTRA), true);
|
||||
recipient.addListener(RecipientPreferenceActivity.this);
|
||||
onModified(recipient);
|
||||
}
|
||||
};
|
||||
|
||||
IntentFilter staleFilter = new IntentFilter();
|
||||
staleFilter.addAction(GroupDatabase.DATABASE_UPDATE_ACTION);
|
||||
staleFilter.addAction(Recipient.RECIPIENT_CLEAR_ACTION);
|
||||
|
||||
registerReceiver(staleReceiver, staleFilter);
|
||||
}
|
||||
|
||||
private void setHeader(@NonNull Recipient recipient) {
|
||||
glideRequests.load(recipient.getContactPhoto())
|
||||
.fallback(recipient.getFallbackContactPhoto().asCallCard(this))
|
||||
@ -306,23 +279,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
|
||||
private void initializeRecipients() {
|
||||
this.recipient = Recipient.from(getActivity(), getArguments().getParcelable(ADDRESS_EXTRA), true);
|
||||
|
||||
this.recipient.addListener(this);
|
||||
|
||||
this.staleReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
recipient.removeListener(RecipientPreferenceFragment.this);
|
||||
recipient = Recipient.from(getActivity(), getArguments().getParcelable(ADDRESS_EXTRA), true);
|
||||
onModified(recipient);
|
||||
}
|
||||
};
|
||||
|
||||
IntentFilter intentFilter = new IntentFilter();
|
||||
intentFilter.addAction(GroupDatabase.DATABASE_UPDATE_ACTION);
|
||||
intentFilter.addAction(Recipient.RECIPIENT_CLEAR_ACTION);
|
||||
|
||||
getActivity().registerReceiver(staleReceiver, intentFilter);
|
||||
}
|
||||
|
||||
private void setSummaries(Recipient recipient) {
|
||||
|
@ -38,14 +38,10 @@ import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
|
||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
||||
import org.whispersystems.signalservice.api.util.PhoneNumberFormatter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -80,13 +76,12 @@ public class ContactsDatabase {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public synchronized @NonNull List<Address> setRegisteredUsers(@NonNull Account account,
|
||||
@NonNull List<Address> registeredAddressList,
|
||||
boolean remove)
|
||||
public synchronized void setRegisteredUsers(@NonNull Account account,
|
||||
@NonNull List<Address> registeredAddressList,
|
||||
boolean remove)
|
||||
throws RemoteException, OperationApplicationException
|
||||
{
|
||||
Set<Address> registeredAddressSet = new HashSet<>();
|
||||
List<Address> addedAddresses = new LinkedList<>();
|
||||
ArrayList<ContentProviderOperation> operations = new ArrayList<>();
|
||||
Map<Address, SignalContact> currentContacts = getSignalRawContacts(account);
|
||||
|
||||
@ -98,7 +93,6 @@ public class ContactsDatabase {
|
||||
|
||||
if (systemContactInfo.isPresent()) {
|
||||
Log.w(TAG, "Adding number: " + registeredAddress);
|
||||
addedAddresses.add(registeredAddress);
|
||||
addTextSecureRawContact(operations, account, systemContactInfo.get().number,
|
||||
systemContactInfo.get().name, systemContactInfo.get().id,
|
||||
true);
|
||||
@ -126,8 +120,6 @@ public class ContactsDatabase {
|
||||
if (!operations.isEmpty()) {
|
||||
context.getContentResolver().applyBatch(ContactsContract.AUTHORITY, operations);
|
||||
}
|
||||
|
||||
return addedAddresses;
|
||||
}
|
||||
|
||||
@NonNull Cursor querySystemContacts(@Nullable String filter) {
|
||||
|
@ -1,9 +1,9 @@
|
||||
package org.thoughtcrime.securesms.database;
|
||||
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
@ -14,6 +14,7 @@ import android.text.TextUtils;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.thoughtcrime.securesms.contacts.avatars.GroupRecordContactPhoto;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
@ -30,8 +31,7 @@ import java.util.List;
|
||||
|
||||
public class GroupDatabase extends Database {
|
||||
|
||||
public static final String DATABASE_UPDATE_ACTION = "org.thoughtcrime.securesms.database.GroupDatabase.UPDATE";
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static final String TAG = GroupDatabase.class.getSimpleName();
|
||||
|
||||
static final String TABLE_NAME = "groups";
|
||||
@ -65,7 +65,7 @@ public class GroupDatabase extends Database {
|
||||
AVATAR_DIGEST + " BLOB, " +
|
||||
MMS + " INTEGER DEFAULT 0);";
|
||||
|
||||
public static final String[] CREATE_INDEXS = {
|
||||
static final String[] CREATE_INDEXS = {
|
||||
"CREATE UNIQUE INDEX IF NOT EXISTS group_id_index ON " + TABLE_NAME + " (" + GROUP_ID + ");",
|
||||
};
|
||||
|
||||
@ -103,9 +103,10 @@ public class GroupDatabase extends Database {
|
||||
}
|
||||
|
||||
public Reader getGroupsFilteredByTitle(String constraint) {
|
||||
@SuppressLint("Recycle")
|
||||
Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, TITLE + " LIKE ?",
|
||||
new String[]{"%" + constraint + "%"},
|
||||
null, null, null);
|
||||
new String[]{"%" + constraint + "%"},
|
||||
null, null, null);
|
||||
|
||||
return new Reader(cursor);
|
||||
}
|
||||
@ -131,6 +132,7 @@ public class GroupDatabase extends Database {
|
||||
}
|
||||
|
||||
public Reader getGroups() {
|
||||
@SuppressLint("Recycle")
|
||||
Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, null, null, null, null, null);
|
||||
return new Reader(cursor);
|
||||
}
|
||||
@ -172,7 +174,14 @@ public class GroupDatabase extends Database {
|
||||
contentValues.put(MMS, GroupUtil.isMmsGroup(groupId));
|
||||
|
||||
databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, contentValues);
|
||||
Recipient.clearCache(context);
|
||||
|
||||
Address address = Address.fromSerialized(groupId);
|
||||
Recipient recipient = Recipient.from(context, Address.fromSerialized(groupId), false);
|
||||
|
||||
recipient.setName(title);
|
||||
if (avatar != null) recipient.setContactPhoto(new GroupRecordContactPhoto(address, avatar.getId()));
|
||||
recipient.setParticipants(Stream.of(members).map(memberAddress -> Recipient.from(context, memberAddress, true)).toList());
|
||||
|
||||
notifyConversationListListeners();
|
||||
}
|
||||
|
||||
@ -191,8 +200,11 @@ public class GroupDatabase extends Database {
|
||||
GROUP_ID + " = ?",
|
||||
new String[] {groupId});
|
||||
|
||||
Recipient.clearCache(context);
|
||||
notifyDatabaseListeners();
|
||||
Address address = Address.fromSerialized(groupId);
|
||||
Recipient recipient = Recipient.from(context, address, false);
|
||||
recipient.setName(title);
|
||||
if (avatar != null) recipient.setContactPhoto(new GroupRecordContactPhoto(address, avatar.getId()));
|
||||
|
||||
notifyConversationListListeners();
|
||||
}
|
||||
|
||||
@ -202,8 +214,8 @@ public class GroupDatabase extends Database {
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
|
||||
new String[] {groupId});
|
||||
|
||||
Recipient.clearCache(context);
|
||||
notifyDatabaseListeners();
|
||||
Recipient recipient = Recipient.from(context, Address.fromSerialized(groupId), false);
|
||||
recipient.setName(title);
|
||||
}
|
||||
|
||||
public void updateAvatar(String groupId, Bitmap avatar) {
|
||||
@ -211,14 +223,17 @@ public class GroupDatabase extends Database {
|
||||
}
|
||||
|
||||
public void updateAvatar(String groupId, byte[] avatar) {
|
||||
long avatarId = Math.abs(new SecureRandom().nextLong());
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(AVATAR, avatar);
|
||||
contentValues.put(AVATAR_ID, avatarId);
|
||||
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
|
||||
new String[] {groupId});
|
||||
|
||||
Recipient.clearCache(context);
|
||||
notifyDatabaseListeners();
|
||||
Address address = Address.fromSerialized(groupId);
|
||||
Recipient recipient = Recipient.from(context, address, false);
|
||||
recipient.setContactPhoto(new GroupRecordContactPhoto(address, avatarId));
|
||||
}
|
||||
|
||||
public void updateMembers(String groupId, List<Address> members) {
|
||||
@ -287,11 +302,6 @@ public class GroupDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyDatabaseListeners() {
|
||||
Intent intent = new Intent(DATABASE_UPDATE_ACTION);
|
||||
context.sendBroadcast(intent);
|
||||
}
|
||||
|
||||
public static class Reader {
|
||||
|
||||
private final Cursor cursor;
|
||||
|
@ -399,7 +399,7 @@ public class RecipientDatabase extends Database {
|
||||
database.setTransactionSuccessful();
|
||||
database.endTransaction();
|
||||
|
||||
Stream.of(pendingDisplayNames).forEach(pair -> pair.first().resolve().setSystemDisplayName(pair.second()));
|
||||
Stream.of(pendingDisplayNames).forEach(pair -> pair.first().resolve().setName(pair.second()));
|
||||
|
||||
context.getContentResolver().notifyChange(Uri.parse(RECIPIENT_PREFERENCES_URI), null);
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2011 Whisper Systems
|
||||
* Copyright (C) 2013 - 2017 Open Whisper Systems
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@ -17,7 +18,6 @@
|
||||
package org.thoughtcrime.securesms.recipients;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
@ -50,9 +50,8 @@ import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class Recipient implements RecipientModifiedListener {
|
||||
|
||||
public static final String RECIPIENT_CLEAR_ACTION = "org.thoughtcrime.securesms.database.RecipientFactory.CLEAR";
|
||||
private static final String TAG = Recipient.class.getSimpleName();
|
||||
private static final RecipientProvider provider = new RecipientProvider();
|
||||
private static final String TAG = Recipient.class.getSimpleName();
|
||||
private static final RecipientProvider provider = new RecipientProvider();
|
||||
|
||||
private final Set<RecipientModifiedListener> listeners = Collections.newSetFromMap(new WeakHashMap<RecipientModifiedListener, Boolean>());
|
||||
|
||||
@ -61,7 +60,6 @@ public class Recipient implements RecipientModifiedListener {
|
||||
|
||||
private @Nullable String name;
|
||||
private @Nullable String customLabel;
|
||||
private boolean stale;
|
||||
private boolean resolving;
|
||||
|
||||
private @Nullable ContactPhoto contactPhoto;
|
||||
@ -84,21 +82,18 @@ public class Recipient implements RecipientModifiedListener {
|
||||
private boolean isSystemContact;
|
||||
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public static @NonNull Recipient from(@NonNull Context context, @NonNull Address address, boolean asynchronous) {
|
||||
if (address == null) throw new AssertionError(address);
|
||||
return provider.getRecipient(context, address, Optional.absent(), Optional.absent(), asynchronous);
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public static @NonNull Recipient from(@NonNull Context context, @NonNull Address address, @NonNull Optional<RecipientSettings> settings, @NonNull Optional<GroupDatabase.GroupRecord> groupRecord, boolean asynchronous) {
|
||||
if (address == null) throw new AssertionError(address);
|
||||
return provider.getRecipient(context, address, settings, groupRecord, asynchronous);
|
||||
}
|
||||
|
||||
public static void clearCache(Context context) {
|
||||
provider.clearCache();
|
||||
context.sendBroadcast(new Intent(RECIPIENT_CLEAR_ACTION));
|
||||
}
|
||||
|
||||
Recipient(@NonNull Address address,
|
||||
@Nullable Recipient stale,
|
||||
@NonNull Optional<RecipientDetails> details,
|
||||
@ -246,6 +241,19 @@ public class Recipient implements RecipientModifiedListener {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public void setName(@Nullable String name) {
|
||||
boolean notify = false;
|
||||
|
||||
synchronized (this) {
|
||||
if (!Util.equals(this.name, name)) {
|
||||
this.name = name;
|
||||
notify = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (notify) notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized @NonNull MaterialColor getColor() {
|
||||
if (isGroupRecipient()) return MaterialColor.GROUP;
|
||||
else if (color != null) return color;
|
||||
@ -333,6 +341,15 @@ public class Recipient implements RecipientModifiedListener {
|
||||
return participants;
|
||||
}
|
||||
|
||||
public void setParticipants(@NonNull List<Recipient> participants) {
|
||||
synchronized (this) {
|
||||
this.participants.clear();
|
||||
this.participants.addAll(participants);
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized void addListener(RecipientModifiedListener listener) {
|
||||
if (listeners.isEmpty()) {
|
||||
for (Recipient recipient : participants) recipient.addListener(this);
|
||||
@ -452,11 +469,16 @@ public class Recipient implements RecipientModifiedListener {
|
||||
}
|
||||
|
||||
public void setRegistered(@NonNull RegisteredState value) {
|
||||
boolean notify = false;
|
||||
|
||||
synchronized (this) {
|
||||
this.registered = value;
|
||||
if (this.registered != value) {
|
||||
this.registered = value;
|
||||
notify = true;
|
||||
}
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
if (notify) notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized @Nullable byte[] getProfileKey() {
|
||||
@ -475,15 +497,6 @@ public class Recipient implements RecipientModifiedListener {
|
||||
return isSystemContact;
|
||||
}
|
||||
|
||||
public void setSystemDisplayName(@Nullable String displayName) {
|
||||
synchronized (this) {
|
||||
if (displayName == null) this.name = profileName;
|
||||
else this.name = displayName;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized Recipient resolve() {
|
||||
while (resolving) Util.wait(this, 0);
|
||||
return this;
|
||||
@ -521,15 +534,6 @@ public class Recipient implements RecipientModifiedListener {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
boolean isStale() {
|
||||
return stale;
|
||||
}
|
||||
|
||||
void setStale() {
|
||||
this.stale = true;
|
||||
}
|
||||
|
||||
// XXX This shouldn't be public, temporary workaround
|
||||
public synchronized boolean isResolving() {
|
||||
return resolving;
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ class RecipientProvider {
|
||||
@NonNull Recipient getRecipient(Context context, Address address, Optional<RecipientSettings> settings, Optional<GroupRecord> groupRecord, boolean asynchronous) {
|
||||
Recipient cachedRecipient = recipientCache.get(address);
|
||||
|
||||
if (cachedRecipient != null && !cachedRecipient.isStale() && (asynchronous || !cachedRecipient.isResolving()) && ((!groupRecord.isPresent() && !settings.isPresent()) || !cachedRecipient.isResolving() || cachedRecipient.getName() != null)) {
|
||||
if (cachedRecipient != null && (asynchronous || !cachedRecipient.isResolving()) && ((!groupRecord.isPresent() && !settings.isPresent()) || !cachedRecipient.isResolving() || cachedRecipient.getName() != null)) {
|
||||
return cachedRecipient;
|
||||
}
|
||||
|
||||
@ -93,10 +93,6 @@ class RecipientProvider {
|
||||
return cachedRecipient;
|
||||
}
|
||||
|
||||
void clearCache() {
|
||||
recipientCache.reset();
|
||||
}
|
||||
|
||||
private @NonNull Optional<RecipientDetails> createPrefetchedRecipientDetails(@NonNull Context context, @NonNull Address address,
|
||||
@NonNull Optional<RecipientSettings> settings,
|
||||
@NonNull Optional<GroupRecord> groupRecord)
|
||||
@ -276,12 +272,6 @@ class RecipientProvider {
|
||||
cache.put(address, recipient);
|
||||
}
|
||||
|
||||
public synchronized void reset() {
|
||||
for (Recipient recipient : cache.values()) {
|
||||
recipient.setStale();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -25,7 +25,6 @@ import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
@ -38,6 +37,7 @@ import org.whispersystems.signalservice.api.push.ContactTokenDetails;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -52,24 +52,22 @@ public class DirectoryHelper {
|
||||
{
|
||||
if (TextUtils.isEmpty(TextSecurePreferences.getLocalNumber(context))) return;
|
||||
|
||||
RefreshResult result = refreshDirectory(context, AccountManagerFactory.createManager(context));
|
||||
List<Address> newlyActiveUsers = refreshDirectory(context, AccountManagerFactory.createManager(context));
|
||||
|
||||
if (!result.getNewUsers().isEmpty() && TextSecurePreferences.isMultiDevice(context)) {
|
||||
if (!newlyActiveUsers.isEmpty() && TextSecurePreferences.isMultiDevice(context)) {
|
||||
ApplicationContext.getInstance(context)
|
||||
.getJobManager()
|
||||
.add(new MultiDeviceContactUpdateJob(context));
|
||||
}
|
||||
|
||||
if (!result.isFresh()) {
|
||||
notifyNewUsers(context, masterSecret, result.getNewUsers());
|
||||
}
|
||||
notifyNewUsers(context, masterSecret, newlyActiveUsers);
|
||||
}
|
||||
|
||||
public static @NonNull RefreshResult refreshDirectory(@NonNull Context context, @NonNull SignalServiceAccountManager accountManager)
|
||||
public static @NonNull List<Address> refreshDirectory(@NonNull Context context, @NonNull SignalServiceAccountManager accountManager)
|
||||
throws IOException
|
||||
{
|
||||
if (TextUtils.isEmpty(TextSecurePreferences.getLocalNumber(context))) {
|
||||
return new RefreshResult(new LinkedList<>(), false);
|
||||
return new LinkedList<>();
|
||||
}
|
||||
|
||||
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
|
||||
@ -94,11 +92,19 @@ public class DirectoryHelper {
|
||||
inactiveRecipients.add(Recipient.from(context, Address.fromSerialized(inactiveContactNumber), true));
|
||||
}
|
||||
|
||||
Set<Address> currentActiveAddresses = new HashSet<>(recipientDatabase.getRegistered());
|
||||
List<Address> newlyActiveAddresses = Stream.of(activeRecipients)
|
||||
.map(Recipient::getAddress)
|
||||
.filter(address -> !currentActiveAddresses.contains(address))
|
||||
.toList();
|
||||
|
||||
recipientDatabase.setRegistered(activeRecipients, inactiveRecipients);
|
||||
return updateContactsDatabase(context, Stream.of(activeRecipients).map(Recipient::getAddress).toList(), true);
|
||||
updateContactsDatabase(context, Stream.of(activeRecipients).map(Recipient::getAddress).toList(), true);
|
||||
|
||||
return newlyActiveAddresses;
|
||||
}
|
||||
|
||||
return new RefreshResult(new LinkedList<>(), false);
|
||||
return new LinkedList<>();
|
||||
}
|
||||
|
||||
public static RegisteredState refreshDirectoryFor(@NonNull Context context,
|
||||
@ -108,20 +114,21 @@ public class DirectoryHelper {
|
||||
{
|
||||
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
|
||||
SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(context);
|
||||
boolean activeUser = recipient.resolve().getRegistered() == RegisteredState.REGISTERED;
|
||||
String number = recipient.getAddress().serialize();
|
||||
Optional<ContactTokenDetails> details = accountManager.getContact(number);
|
||||
|
||||
if (details.isPresent()) {
|
||||
recipientDatabase.setRegistered(recipient, RegisteredState.REGISTERED);
|
||||
|
||||
RefreshResult result = updateContactsDatabase(context, Util.asList(recipient.getAddress()), false);
|
||||
updateContactsDatabase(context, Util.asList(recipient.getAddress()), false);
|
||||
|
||||
if (!result.getNewUsers().isEmpty() && TextSecurePreferences.isMultiDevice(context)) {
|
||||
if (!activeUser && TextSecurePreferences.isMultiDevice(context)) {
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new MultiDeviceContactUpdateJob(context));
|
||||
}
|
||||
|
||||
if (!result.isFresh()) {
|
||||
notifyNewUsers(context, masterSecret, result.getNewUsers());
|
||||
if (!activeUser) {
|
||||
notifyNewUsers(context, masterSecret, Collections.singletonList(recipient.getAddress()));
|
||||
}
|
||||
|
||||
return RegisteredState.REGISTERED;
|
||||
@ -131,13 +138,12 @@ public class DirectoryHelper {
|
||||
}
|
||||
}
|
||||
|
||||
private static @NonNull RefreshResult updateContactsDatabase(@NonNull Context context, @NonNull List<Address> activeAddresses, boolean removeMissing) {
|
||||
private static void updateContactsDatabase(@NonNull Context context, @NonNull List<Address> activeAddresses, boolean removeMissing) {
|
||||
Optional<AccountHolder> account = getOrCreateAccount(context);
|
||||
|
||||
if (account.isPresent()) {
|
||||
try {
|
||||
List<Address> newUsers = DatabaseFactory.getContactsDatabase(context)
|
||||
.setRegisteredUsers(account.get().getAccount(), activeAddresses, removeMissing);
|
||||
DatabaseFactory.getContactsDatabase(context).setRegisteredUsers(account.get().getAccount(), activeAddresses, removeMissing);
|
||||
|
||||
Cursor cursor = ContactAccessor.getInstance().getAllSystemContacts(context);
|
||||
RecipientDatabase.BulkOperationsHandle handle = DatabaseFactory.getRecipientDatabase(context).resetAllDisplayNames();
|
||||
@ -158,13 +164,10 @@ public class DirectoryHelper {
|
||||
handle.finish();
|
||||
}
|
||||
|
||||
return new RefreshResult(newUsers, account.get().isFresh());
|
||||
} catch (RemoteException | OperationApplicationException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
|
||||
return new RefreshResult(new LinkedList<Address>(), false);
|
||||
}
|
||||
|
||||
private static void notifyNewUsers(@NonNull Context context,
|
||||
@ -240,23 +243,4 @@ public class DirectoryHelper {
|
||||
|
||||
}
|
||||
|
||||
private static class RefreshResult {
|
||||
|
||||
private final List<Address> newUsers;
|
||||
private final boolean fresh;
|
||||
|
||||
private RefreshResult(List<Address> newUsers, boolean fresh) {
|
||||
this.newUsers = newUsers;
|
||||
this.fresh = fresh;
|
||||
}
|
||||
|
||||
public List<Address> getNewUsers() {
|
||||
return newUsers;
|
||||
}
|
||||
|
||||
public boolean isFresh() {
|
||||
return fresh;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user