diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java index 9d7411ae9..b98f89ba5 100644 --- a/src/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationActivity.java @@ -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 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 diff --git a/src/org/thoughtcrime/securesms/ConversationListActivity.java b/src/org/thoughtcrime/securesms/ConversationListActivity.java index e7cbaf6e8..4b858d79e 100644 --- a/src/org/thoughtcrime/securesms/ConversationListActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationListActivity.java @@ -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); - } } diff --git a/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java b/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java index 4025b185d..7564d66e6 100644 --- a/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java +++ b/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java @@ -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) { diff --git a/src/org/thoughtcrime/securesms/contacts/ContactsDatabase.java b/src/org/thoughtcrime/securesms/contacts/ContactsDatabase.java index ea64d7b31..34c0e6f61 100644 --- a/src/org/thoughtcrime/securesms/contacts/ContactsDatabase.java +++ b/src/org/thoughtcrime/securesms/contacts/ContactsDatabase.java @@ -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
setRegisteredUsers(@NonNull Account account, - @NonNull List
registeredAddressList, - boolean remove) + public synchronized void setRegisteredUsers(@NonNull Account account, + @NonNull List
registeredAddressList, + boolean remove) throws RemoteException, OperationApplicationException { Set
registeredAddressSet = new HashSet<>(); - List
addedAddresses = new LinkedList<>(); ArrayList operations = new ArrayList<>(); Map 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) { diff --git a/src/org/thoughtcrime/securesms/database/GroupDatabase.java b/src/org/thoughtcrime/securesms/database/GroupDatabase.java index 6c9bdd672..99576a1fc 100644 --- a/src/org/thoughtcrime/securesms/database/GroupDatabase.java +++ b/src/org/thoughtcrime/securesms/database/GroupDatabase.java @@ -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
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; diff --git a/src/org/thoughtcrime/securesms/database/RecipientDatabase.java b/src/org/thoughtcrime/securesms/database/RecipientDatabase.java index 9ccaf3487..c349c35e4 100644 --- a/src/org/thoughtcrime/securesms/database/RecipientDatabase.java +++ b/src/org/thoughtcrime/securesms/database/RecipientDatabase.java @@ -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); } diff --git a/src/org/thoughtcrime/securesms/recipients/Recipient.java b/src/org/thoughtcrime/securesms/recipients/Recipient.java index f4a8628cf..6ad9a5cff 100644 --- a/src/org/thoughtcrime/securesms/recipients/Recipient.java +++ b/src/org/thoughtcrime/securesms/recipients/Recipient.java @@ -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 listeners = Collections.newSetFromMap(new WeakHashMap()); @@ -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 settings, @NonNull Optional 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 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 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; } diff --git a/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java b/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java index dcd32c38d..713c782ed 100644 --- a/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java +++ b/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java @@ -77,7 +77,7 @@ class RecipientProvider { @NonNull Recipient getRecipient(Context context, Address address, Optional settings, Optional 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 createPrefetchedRecipientDetails(@NonNull Context context, @NonNull Address address, @NonNull Optional settings, @NonNull Optional groupRecord) @@ -276,12 +272,6 @@ class RecipientProvider { cache.put(address, recipient); } - public synchronized void reset() { - for (Recipient recipient : cache.values()) { - recipient.setStale(); - } - } - } } \ No newline at end of file diff --git a/src/org/thoughtcrime/securesms/util/DirectoryHelper.java b/src/org/thoughtcrime/securesms/util/DirectoryHelper.java index a22daf1ae..c8ec529f1 100644 --- a/src/org/thoughtcrime/securesms/util/DirectoryHelper.java +++ b/src/org/thoughtcrime/securesms/util/DirectoryHelper.java @@ -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
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
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
currentActiveAddresses = new HashSet<>(recipientDatabase.getRegistered()); + List
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 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
activeAddresses, boolean removeMissing) { + private static void updateContactsDatabase(@NonNull Context context, @NonNull List
activeAddresses, boolean removeMissing) { Optional account = getOrCreateAccount(context); if (account.isPresent()) { try { - List
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
(), false); } private static void notifyNewUsers(@NonNull Context context, @@ -240,23 +243,4 @@ public class DirectoryHelper { } - private static class RefreshResult { - - private final List
newUsers; - private final boolean fresh; - - private RefreshResult(List
newUsers, boolean fresh) { - this.newUsers = newUsers; - this.fresh = fresh; - } - - public List
getNewUsers() { - return newUsers; - } - - public boolean isFresh() { - return fresh; - } - } - }