mirror of
https://github.com/oxen-io/session-android.git
synced 2025-01-11 16:13:57 +00:00
Access all RecipientDatabase settings directly from Recipient
// FREEBIE
This commit is contained in:
parent
d1790dfe17
commit
f17af19d09
@ -108,8 +108,7 @@ import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.VerifiedStatus;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsColumns.Types;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientPreferenceEvent;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.database.identity.IdentityRecordList;
|
||||
@ -142,7 +141,6 @@ import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||
import org.thoughtcrime.securesms.util.CharacterCalculator.CharacterState;
|
||||
import org.thoughtcrime.securesms.util.Dialogs;
|
||||
import org.thoughtcrime.securesms.util.DirectoryHelper;
|
||||
import org.thoughtcrime.securesms.util.DirectoryHelper.Capability;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.ExpirationUtil;
|
||||
@ -574,10 +572,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
|
||||
.setExpireMessages(recipient, expirationTime);
|
||||
recipient.setExpireMessages(expirationTime);
|
||||
|
||||
DatabaseFactory.getRecipientDatabase(ConversationActivity.this).setExpireMessages(recipient, expirationTime);
|
||||
OutgoingExpirationUpdateMessage outgoingMessage = new OutgoingExpirationUpdateMessage(getRecipient(), System.currentTimeMillis(), expirationTime * 1000);
|
||||
MessageSender.send(ConversationActivity.this, masterSecret, outgoingMessage, threadId, false, null);
|
||||
|
||||
@ -639,8 +634,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
.setPositiveButton(R.string.ConversationActivity_unblock, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
recipient.setBlocked(false);
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
@ -1012,19 +1005,19 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
new AsyncTask<Recipient, Void, boolean[]>() {
|
||||
@Override
|
||||
protected boolean[] doInBackground(Recipient... params) {
|
||||
Context context = ConversationActivity.this;
|
||||
Recipient recipient = params[0];
|
||||
Capability capability = DirectoryHelper.getUserCapabilities(context, recipient);
|
||||
Context context = ConversationActivity.this;
|
||||
Recipient recipient = params[0];
|
||||
RegisteredState registeredState = recipient.resolve().getRegistered();
|
||||
|
||||
if (capability == Capability.UNKNOWN) {
|
||||
if (registeredState == RegisteredState.UNKNOWN) {
|
||||
try {
|
||||
capability = DirectoryHelper.refreshDirectoryFor(context, masterSecret, recipient);
|
||||
registeredState = DirectoryHelper.refreshDirectoryFor(context, masterSecret, recipient);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
|
||||
return new boolean[] {capability == Capability.SUPPORTED, Util.isDefaultSmsProvider(context)};
|
||||
return new boolean[] {registeredState == RegisteredState.REGISTERED, Util.isDefaultSmsProvider(context)};
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1041,11 +1034,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private void onSecurityUpdated() {
|
||||
updateRecipientPreferences();
|
||||
}
|
||||
|
||||
private void updateRecipientPreferences() {
|
||||
new RecipientPreferencesTask().execute(recipient);
|
||||
updateInviteReminder(recipient.hasSeenInviteReminder());
|
||||
updateDefaultSubscriptionId(recipient.getDefaultSubscriptionId());
|
||||
}
|
||||
|
||||
protected void updateInviteReminder(boolean seenInvite) {
|
||||
@ -1284,19 +1274,14 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
titleView.setVerified(identityRecords.isVerified());
|
||||
setBlockedUserState(recipient, isSecureText, isDefaultSms);
|
||||
setActionBarColor(recipient.getColor());
|
||||
updateInviteReminder(recipient.hasSeenInviteReminder());
|
||||
updateDefaultSubscriptionId(recipient.getDefaultSubscriptionId());
|
||||
initializeSecurity(isSecureText, isDefaultSms);
|
||||
invalidateOptionsMenu();
|
||||
updateRecipientPreferences();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onRecipientPreferenceUpdate(final RecipientPreferenceEvent event) {
|
||||
if (event.getRecipient().getAddress().equals(this.recipient.getAddress())) {
|
||||
new RecipientPreferencesTask().execute(this.recipient);
|
||||
}
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onIdentityRecordUpdate(final IdentityRecord event) {
|
||||
initializeIdentityRecords();
|
||||
@ -1652,7 +1637,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
@Override
|
||||
protected Long doInBackground(OutgoingMediaMessage... messages) {
|
||||
if (initiating) {
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient.getAddress(), true);
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true);
|
||||
}
|
||||
|
||||
return MessageSender.send(context, masterSecret, messages[0], threadId, forceSms, new SmsDatabase.InsertListener() {
|
||||
@ -1692,7 +1677,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
@Override
|
||||
protected Long doInBackground(OutgoingTextMessage... messages) {
|
||||
if (initiatingConversation) {
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient.getAddress(), true);
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true);
|
||||
}
|
||||
|
||||
return MessageSender.send(context, masterSecret, messages[0], threadId, forceSms, new SmsDatabase.InsertListener() {
|
||||
@ -1989,27 +1974,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
updateToggleButtonState();
|
||||
}
|
||||
|
||||
private class RecipientPreferencesTask extends AsyncTask<Recipient, Void, Pair<Recipient,RecipientSettings>> {
|
||||
@Override
|
||||
protected Pair<Recipient, RecipientSettings> doInBackground(Recipient... recipient) {
|
||||
if (recipient.length != 1 || recipient[0] == null) {
|
||||
throw new AssertionError("task needs exactly one Recipients object");
|
||||
}
|
||||
|
||||
Optional<RecipientSettings> prefs = DatabaseFactory.getRecipientDatabase(ConversationActivity.this)
|
||||
.getRecipientSettings(recipient[0].getAddress());
|
||||
return new Pair<>(recipient[0], prefs.orNull());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(@NonNull Pair<Recipient, RecipientSettings> result) {
|
||||
if (result.first == recipient) {
|
||||
updateInviteReminder(result.second != null && result.second.hasSeenInviteReminder());
|
||||
updateDefaultSubscriptionId(result.second != null ? result.second.getDefaultSubscriptionId() : Optional.<Integer>absent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class UnverifiedDismissedListener implements UnverifiedBannerView.DismissListener {
|
||||
@Override
|
||||
public void onDismissed(final List<IdentityRecord> unverifiedIdentities) {
|
||||
|
@ -18,7 +18,6 @@
|
||||
package org.thoughtcrime.securesms;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
@ -54,7 +53,7 @@ import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager;
|
||||
import org.thoughtcrime.securesms.groups.GroupManager.GroupActionResult;
|
||||
@ -167,9 +166,8 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isActiveInDirectory(Context context, Recipient recipient) {
|
||||
Optional<RecipientSettings> preferences = DatabaseFactory.getRecipientDatabase(context).getRecipientSettings(recipient.getAddress());
|
||||
return preferences.isPresent() && preferences.get().isRegistered();
|
||||
private static boolean isActiveInDirectory(Recipient recipient) {
|
||||
return recipient.resolve().getRegistered() == RecipientDatabase.RegisteredState.REGISTERED;
|
||||
}
|
||||
|
||||
private void addSelectedContacts(@NonNull Recipient... recipients) {
|
||||
@ -495,7 +493,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
final List<Result> results = new LinkedList<>();
|
||||
|
||||
for (Recipient recipient : recipients) {
|
||||
boolean isPush = isActiveInDirectory(activity, recipient);
|
||||
boolean isPush = isActiveInDirectory(recipient);
|
||||
|
||||
if (failIfNotPush && !isPush) {
|
||||
results.add(new Result(null, false, activity.getString(R.string.GroupCreateActivity_cannot_add_non_push_to_existing_group,
|
||||
|
@ -230,9 +230,8 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
|
||||
if (context == null) return null;
|
||||
|
||||
for (String number : numbers) {
|
||||
Recipient recipient = Recipient.from(context, Address.fromExternal(context, number), false);
|
||||
Optional<RecipientSettings> settings = DatabaseFactory.getRecipientDatabase(context).getRecipientSettings(recipient.getAddress());
|
||||
int subscriptionId = settings.isPresent() ? settings.get().getDefaultSubscriptionId().or(-1) : -1;
|
||||
Recipient recipient = Recipient.from(context, Address.fromExternal(context, number), false);
|
||||
int subscriptionId = recipient.getDefaultSubscriptionId().or(-1);
|
||||
|
||||
MessageSender.send(context, masterSecret, new OutgoingTextMessage(recipient, message, subscriptionId), -1L, true, null);
|
||||
|
||||
|
@ -36,6 +36,7 @@ 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;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob;
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
|
||||
@ -43,7 +44,6 @@ import org.thoughtcrime.securesms.preferences.AdvancedRingtonePreference;
|
||||
import org.thoughtcrime.securesms.preferences.ColorPreference;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.util.DirectoryHelper;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
@ -350,8 +350,6 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
uri = Uri.parse(value);
|
||||
}
|
||||
|
||||
recipient.setRingtone(uri);
|
||||
|
||||
new AsyncTask<Uri, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Uri... params) {
|
||||
@ -371,8 +369,6 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
int value = Integer.parseInt((String) newValue);
|
||||
final VibrateState vibrateState = VibrateState.fromId(value);
|
||||
|
||||
recipient.setVibrate(vibrateState);
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
@ -397,16 +393,13 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
if (selectedColor == null) return true;
|
||||
|
||||
if (preference.isEnabled() && !currentColor.equals(selectedColor)) {
|
||||
recipient.setColor(selectedColor);
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
Context context = getActivity();
|
||||
DatabaseFactory.getRecipientDatabase(context)
|
||||
.setColor(recipient, selectedColor);
|
||||
DatabaseFactory.getRecipientDatabase(context).setColor(recipient, selectedColor);
|
||||
|
||||
if (DirectoryHelper.getUserCapabilities(context, recipient) == DirectoryHelper.Capability.SUPPORTED) {
|
||||
if (recipient.resolve().getRegistered() == RecipientDatabase.RegisteredState.REGISTERED) {
|
||||
ApplicationContext.getInstance(context)
|
||||
.getJobManager()
|
||||
.add(new MultiDeviceContactUpdateJob(context, recipient.getAddress()));
|
||||
@ -516,8 +509,6 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
}
|
||||
|
||||
private void setBlocked(final Recipient recipient, final boolean blocked) {
|
||||
recipient.setBlocked(blocked);
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
|
@ -29,8 +29,8 @@ import android.util.Log;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.DirectoryHelper;
|
||||
import org.thoughtcrime.securesms.util.NumberUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -102,9 +102,9 @@ public class ContactsCursorLoader extends CursorLoader {
|
||||
ContactsDatabase.CONTACT_TYPE_COLUMN});
|
||||
while (cursor.moveToNext()) {
|
||||
final String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_COLUMN));
|
||||
final Recipient recipient = Recipient.from(getContext(), Address.fromExternal(getContext(), number), true);
|
||||
final Recipient recipient = Recipient.from(getContext(), Address.fromExternal(getContext(), number), false);
|
||||
|
||||
if (DirectoryHelper.getUserCapabilities(getContext(), recipient) != DirectoryHelper.Capability.SUPPORTED) {
|
||||
if (recipient.resolve().getRegistered() != RecipientDatabase.RegisteredState.REGISTERED) {
|
||||
matrix.addRow(new Object[]{cursor.getLong(cursor.getColumnIndexOrThrow(ContactsDatabase.ID_COLUMN)),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NAME_COLUMN)),
|
||||
number,
|
||||
|
@ -32,4 +32,9 @@ public class BitmapContactPhoto implements ContactPhoto {
|
||||
public Drawable asCallCard(Context context) {
|
||||
return new BitmapDrawable(context.getResources(), bitmap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGenerated() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -8,5 +8,6 @@ public interface ContactPhoto {
|
||||
public Drawable asDrawable(Context context, int color);
|
||||
public Drawable asDrawable(Context context, int color, boolean inverted);
|
||||
public Drawable asCallCard(Context context);
|
||||
public boolean isGenerated();
|
||||
|
||||
}
|
||||
|
@ -50,4 +50,9 @@ public class GeneratedContactPhoto implements ContactPhoto {
|
||||
public Drawable asCallCard(Context context) {
|
||||
return ContextCompat.getDrawable(context, R.drawable.ic_contact_picture_large);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGenerated() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -45,6 +45,11 @@ public class ResourceContactPhoto implements ContactPhoto {
|
||||
return context.getResources().getDrawable(resourceId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGenerated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static class ExpandingLayerDrawable extends LayerDrawable {
|
||||
public ExpandingLayerDrawable(Drawable[] layers) {
|
||||
super(layers);
|
||||
|
@ -26,4 +26,9 @@ public class TransparentContactPhoto implements ContactPhoto {
|
||||
public Drawable asCallCard(Context context) {
|
||||
return ContextCompat.getDrawable(context, R.drawable.ic_contact_picture_large);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGenerated() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -191,20 +191,20 @@ public class DatabaseFactory {
|
||||
}
|
||||
|
||||
private DatabaseFactory(Context context) {
|
||||
this.databaseHelper = new DatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
this.sms = new SmsDatabase(context, databaseHelper);
|
||||
this.encryptingSms = new EncryptingSmsDatabase(context, databaseHelper);
|
||||
this.mms = new MmsDatabase(context, databaseHelper);
|
||||
this.attachments = new AttachmentDatabase(context, databaseHelper);
|
||||
this.media = new MediaDatabase(context, databaseHelper);
|
||||
this.thread = new ThreadDatabase(context, databaseHelper);
|
||||
this.mmsSmsDatabase = new MmsSmsDatabase(context, databaseHelper);
|
||||
this.identityDatabase = new IdentityDatabase(context, databaseHelper);
|
||||
this.draftDatabase = new DraftDatabase(context, databaseHelper);
|
||||
this.pushDatabase = new PushDatabase(context, databaseHelper);
|
||||
this.groupDatabase = new GroupDatabase(context, databaseHelper);
|
||||
this.databaseHelper = new DatabaseHelper(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||
this.sms = new SmsDatabase(context, databaseHelper);
|
||||
this.encryptingSms = new EncryptingSmsDatabase(context, databaseHelper);
|
||||
this.mms = new MmsDatabase(context, databaseHelper);
|
||||
this.attachments = new AttachmentDatabase(context, databaseHelper);
|
||||
this.media = new MediaDatabase(context, databaseHelper);
|
||||
this.thread = new ThreadDatabase(context, databaseHelper);
|
||||
this.mmsSmsDatabase = new MmsSmsDatabase(context, databaseHelper);
|
||||
this.identityDatabase = new IdentityDatabase(context, databaseHelper);
|
||||
this.draftDatabase = new DraftDatabase(context, databaseHelper);
|
||||
this.pushDatabase = new PushDatabase(context, databaseHelper);
|
||||
this.groupDatabase = new GroupDatabase(context, databaseHelper);
|
||||
this.recipientDatabase = new RecipientDatabase(context, databaseHelper);
|
||||
this.contactsDatabase = new ContactsDatabase(context);
|
||||
this.contactsDatabase = new ContactsDatabase(context);
|
||||
}
|
||||
|
||||
public void reset(Context context) {
|
||||
@ -1290,7 +1290,7 @@ public class DatabaseFactory {
|
||||
String address = new NumberMigrator(TextSecurePreferences.getLocalNumber(context)).migrate(cursor.getString(0));
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
|
||||
contentValues.put("registered", cursor.getInt(1) == 1);
|
||||
contentValues.put("registered", cursor.getInt(1) == 1 ? 1 : 2);
|
||||
|
||||
if (db.update("recipient_preferences", contentValues, "recipient_ids = ?", new String[] {address}) < 1) {
|
||||
contentValues.put("recipient_ids", address);
|
||||
|
@ -12,10 +12,11 @@ import android.util.Log;
|
||||
|
||||
import com.annimon.stream.Stream;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhotoFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.whispersystems.libsignal.util.Pair;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -74,6 +75,24 @@ public class RecipientDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
public enum RegisteredState {
|
||||
UNKNOWN(0), REGISTERED(1), NOT_REGISTERED(2);
|
||||
|
||||
private final int id;
|
||||
|
||||
RegisteredState(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public static RegisteredState fromId(int id) {
|
||||
return values()[id];
|
||||
}
|
||||
}
|
||||
|
||||
public static final String CREATE_TABLE =
|
||||
"CREATE TABLE " + TABLE_NAME +
|
||||
" (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
@ -120,7 +139,7 @@ public class RecipientDatabase extends Database {
|
||||
cursor = database.query(TABLE_NAME, null, ADDRESS + " = ?", new String[] {address.serialize()}, null, null, null);
|
||||
|
||||
if (cursor != null && cursor.moveToNext()) {
|
||||
return getRecipientPreferences(cursor);
|
||||
return getRecipientSettings(cursor);
|
||||
}
|
||||
|
||||
return Optional.absent();
|
||||
@ -129,7 +148,7 @@ public class RecipientDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
Optional<RecipientSettings> getRecipientPreferences(@NonNull Cursor cursor) {
|
||||
Optional<RecipientSettings> getRecipientSettings(@NonNull Cursor cursor) {
|
||||
boolean blocked = cursor.getInt(cursor.getColumnIndexOrThrow(BLOCK)) == 1;
|
||||
String notification = cursor.getString(cursor.getColumnIndexOrThrow(NOTIFICATION));
|
||||
int vibrateState = cursor.getInt(cursor.getColumnIndexOrThrow(VIBRATE));
|
||||
@ -139,12 +158,12 @@ public class RecipientDatabase extends Database {
|
||||
boolean seenInviteReminder = cursor.getInt(cursor.getColumnIndexOrThrow(SEEN_INVITE_REMINDER)) == 1;
|
||||
int defaultSubscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(DEFAULT_SUBSCRIPTION_ID));
|
||||
int expireMessages = cursor.getInt(cursor.getColumnIndexOrThrow(EXPIRE_MESSAGES));
|
||||
boolean registered = cursor.getInt(cursor.getColumnIndexOrThrow(REGISTERED)) == 1;
|
||||
int registeredState = cursor.getInt(cursor.getColumnIndexOrThrow(REGISTERED));
|
||||
String profileKeyString = cursor.getString(cursor.getColumnIndexOrThrow(PROFILE_KEY));
|
||||
String systemDisplayName = cursor.getString(cursor.getColumnIndexOrThrow(SYSTEM_DISPLAY_NAME));
|
||||
String signalProfileName = cursor.getString(cursor.getColumnIndexOrThrow(SIGNAL_PROFILE_NAME));
|
||||
String signalProfileAvatar = cursor.getString(cursor.getColumnIndexOrThrow(SIGNAL_PROFILE_AVATAR));
|
||||
boolean profileSharing = cursor.getInt(cursor.getColumnIndexOrThrow(PROFILE_SHARING)) == 1;
|
||||
boolean profileSharing = cursor.getInt(cursor.getColumnIndexOrThrow(PROFILE_SHARING)) == 1;
|
||||
|
||||
MaterialColor color;
|
||||
byte[] profileKey = null;
|
||||
@ -168,7 +187,8 @@ public class RecipientDatabase extends Database {
|
||||
return Optional.of(new RecipientSettings(blocked, muteUntil,
|
||||
VibrateState.fromId(vibrateState),
|
||||
notificationUri, color, seenInviteReminder,
|
||||
defaultSubscriptionId, expireMessages, registered,
|
||||
defaultSubscriptionId, expireMessages,
|
||||
RegisteredState.fromId(registeredState),
|
||||
profileKey, systemDisplayName, signalProfileName,
|
||||
signalProfileAvatar, profileSharing));
|
||||
}
|
||||
@ -185,117 +205,129 @@ public class RecipientDatabase extends Database {
|
||||
return new BulkOperationsHandle(database);
|
||||
}
|
||||
|
||||
public void setColor(Recipient recipient, MaterialColor color) {
|
||||
public void setColor(@NonNull Recipient recipient, @NonNull MaterialColor color) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(COLOR, color.serialize());
|
||||
updateOrInsert(recipient.getAddress(), values);
|
||||
recipient.resolve().setColor(color);
|
||||
}
|
||||
|
||||
public void setDefaultSubscriptionId(@NonNull Recipient recipient, int defaultSubscriptionId) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(DEFAULT_SUBSCRIPTION_ID, defaultSubscriptionId);
|
||||
updateOrInsert(recipient.getAddress(), values);
|
||||
EventBus.getDefault().post(new RecipientPreferenceEvent(recipient));
|
||||
recipient.resolve().setDefaultSubscriptionId(Optional.of(defaultSubscriptionId));
|
||||
}
|
||||
|
||||
public void setBlocked(Recipient recipient, boolean blocked) {
|
||||
public void setBlocked(@NonNull Recipient recipient, boolean blocked) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(BLOCK, blocked ? 1 : 0);
|
||||
updateOrInsert(recipient.getAddress(), values);
|
||||
recipient.resolve().setBlocked(blocked);
|
||||
}
|
||||
|
||||
public void setRingtone(Recipient recipient, @Nullable Uri notification) {
|
||||
public void setRingtone(@NonNull Recipient recipient, @Nullable Uri notification) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(NOTIFICATION, notification == null ? null : notification.toString());
|
||||
updateOrInsert(recipient.getAddress(), values);
|
||||
recipient.resolve().setRingtone(notification);
|
||||
}
|
||||
|
||||
public void setVibrate(Recipient recipient, @NonNull VibrateState enabled) {
|
||||
public void setVibrate(@NonNull Recipient recipient, @NonNull VibrateState enabled) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(VIBRATE, enabled.getId());
|
||||
updateOrInsert(recipient.getAddress(), values);
|
||||
recipient.resolve().setVibrate(enabled);
|
||||
}
|
||||
|
||||
public void setMuted(Recipient recipient, long until) {
|
||||
public void setMuted(@NonNull Recipient recipient, long until) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(MUTE_UNTIL, until);
|
||||
updateOrInsert(recipient.getAddress(), values);
|
||||
recipient.resolve().setMuted(until);
|
||||
}
|
||||
|
||||
public void setSeenInviteReminder(Recipient recipient, boolean seen) {
|
||||
public void setSeenInviteReminder(@NonNull Recipient recipient, boolean seen) {
|
||||
ContentValues values = new ContentValues(1);
|
||||
values.put(SEEN_INVITE_REMINDER, seen ? 1 : 0);
|
||||
updateOrInsert(recipient.getAddress(), values);
|
||||
recipient.resolve().setHasSeenInviteReminder(seen);
|
||||
}
|
||||
|
||||
public void setExpireMessages(Recipient recipient, int expiration) {
|
||||
public void setExpireMessages(@NonNull Recipient recipient, int expiration) {
|
||||
recipient.setExpireMessages(expiration);
|
||||
|
||||
ContentValues values = new ContentValues(1);
|
||||
values.put(EXPIRE_MESSAGES, expiration);
|
||||
updateOrInsert(recipient.getAddress(), values);
|
||||
recipient.resolve().setExpireMessages(expiration);
|
||||
}
|
||||
|
||||
public void setSystemDisplayName(@NonNull Address address, @Nullable String systemDisplayName) {
|
||||
ContentValues values = new ContentValues(1);
|
||||
values.put(SYSTEM_DISPLAY_NAME, systemDisplayName);
|
||||
updateOrInsert(address, values);
|
||||
}
|
||||
|
||||
public void setProfileKey(@NonNull Address address, @Nullable byte[] profileKey) {
|
||||
public void setProfileKey(@NonNull Recipient recipient, @Nullable byte[] profileKey) {
|
||||
ContentValues values = new ContentValues(1);
|
||||
values.put(PROFILE_KEY, profileKey == null ? null : Base64.encodeBytes(profileKey));
|
||||
updateOrInsert(address, values);;
|
||||
updateOrInsert(recipient.getAddress(), values);
|
||||
recipient.resolve().setProfileKey(profileKey);
|
||||
}
|
||||
|
||||
public void setProfileName(@NonNull Address address, @Nullable String profileName) {
|
||||
public void setProfileName(@NonNull Recipient recipient, @Nullable String profileName) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(SIGNAL_PROFILE_NAME, profileName);
|
||||
updateOrInsert(address, contentValues);
|
||||
updateOrInsert(recipient.getAddress(), contentValues);
|
||||
recipient.resolve().setProfileName(profileName);
|
||||
}
|
||||
|
||||
public void setProfileAvatar(@NonNull Address address, @Nullable String profileAvatar) {
|
||||
public void setProfileAvatar(@NonNull Recipient recipient, @Nullable String profileAvatar) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(SIGNAL_PROFILE_AVATAR, profileAvatar);
|
||||
updateOrInsert(address, contentValues);
|
||||
updateOrInsert(recipient.getAddress(), contentValues);
|
||||
recipient.resolve().setProfileAvatar(profileAvatar);
|
||||
}
|
||||
|
||||
public void setProfileSharing(@NonNull Address address, boolean enabled) {
|
||||
public void setProfileSharing(@NonNull Recipient recipient, boolean enabled) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(PROFILE_SHARING, enabled ? 1 : 0);
|
||||
updateOrInsert(address, contentValues);
|
||||
updateOrInsert(recipient.getAddress(), contentValues);
|
||||
recipient.setProfileSharing(enabled);
|
||||
}
|
||||
|
||||
public Set<Address> getAllRecipients() {
|
||||
public Set<Recipient> getAllRecipients() {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
Set<Address> results = new HashSet<>();
|
||||
Set<Recipient> results = new HashSet<>();
|
||||
|
||||
try (Cursor cursor = db.query(TABLE_NAME, new String[] {ADDRESS}, null, null, null, null, null)) {
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
results.add(Address.fromExternal(context, cursor.getString(0)));
|
||||
results.add(Recipient.from(context, Address.fromExternal(context, cursor.getString(0)), true));
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public void setRegistered(@NonNull List<Address> activeAddresses,
|
||||
@NonNull List<Address> inactiveAddresses)
|
||||
public void setRegistered(@NonNull Recipient recipient, RegisteredState registeredState) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(REGISTERED, registeredState.getId());
|
||||
updateOrInsert(recipient.getAddress(), contentValues);
|
||||
recipient.setRegistered(registeredState);
|
||||
}
|
||||
|
||||
public void setRegistered(@NonNull List<Recipient> activeRecipients,
|
||||
@NonNull List<Recipient> inactiveRecipients)
|
||||
{
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
|
||||
for (Address activeAddress : activeAddresses) {
|
||||
for (Recipient activeRecipient : activeRecipients) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(REGISTERED, 1);
|
||||
contentValues.put(REGISTERED, RegisteredState.REGISTERED.getId());
|
||||
|
||||
updateOrInsert(activeAddress, contentValues);
|
||||
updateOrInsert(activeRecipient.getAddress(), contentValues);
|
||||
activeRecipient.setRegistered(RegisteredState.REGISTERED);
|
||||
}
|
||||
|
||||
for (Address inactiveAddress : inactiveAddresses) {
|
||||
for (Recipient inactiveRecipient : inactiveRecipients) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(REGISTERED, 0);
|
||||
contentValues.put(REGISTERED, RegisteredState.NOT_REGISTERED.getId());
|
||||
|
||||
updateOrInsert(inactiveAddress, contentValues);
|
||||
updateOrInsert(inactiveRecipient.getAddress(), contentValues);
|
||||
inactiveRecipient.setRegistered(RegisteredState.NOT_REGISTERED);
|
||||
}
|
||||
|
||||
context.getContentResolver().notifyChange(Uri.parse(RECIPIENT_PREFERENCES_URI), null);
|
||||
@ -341,39 +373,44 @@ public class RecipientDatabase extends Database {
|
||||
|
||||
private final SQLiteDatabase database;
|
||||
|
||||
public BulkOperationsHandle(SQLiteDatabase database) {
|
||||
private final List<Pair<Recipient, String>> pendingDisplayNames = new LinkedList<>();
|
||||
|
||||
BulkOperationsHandle(SQLiteDatabase database) {
|
||||
this.database = database;
|
||||
}
|
||||
|
||||
public void setDisplayName(@NonNull Address address, @Nullable String displayName) {
|
||||
public void setDisplayName(@NonNull Recipient recipient, @Nullable String displayName) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(SYSTEM_DISPLAY_NAME, displayName);
|
||||
updateOrInsert(address, contentValues);
|
||||
updateOrInsert(recipient.getAddress(), contentValues);
|
||||
pendingDisplayNames.add(new Pair<>(recipient, displayName));
|
||||
}
|
||||
|
||||
public void finish() {
|
||||
database.setTransactionSuccessful();
|
||||
database.endTransaction();
|
||||
Recipient.clearCache(context);
|
||||
|
||||
Stream.of(pendingDisplayNames).forEach(pair -> pair.first().resolve().setSystemDisplayName(pair.second()));
|
||||
|
||||
context.getContentResolver().notifyChange(Uri.parse(RECIPIENT_PREFERENCES_URI), null);
|
||||
}
|
||||
}
|
||||
|
||||
public static class RecipientSettings {
|
||||
private final boolean blocked;
|
||||
private final long muteUntil;
|
||||
private final VibrateState vibrateState;
|
||||
private final Uri notification;
|
||||
private final MaterialColor color;
|
||||
private final boolean seenInviteReminder;
|
||||
private final int defaultSubscriptionId;
|
||||
private final int expireMessages;
|
||||
private final boolean registered;
|
||||
private final byte[] profileKey;
|
||||
private final String systemDisplayName;
|
||||
private final String signalProfileName;
|
||||
private final String signalProfileAvatar;
|
||||
private final boolean profileSharing;
|
||||
private final boolean blocked;
|
||||
private final long muteUntil;
|
||||
private final VibrateState vibrateState;
|
||||
private final Uri notification;
|
||||
private final MaterialColor color;
|
||||
private final boolean seenInviteReminder;
|
||||
private final int defaultSubscriptionId;
|
||||
private final int expireMessages;
|
||||
private final RegisteredState registered;
|
||||
private final byte[] profileKey;
|
||||
private final String systemDisplayName;
|
||||
private final String signalProfileName;
|
||||
private final String signalProfileAvatar;
|
||||
private final boolean profileSharing;
|
||||
|
||||
RecipientSettings(boolean blocked, long muteUntil,
|
||||
@NonNull VibrateState vibrateState,
|
||||
@ -382,7 +419,7 @@ public class RecipientDatabase extends Database {
|
||||
boolean seenInviteReminder,
|
||||
int defaultSubscriptionId,
|
||||
int expireMessages,
|
||||
boolean registered,
|
||||
@NonNull RegisteredState registered,
|
||||
@Nullable byte[] profileKey,
|
||||
@Nullable String systemDisplayName,
|
||||
@Nullable String signalProfileName,
|
||||
@ -437,7 +474,7 @@ public class RecipientDatabase extends Database {
|
||||
return expireMessages;
|
||||
}
|
||||
|
||||
public boolean isRegistered() {
|
||||
public RegisteredState getRegistered() {
|
||||
return registered;
|
||||
}
|
||||
|
||||
@ -485,17 +522,4 @@ public class RecipientDatabase extends Database {
|
||||
return getCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
public static class RecipientPreferenceEvent {
|
||||
|
||||
private final Recipient recipient;
|
||||
|
||||
public RecipientPreferenceEvent(Recipient recipients) {
|
||||
this.recipient = recipients;
|
||||
}
|
||||
|
||||
public Recipient getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -624,7 +624,7 @@ public class ThreadDatabase extends Database {
|
||||
Optional<GroupRecord> groupRecord;
|
||||
|
||||
if (distributionType != DistributionTypes.ARCHIVE) {
|
||||
settings = DatabaseFactory.getRecipientDatabase(context).getRecipientPreferences(cursor);
|
||||
settings = DatabaseFactory.getRecipientDatabase(context).getRecipientSettings(cursor);
|
||||
groupRecord = DatabaseFactory.getGroupDatabase(context).getGroup(cursor);
|
||||
} else {
|
||||
settings = Optional.absent();
|
||||
|
@ -43,21 +43,21 @@ public class GroupManager {
|
||||
@Nullable String name,
|
||||
boolean mms)
|
||||
{
|
||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
final String groupId = GroupUtil.getEncodedId(groupDatabase.allocateGroupId(), mms);
|
||||
final Set<Address> memberAddresses = getMemberAddresses(members);
|
||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
final String groupId = GroupUtil.getEncodedId(groupDatabase.allocateGroupId(), mms);
|
||||
final Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), false);
|
||||
final Set<Address> memberAddresses = getMemberAddresses(members);
|
||||
|
||||
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
||||
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null);
|
||||
|
||||
if (!mms) {
|
||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(Address.fromSerialized(groupId), true);
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(groupRecipient, true);
|
||||
return sendGroupUpdate(context, masterSecret, groupId, memberAddresses, name, avatarBytes);
|
||||
} else {
|
||||
Recipient groupRecipient = Recipient.from(context, Address.fromSerialized(groupId), true);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
||||
return new GroupActionResult(groupRecipient, threadId);
|
||||
}
|
||||
}
|
||||
|
@ -803,19 +803,14 @@ public class PushDecryptJob extends ContextJob {
|
||||
private void handleProfileKey(@NonNull SignalServiceEnvelope envelope,
|
||||
@NonNull SignalServiceDataMessage message)
|
||||
{
|
||||
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
|
||||
Address sourceAddress = Address.fromExternal(context, envelope.getSource());
|
||||
Optional<RecipientSettings> settings = database.getRecipientSettings(sourceAddress);
|
||||
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
|
||||
Address sourceAddress = Address.fromExternal(context, envelope.getSource());
|
||||
Recipient recipient = Recipient.from(context, sourceAddress, false);
|
||||
|
||||
if (!settings.isPresent() || settings.get().getProfileKey() == null ||
|
||||
!MessageDigest.isEqual(message.getProfileKey().get(), settings.get().getProfileKey()))
|
||||
{
|
||||
database.setProfileKey(sourceAddress, message.getProfileKey().get());
|
||||
|
||||
Recipient recipient = Recipient.from(context, sourceAddress, true);
|
||||
if (recipient.getProfileKey() == null || MessageDigest.isEqual(recipient.getProfileKey(), message.getProfileKey().get())) {
|
||||
database.setProfileKey(recipient, message.getProfileKey().get());
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new RetrieveProfileJob(context, recipient));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Optional<InsertResult> insertPlaceholder(@NonNull SignalServiceEnvelope envelope) {
|
||||
|
@ -114,7 +114,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
||||
MediaConstraints mediaConstraints = MediaConstraints.getPushMediaConstraints();
|
||||
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
|
||||
List<SignalServiceAttachment> attachmentStreams = getAttachmentsFor(masterSecret, scaledAttachments);
|
||||
Optional<byte[]> profileKey = getProfileKey(message.getRecipient().getAddress());
|
||||
Optional<byte[]> profileKey = getProfileKey(message.getRecipient());
|
||||
SignalServiceDataMessage mediaMessage = SignalServiceDataMessage.newBuilder()
|
||||
.withBody(message.getBody())
|
||||
.withAttachments(attachmentStreams)
|
||||
|
@ -1,12 +1,14 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
@ -27,11 +29,11 @@ public abstract class PushReceivedJob extends ContextJob {
|
||||
}
|
||||
|
||||
public void handle(SignalServiceEnvelope envelope, boolean sendExplicitReceipt) {
|
||||
Address source = Address.fromExternal(context, envelope.getSource());
|
||||
Address source = Address.fromExternal(context, envelope.getSource());
|
||||
Recipient recipient = Recipient.from(context, source, false);
|
||||
|
||||
if (!isActiveNumber(context, source)) {
|
||||
DatabaseFactory.getRecipientDatabase(context).setRegistered(Util.asList(source), new LinkedList<>());
|
||||
Recipient recipient = Recipient.from(context, source, false);
|
||||
if (!isActiveNumber(recipient)) {
|
||||
DatabaseFactory.getRecipientDatabase(context).setRegistered(recipient, RecipientDatabase.RegisteredState.REGISTERED);
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(context, KeyCachingService.getMasterSecret(context), recipient));
|
||||
}
|
||||
|
||||
@ -68,9 +70,8 @@ public abstract class PushReceivedJob extends ContextJob {
|
||||
envelope.getTimestamp()));
|
||||
}
|
||||
|
||||
private boolean isActiveNumber(Context context, Address address) {
|
||||
Optional<RecipientSettings> settings = DatabaseFactory.getRecipientDatabase(context).getRecipientSettings(address);
|
||||
return settings.isPresent() && settings.get().isRegistered();
|
||||
private boolean isActiveNumber(@NonNull Recipient recipient) {
|
||||
return recipient.resolve().getRegistered() == RecipientDatabase.RegisteredState.REGISTERED;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
@ -64,17 +65,11 @@ public abstract class PushSendJob extends SendJob {
|
||||
onPushSend(masterSecret);
|
||||
}
|
||||
|
||||
protected Optional<byte[]> getProfileKey(Address address) {
|
||||
protected Optional<byte[]> getProfileKey(@NonNull Recipient recipient) {
|
||||
try {
|
||||
Optional<RecipientSettings> recipientsPreferences = DatabaseFactory.getRecipientDatabase(context)
|
||||
.getRecipientSettings(address);
|
||||
|
||||
if (!recipientsPreferences.isPresent()) return Optional.absent();
|
||||
|
||||
boolean isSystemContact = !TextUtils.isEmpty(recipientsPreferences.get().getSystemDisplayName());
|
||||
boolean isApproved = recipientsPreferences.get().isProfileSharing();
|
||||
|
||||
if (!isSystemContact & !isApproved) return Optional.absent();
|
||||
if (!recipient.resolve().isSystemContact() && !recipient.resolve().isProfileSharing()) {
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
String profileKey = TextSecurePreferences.getProfileKey(context);
|
||||
|
||||
|
@ -102,7 +102,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
||||
try {
|
||||
SignalServiceAddress address = getPushAddress(message.getIndividualRecipient().getAddress());
|
||||
SignalServiceMessageSender messageSender = messageSenderFactory.create();
|
||||
Optional<byte[]> profileKey = getProfileKey(message.getIndividualRecipient().getAddress());
|
||||
Optional<byte[]> profileKey = getProfileKey(message.getIndividualRecipient());
|
||||
SignalServiceDataMessage textSecureMessage = SignalServiceDataMessage.newBuilder()
|
||||
.withTimestamp(message.getDateSent())
|
||||
.withBody(message.getBody().getBody())
|
||||
|
@ -5,16 +5,16 @@ import android.content.Context;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhotoFactory;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.profiles.AvatarHelper;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageReceiver;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
|
||||
@ -51,20 +51,15 @@ public class RetrieveProfileAvatarJob extends ContextJob implements InjectableTy
|
||||
|
||||
@Override
|
||||
public void onRun() throws IOException {
|
||||
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
|
||||
Optional<RecipientSettings> recipientSettings = database.getRecipientSettings(recipient.getAddress());
|
||||
RecipientDatabase database = DatabaseFactory.getRecipientDatabase(context);
|
||||
byte[] profileKey = recipient.resolve().getProfileKey();
|
||||
|
||||
if (!recipientSettings.isPresent()) {
|
||||
Log.w(TAG, "Recipient preference row is gone!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (recipientSettings.get().getProfileKey() == null) {
|
||||
if (profileKey == null) {
|
||||
Log.w(TAG, "Recipient profile key is gone!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (Util.equals(profileAvatar, recipientSettings.get().getProfileAvatar())) {
|
||||
if (Util.equals(profileAvatar, recipient.resolve().getProfileAvatar())) {
|
||||
Log.w(TAG, "Already retrieved profile avatar: " + profileAvatar);
|
||||
return;
|
||||
}
|
||||
@ -72,13 +67,14 @@ public class RetrieveProfileAvatarJob extends ContextJob implements InjectableTy
|
||||
if (TextUtils.isEmpty(profileAvatar)) {
|
||||
Log.w(TAG, "Removing profile avatar for: " + recipient.getAddress().serialize());
|
||||
AvatarHelper.delete(context, recipient.getAddress());
|
||||
database.setProfileAvatar(recipient, profileAvatar);
|
||||
return;
|
||||
}
|
||||
|
||||
File downloadDestination = File.createTempFile("avatar", "jpg", context.getCacheDir());
|
||||
|
||||
try {
|
||||
InputStream avatarStream = receiver.retrieveProfileAvatar(profileAvatar, downloadDestination, recipientSettings.get().getProfileKey(), MAX_PROFILE_SIZE_BYTES);
|
||||
InputStream avatarStream = receiver.retrieveProfileAvatar(profileAvatar, downloadDestination, profileKey, MAX_PROFILE_SIZE_BYTES);
|
||||
File decryptDestination = File.createTempFile("avatar", "jpg", context.getCacheDir());
|
||||
|
||||
Util.copy(avatarStream, new FileOutputStream(decryptDestination));
|
||||
@ -87,8 +83,11 @@ public class RetrieveProfileAvatarJob extends ContextJob implements InjectableTy
|
||||
if (downloadDestination != null) downloadDestination.delete();
|
||||
}
|
||||
|
||||
database.setProfileAvatar(recipient.getAddress(), profileAvatar);
|
||||
Recipient.clearCache(context);
|
||||
database.setProfileAvatar(recipient, profileAvatar);
|
||||
|
||||
if (recipient.resolve().getContactPhoto().isGenerated()) {
|
||||
recipient.setContactPhoto(ContactPhotoFactory.getSignalAvatarContactPhoto(context, recipient.getAddress(), recipient.getName(), context.getResources().getDimensionPixelSize(R.dimen.contact_photo_target_size)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -71,13 +71,12 @@ public class RetrieveProfileJob extends ContextJob implements InjectableType {
|
||||
private void handleIndividualRecipient(Recipient recipient)
|
||||
throws IOException, InvalidKeyException, InvalidNumberException
|
||||
{
|
||||
String number = recipient.getAddress().toPhoneString();
|
||||
SignalServiceProfile profile = retrieveProfile(number);
|
||||
Optional<RecipientSettings> recipientSettings = DatabaseFactory.getRecipientDatabase(context).getRecipientSettings(recipient.getAddress());
|
||||
String number = recipient.getAddress().toPhoneString();
|
||||
SignalServiceProfile profile = retrieveProfile(number);
|
||||
|
||||
setIdentityKey(recipient, profile.getIdentityKey());
|
||||
setProfileName(recipient, recipientSettings, profile.getName());
|
||||
setProfileAvatar(recipient, recipientSettings, profile.getAvatar());
|
||||
setProfileName(recipient, profile.getName());
|
||||
setProfileAvatar(recipient, profile.getAvatar());
|
||||
}
|
||||
|
||||
private void handleGroupRecipient(Recipient group)
|
||||
@ -127,32 +126,30 @@ public class RetrieveProfileJob extends ContextJob implements InjectableType {
|
||||
}
|
||||
}
|
||||
|
||||
private void setProfileName(Recipient recipient, Optional<RecipientSettings> recipientPreferences, String profileName) {
|
||||
private void setProfileName(Recipient recipient, String profileName) {
|
||||
try {
|
||||
if (!recipientPreferences.isPresent()) return;
|
||||
if (recipientPreferences.get().getProfileKey() == null) return;
|
||||
byte[] profileKey = recipient.getProfileKey();
|
||||
if (profileKey == null) return;
|
||||
|
||||
String plaintextProfileName = null;
|
||||
|
||||
if (profileName != null) {
|
||||
ProfileCipher profileCipher = new ProfileCipher(recipientPreferences.get().getProfileKey());
|
||||
ProfileCipher profileCipher = new ProfileCipher(profileKey);
|
||||
plaintextProfileName = new String(profileCipher.decryptName(Base64.decode(profileName)));
|
||||
}
|
||||
|
||||
if (!Util.equals(plaintextProfileName, recipientPreferences.get().getProfileName())) {
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileName(recipient.getAddress(), plaintextProfileName);
|
||||
Recipient.clearCache(context);
|
||||
if (!Util.equals(plaintextProfileName, recipient.getProfileName())) {
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileName(recipient, plaintextProfileName);
|
||||
}
|
||||
} catch (ProfileCipher.InvalidCiphertextException | IOException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setProfileAvatar(Recipient recipient, Optional<RecipientSettings> recipientPreferences, String profileAvatar) {
|
||||
if (!recipientPreferences.isPresent()) return;
|
||||
if (recipientPreferences.get().getProfileKey() == null) return;
|
||||
private void setProfileAvatar(Recipient recipient, String profileAvatar) {
|
||||
if (recipient.getProfileKey() == null) return;
|
||||
|
||||
if (!Util.equals(profileAvatar, recipientPreferences.get().getProfileAvatar())) {
|
||||
if (!Util.equals(profileAvatar, recipient.getProfileAvatar())) {
|
||||
ApplicationContext.getInstance(context)
|
||||
.getJobManager()
|
||||
.add(new RetrieveProfileAvatarJob(context, recipient, profileAvatar));
|
||||
|
@ -73,9 +73,8 @@ public class AndroidAutoReplyReceiver extends MasterSecretBroadcastReceiver {
|
||||
|
||||
long replyThreadId;
|
||||
|
||||
Optional<RecipientSettings> settings = DatabaseFactory.getRecipientDatabase(context).getRecipientSettings(address);
|
||||
int subscriptionId = settings.isPresent() ? settings.get().getDefaultSubscriptionId().or(-1) : -1;
|
||||
long expiresIn = settings.isPresent() ? settings.get().getExpireMessages() * 1000 : 0;
|
||||
int subscriptionId = recipient.getDefaultSubscriptionId().or(-1);
|
||||
long expiresIn = recipient.getExpireMessages() * 1000;
|
||||
|
||||
if (recipient.isGroupRecipient()) {
|
||||
Log.w("AndroidAutoReplyReceiver", "GroupRecipient, Sending media message");
|
||||
|
@ -67,10 +67,9 @@ public class RemoteReplyReceiver extends MasterSecretBroadcastReceiver {
|
||||
protected Void doInBackground(Void... params) {
|
||||
long threadId;
|
||||
|
||||
Optional<RecipientSettings> settings = DatabaseFactory.getRecipientDatabase(context).getRecipientSettings(address);
|
||||
int subscriptionId = settings.isPresent() ? settings.get().getDefaultSubscriptionId().or(-1) : -1;
|
||||
long expiresIn = settings.isPresent() ? settings.get().getExpireMessages() * 1000 : 0;
|
||||
Recipient recipient = Recipient.from(context, address, false);
|
||||
int subscriptionId = recipient.getDefaultSubscriptionId().or(-1);
|
||||
long expiresIn = recipient.getExpireMessages() * 1000;
|
||||
|
||||
if (recipient.isGroupRecipient()) {
|
||||
OutgoingMediaMessage reply = new OutgoingMediaMessage(recipient, responseText.toString(), new LinkedList<Attachment>(), System.currentTimeMillis(), subscriptionId, expiresIn, 0);
|
||||
|
@ -52,11 +52,6 @@ public class UnknownSenderView extends FrameLayout {
|
||||
if (threadId != -1) DatabaseFactory.getThreadDatabase(context).setHasSent(threadId, true);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Void result) {
|
||||
recipient.setBlocked(true);
|
||||
}
|
||||
}.execute();
|
||||
})
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
@ -94,7 +89,7 @@ public class UnknownSenderView extends FrameLayout {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient.getAddress(), true);
|
||||
DatabaseFactory.getRecipientDatabase(context).setProfileSharing(recipient, true);
|
||||
if (threadId != -1) DatabaseFactory.getThreadDatabase(context).setHasSent(threadId, true);
|
||||
return null;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import org.thoughtcrime.securesms.contacts.avatars.ContactPhotoFactory;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientProvider.RecipientDetails;
|
||||
import org.thoughtcrime.securesms.util.FutureTaskListener;
|
||||
@ -61,16 +62,24 @@ public class Recipient implements RecipientModifiedListener {
|
||||
private boolean stale;
|
||||
private boolean resolving;
|
||||
|
||||
private ContactPhoto contactPhoto;
|
||||
private Uri contactUri;
|
||||
private Uri ringtone = null;
|
||||
private long mutedUntil = 0;
|
||||
private boolean blocked = false;
|
||||
private VibrateState vibrate = VibrateState.DEFAULT;
|
||||
private int expireMessages = 0;
|
||||
private String profileName = null;
|
||||
private ContactPhoto contactPhoto;
|
||||
private Uri contactUri;
|
||||
private @Nullable Uri ringtone = null;
|
||||
private long mutedUntil = 0;
|
||||
private boolean blocked = false;
|
||||
private VibrateState vibrate = VibrateState.DEFAULT;
|
||||
private int expireMessages = 0;
|
||||
private Optional<Integer> defaultSubscriptionId = Optional.absent();
|
||||
private @NonNull RegisteredState registered = RegisteredState.UNKNOWN;
|
||||
|
||||
private @Nullable MaterialColor color;
|
||||
private boolean seenInviteReminder;
|
||||
private @Nullable byte[] profileKey;
|
||||
private @Nullable String profileName;
|
||||
private @Nullable String profileAvatar;
|
||||
private boolean profileSharing;
|
||||
private boolean isSystemContact;
|
||||
|
||||
@Nullable private MaterialColor color;
|
||||
|
||||
public static @NonNull Recipient from(@NonNull Context context, @NonNull Address address, boolean asynchronous) {
|
||||
if (address == null) throw new AssertionError(address);
|
||||
@ -98,31 +107,45 @@ public class Recipient implements RecipientModifiedListener {
|
||||
this.resolving = true;
|
||||
|
||||
if (stale != null) {
|
||||
this.name = stale.name;
|
||||
this.contactUri = stale.contactUri;
|
||||
this.contactPhoto = stale.contactPhoto;
|
||||
this.color = stale.color;
|
||||
this.customLabel = stale.customLabel;
|
||||
this.ringtone = stale.ringtone;
|
||||
this.mutedUntil = stale.mutedUntil;
|
||||
this.blocked = stale.blocked;
|
||||
this.vibrate = stale.vibrate;
|
||||
this.expireMessages = stale.expireMessages;
|
||||
this.profileName = stale.profileName;
|
||||
this.name = stale.name;
|
||||
this.contactUri = stale.contactUri;
|
||||
this.contactPhoto = stale.contactPhoto;
|
||||
this.color = stale.color;
|
||||
this.customLabel = stale.customLabel;
|
||||
this.ringtone = stale.ringtone;
|
||||
this.mutedUntil = stale.mutedUntil;
|
||||
this.blocked = stale.blocked;
|
||||
this.vibrate = stale.vibrate;
|
||||
this.expireMessages = stale.expireMessages;
|
||||
this.seenInviteReminder = stale.seenInviteReminder;
|
||||
this.defaultSubscriptionId = stale.defaultSubscriptionId;
|
||||
this.registered = stale.registered;
|
||||
this.profileKey = stale.profileKey;
|
||||
this.profileName = stale.profileName;
|
||||
this.profileAvatar = stale.profileAvatar;
|
||||
this.profileSharing = stale.profileSharing;
|
||||
this.isSystemContact = stale.isSystemContact;
|
||||
this.participants.clear();
|
||||
this.participants.addAll(stale.participants);
|
||||
}
|
||||
|
||||
if (details.isPresent()) {
|
||||
this.name = details.get().name;
|
||||
this.contactPhoto = details.get().avatar;
|
||||
this.color = details.get().color;
|
||||
this.ringtone = details.get().ringtone;
|
||||
this.mutedUntil = details.get().mutedUntil;
|
||||
this.blocked = details.get().blocked;
|
||||
this.vibrate = details.get().vibrateState;
|
||||
this.expireMessages = details.get().expireMessages;
|
||||
this.profileName = details.get().profileName;
|
||||
this.name = details.get().name;
|
||||
this.contactPhoto = details.get().avatar;
|
||||
this.color = details.get().color;
|
||||
this.ringtone = details.get().ringtone;
|
||||
this.mutedUntil = details.get().mutedUntil;
|
||||
this.blocked = details.get().blocked;
|
||||
this.vibrate = details.get().vibrateState;
|
||||
this.expireMessages = details.get().expireMessages;
|
||||
this.seenInviteReminder = details.get().seenInviteReminder;
|
||||
this.defaultSubscriptionId = details.get().defaultSubscriptionId;
|
||||
this.registered = details.get().registered;
|
||||
this.profileKey = details.get().profileKey;
|
||||
this.profileName = details.get().profileName;
|
||||
this.profileAvatar = details.get().profileAvatar;
|
||||
this.profileSharing = details.get().profileSharing;
|
||||
this.isSystemContact = details.get().systemContact;
|
||||
this.participants.clear();
|
||||
this.participants.addAll(details.get().participants);
|
||||
}
|
||||
@ -132,25 +155,35 @@ public class Recipient implements RecipientModifiedListener {
|
||||
public void onSuccess(RecipientDetails result) {
|
||||
if (result != null) {
|
||||
synchronized (Recipient.this) {
|
||||
Recipient.this.name = result.name;
|
||||
Recipient.this.contactUri = result.contactUri;
|
||||
Recipient.this.contactPhoto = result.avatar;
|
||||
Recipient.this.color = result.color;
|
||||
Recipient.this.customLabel = result.customLabel;
|
||||
Recipient.this.ringtone = result.ringtone;
|
||||
Recipient.this.mutedUntil = result.mutedUntil;
|
||||
Recipient.this.blocked = result.blocked;
|
||||
Recipient.this.vibrate = result.vibrateState;
|
||||
Recipient.this.expireMessages = result.expireMessages;
|
||||
Recipient.this.profileName = result.profileName;
|
||||
Recipient.this.name = result.name;
|
||||
Recipient.this.contactUri = result.contactUri;
|
||||
Recipient.this.contactPhoto = result.avatar;
|
||||
Recipient.this.color = result.color;
|
||||
Recipient.this.customLabel = result.customLabel;
|
||||
Recipient.this.ringtone = result.ringtone;
|
||||
Recipient.this.mutedUntil = result.mutedUntil;
|
||||
Recipient.this.blocked = result.blocked;
|
||||
Recipient.this.vibrate = result.vibrateState;
|
||||
Recipient.this.expireMessages = result.expireMessages;
|
||||
Recipient.this.seenInviteReminder = result.seenInviteReminder;
|
||||
Recipient.this.defaultSubscriptionId = result.defaultSubscriptionId;
|
||||
Recipient.this.registered = result.registered;
|
||||
Recipient.this.profileKey = result.profileKey;
|
||||
Recipient.this.profileName = result.profileName;
|
||||
Recipient.this.profileAvatar = result.profileAvatar;
|
||||
Recipient.this.profileSharing = result.profileSharing;
|
||||
Recipient.this.profileName = result.profileName;
|
||||
Recipient.this.isSystemContact = result.systemContact;
|
||||
|
||||
Recipient.this.participants.clear();
|
||||
Recipient.this.participants.addAll(result.participants);
|
||||
Recipient.this.resolving = false;
|
||||
Recipient.this.resolving = false;
|
||||
|
||||
if (!listeners.isEmpty()) {
|
||||
for (Recipient recipient : participants) recipient.addListener(Recipient.this);
|
||||
}
|
||||
|
||||
Recipient.this.notifyAll();
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
@ -165,18 +198,25 @@ public class Recipient implements RecipientModifiedListener {
|
||||
}
|
||||
|
||||
Recipient(@NonNull Address address, @NonNull RecipientDetails details) {
|
||||
this.address = address;
|
||||
this.contactUri = details.contactUri;
|
||||
this.name = details.name;
|
||||
this.contactPhoto = details.avatar;
|
||||
this.color = details.color;
|
||||
this.customLabel = details.customLabel;
|
||||
this.ringtone = details.ringtone;
|
||||
this.mutedUntil = details.mutedUntil;
|
||||
this.blocked = details.blocked;
|
||||
this.vibrate = details.vibrateState;
|
||||
this.expireMessages = details.expireMessages;
|
||||
this.profileName = details.profileName;
|
||||
this.address = address;
|
||||
this.contactUri = details.contactUri;
|
||||
this.name = details.name;
|
||||
this.contactPhoto = details.avatar;
|
||||
this.color = details.color;
|
||||
this.customLabel = details.customLabel;
|
||||
this.ringtone = details.ringtone;
|
||||
this.mutedUntil = details.mutedUntil;
|
||||
this.blocked = details.blocked;
|
||||
this.vibrate = details.vibrateState;
|
||||
this.expireMessages = details.expireMessages;
|
||||
this.seenInviteReminder = details.seenInviteReminder;
|
||||
this.defaultSubscriptionId = details.defaultSubscriptionId;
|
||||
this.registered = details.registered;
|
||||
this.profileKey = details.profileKey;
|
||||
this.profileName = details.profileName;
|
||||
this.profileAvatar = details.profileAvatar;
|
||||
this.profileSharing = details.profileSharing;
|
||||
this.isSystemContact = details.systemContact;
|
||||
this.participants.addAll(details.participants);
|
||||
this.resolving = false;
|
||||
}
|
||||
@ -222,10 +262,54 @@ public class Recipient implements RecipientModifiedListener {
|
||||
return customLabel;
|
||||
}
|
||||
|
||||
public @Nullable String getProfileName() {
|
||||
public synchronized Optional<Integer> getDefaultSubscriptionId() {
|
||||
return defaultSubscriptionId;
|
||||
}
|
||||
|
||||
public void setDefaultSubscriptionId(Optional<Integer> defaultSubscriptionId) {
|
||||
synchronized (this) {
|
||||
this.defaultSubscriptionId = defaultSubscriptionId;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized @Nullable String getProfileName() {
|
||||
return profileName;
|
||||
}
|
||||
|
||||
public void setProfileName(@Nullable String profileName) {
|
||||
synchronized (this) {
|
||||
this.profileName = profileName;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized @Nullable String getProfileAvatar() {
|
||||
return profileAvatar;
|
||||
}
|
||||
|
||||
public void setProfileAvatar(@Nullable String profileAvatar) {
|
||||
synchronized (this) {
|
||||
this.profileAvatar = profileAvatar;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized boolean isProfileSharing() {
|
||||
return profileSharing;
|
||||
}
|
||||
|
||||
public void setProfileSharing(boolean value) {
|
||||
synchronized (this) {
|
||||
this.profileSharing = value;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public boolean isGroupRecipient() {
|
||||
return address.isGroup();
|
||||
}
|
||||
@ -265,6 +349,14 @@ public class Recipient implements RecipientModifiedListener {
|
||||
return contactPhoto;
|
||||
}
|
||||
|
||||
public void setContactPhoto(@NonNull ContactPhoto contactPhoto) {
|
||||
synchronized (this) {
|
||||
this.contactPhoto = contactPhoto;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized @Nullable Uri getRingtone() {
|
||||
return ringtone;
|
||||
}
|
||||
@ -325,6 +417,60 @@ public class Recipient implements RecipientModifiedListener {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized boolean hasSeenInviteReminder() {
|
||||
return seenInviteReminder;
|
||||
}
|
||||
|
||||
public void setHasSeenInviteReminder(boolean value) {
|
||||
synchronized (this) {
|
||||
this.seenInviteReminder = value;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized RegisteredState getRegistered() {
|
||||
return registered;
|
||||
}
|
||||
|
||||
public void setRegistered(@NonNull RegisteredState value) {
|
||||
synchronized (this) {
|
||||
this.registered = value;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized @Nullable byte[] getProfileKey() {
|
||||
return profileKey;
|
||||
}
|
||||
|
||||
public void setProfileKey(@Nullable byte[] profileKey) {
|
||||
synchronized (this) {
|
||||
this.profileKey = profileKey;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized boolean isSystemContact() {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
@ -369,4 +515,5 @@ public class Recipient implements RecipientModifiedListener {
|
||||
return resolving;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -33,7 +33,9 @@ import org.thoughtcrime.securesms.contacts.avatars.ContactPhotoFactory;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RegisteredState;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
|
||||
import org.thoughtcrime.securesms.util.LRUCache;
|
||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
@ -187,38 +189,52 @@ class RecipientProvider {
|
||||
}
|
||||
|
||||
static class RecipientDetails {
|
||||
@Nullable public final String name;
|
||||
@Nullable public final String customLabel;
|
||||
@NonNull public final ContactPhoto avatar;
|
||||
@Nullable public final Uri contactUri;
|
||||
@Nullable public final MaterialColor color;
|
||||
@Nullable public final Uri ringtone;
|
||||
public final long mutedUntil;
|
||||
@Nullable public final VibrateState vibrateState;
|
||||
public final boolean blocked;
|
||||
public final int expireMessages;
|
||||
@NonNull public final List<Recipient> participants;
|
||||
@Nullable public final String profileName;
|
||||
@Nullable public final String name;
|
||||
@Nullable public final String customLabel;
|
||||
@NonNull public final ContactPhoto avatar;
|
||||
@Nullable public final Uri contactUri;
|
||||
@Nullable public final MaterialColor color;
|
||||
@Nullable public final Uri ringtone;
|
||||
public final long mutedUntil;
|
||||
@Nullable public final VibrateState vibrateState;
|
||||
public final boolean blocked;
|
||||
public final int expireMessages;
|
||||
@NonNull public final List<Recipient> participants;
|
||||
@Nullable public final String profileName;
|
||||
public final boolean seenInviteReminder;
|
||||
public final Optional<Integer> defaultSubscriptionId;
|
||||
@NonNull public final RegisteredState registered;
|
||||
@Nullable public final byte[] profileKey;
|
||||
@Nullable public final String profileAvatar;
|
||||
public final boolean profileSharing;
|
||||
public final boolean systemContact;
|
||||
|
||||
public RecipientDetails(@Nullable String name, @Nullable String customLabel,
|
||||
@Nullable Uri contactUri, @NonNull ContactPhoto avatar,
|
||||
@Nullable RecipientSettings settings,
|
||||
@Nullable List<Recipient> participants)
|
||||
{
|
||||
this.customLabel = customLabel;
|
||||
this.avatar = avatar;
|
||||
this.contactUri = contactUri;
|
||||
this.color = settings != null ? settings.getColor() : null;
|
||||
this.ringtone = settings != null ? settings.getRingtone() : null;
|
||||
this.mutedUntil = settings != null ? settings.getMuteUntil() : 0;
|
||||
this.vibrateState = settings != null ? settings.getVibrateState() : null;
|
||||
this.blocked = settings != null && settings.isBlocked();
|
||||
this.expireMessages = settings != null ? settings.getExpireMessages() : 0;
|
||||
this.participants = participants == null ? new LinkedList<Recipient>() : participants;
|
||||
this.profileName = settings != null ? settings.getProfileName() : null;
|
||||
this.customLabel = customLabel;
|
||||
this.avatar = avatar;
|
||||
this.contactUri = contactUri;
|
||||
this.color = settings != null ? settings.getColor() : null;
|
||||
this.ringtone = settings != null ? settings.getRingtone() : null;
|
||||
this.mutedUntil = settings != null ? settings.getMuteUntil() : 0;
|
||||
this.vibrateState = settings != null ? settings.getVibrateState() : null;
|
||||
this.blocked = settings != null && settings.isBlocked();
|
||||
this.expireMessages = settings != null ? settings.getExpireMessages() : 0;
|
||||
this.participants = participants == null ? new LinkedList<Recipient>() : participants;
|
||||
this.profileName = settings != null ? settings.getProfileName() : null;
|
||||
this.seenInviteReminder = settings != null && settings.hasSeenInviteReminder();
|
||||
this.defaultSubscriptionId = settings != null ? settings.getDefaultSubscriptionId() : Optional.absent();
|
||||
this.registered = settings != null ? settings.getRegistered() : RegisteredState.UNKNOWN;
|
||||
this.profileKey = settings != null ? settings.getProfileKey() : null;
|
||||
this.profileAvatar = settings != null ? settings.getProfileAvatar() : null;
|
||||
this.profileSharing = settings != null && settings.isProfileSharing();
|
||||
this.systemContact = settings != null && !TextUtils.isEmpty(settings.getSystemDisplayName());
|
||||
|
||||
if (name == null && settings != null) this.name = settings.getSystemDisplayName();
|
||||
else this.name = name;
|
||||
else this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,11 +51,10 @@ public class QuickResponseService extends MasterSecretIntentService {
|
||||
number = URLDecoder.decode(number);
|
||||
}
|
||||
|
||||
Address address = Address.fromExternal(this, number);
|
||||
Recipient recipient = Recipient.from(this, address, false);
|
||||
Optional<RecipientSettings> settings = DatabaseFactory.getRecipientDatabase(this).getRecipientSettings(recipient.getAddress());
|
||||
int subscriptionId = settings.isPresent() ? settings.get().getDefaultSubscriptionId().or(-1) : -1;
|
||||
long expiresIn = settings.isPresent() ? settings.get().getExpireMessages() * 1000 : 0;
|
||||
Address address = Address.fromExternal(this, number);
|
||||
Recipient recipient = Recipient.from(this, address, false);
|
||||
int subscriptionId = recipient.getDefaultSubscriptionId().or(-1);
|
||||
long expiresIn = recipient.getExpireMessages() * 1000;
|
||||
|
||||
if (!TextUtils.isEmpty(content)) {
|
||||
MessageSender.send(this, masterSecret, new OutgoingTextMessage(recipient, content, expiresIn, subscriptionId), -1, false, null);
|
||||
|
@ -28,7 +28,6 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase;
|
||||
import org.thoughtcrime.securesms.database.RecipientDatabase.RecipientSettings;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
@ -50,7 +49,6 @@ import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class MessageSender {
|
||||
|
||||
@ -232,7 +230,7 @@ public class MessageSender {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isPushDestination(context, recipient.getAddress());
|
||||
return isPushDestination(context, recipient);
|
||||
}
|
||||
|
||||
private static boolean isPushMediaSend(Context context, Recipient recipient) {
|
||||
@ -244,7 +242,7 @@ public class MessageSender {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isPushDestination(context, recipient.getAddress());
|
||||
return isPushDestination(context, recipient);
|
||||
}
|
||||
|
||||
private static boolean isGroupPushSend(Recipient recipient) {
|
||||
@ -264,22 +262,21 @@ public class MessageSender {
|
||||
return Util.isOwnNumber(context, recipient.getAddress());
|
||||
}
|
||||
|
||||
private static boolean isPushDestination(Context context, Address destination) {
|
||||
RecipientDatabase recipientsDatabase = DatabaseFactory.getRecipientDatabase(context);
|
||||
Optional<RecipientSettings> recipientPreferences = recipientsDatabase.getRecipientSettings(destination);
|
||||
|
||||
if (recipientPreferences.isPresent()) {
|
||||
return recipientPreferences.get().isRegistered();
|
||||
private static boolean isPushDestination(Context context, Recipient destination) {
|
||||
if (destination.resolve().getRegistered() == RecipientDatabase.RegisteredState.REGISTERED) {
|
||||
return true;
|
||||
} else if (destination.resolve().getRegistered() == RecipientDatabase.RegisteredState.NOT_REGISTERED) {
|
||||
return false;
|
||||
} else {
|
||||
try {
|
||||
SignalServiceAccountManager accountManager = AccountManagerFactory.createManager(context);
|
||||
Optional<ContactTokenDetails> registeredUser = accountManager.getContact(destination.serialize());
|
||||
Optional<ContactTokenDetails> registeredUser = accountManager.getContact(destination.getAddress().serialize());
|
||||
|
||||
if (!registeredUser.isPresent()) {
|
||||
recipientsDatabase.setRegistered(new LinkedList<>(), Util.asList(destination));
|
||||
DatabaseFactory.getRecipientDatabase(context).setRegistered(destination, RecipientDatabase.RegisteredState.NOT_REGISTERED);
|
||||
return false;
|
||||
} else {
|
||||
recipientsDatabase.setRegistered(Util.asList(destination), new LinkedList<>());
|
||||
DatabaseFactory.getRecipientDatabase(context).setRegistered(destination, RecipientDatabase.RegisteredState.REGISTERED);
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e1) {
|
||||
|
@ -26,6 +26,7 @@ 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;
|
||||
import org.thoughtcrime.securesms.push.AccountManagerFactory;
|
||||
@ -44,10 +45,6 @@ import java.util.Set;
|
||||
|
||||
public class DirectoryHelper {
|
||||
|
||||
public enum Capability {
|
||||
UNKNOWN, SUPPORTED, UNSUPPORTED
|
||||
}
|
||||
|
||||
private static final String TAG = DirectoryHelper.class.getSimpleName();
|
||||
|
||||
public static void refreshDirectory(@NonNull Context context, @Nullable MasterSecret masterSecret)
|
||||
@ -75,33 +72,38 @@ public class DirectoryHelper {
|
||||
return new RefreshResult(new LinkedList<>(), false);
|
||||
}
|
||||
|
||||
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
|
||||
Set<Address> eligibleContactNumbers = recipientDatabase.getAllRecipients();
|
||||
eligibleContactNumbers.addAll(ContactAccessor.getInstance().getAllContactsWithNumbers(context));
|
||||
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
|
||||
Stream<String> eligibleRecipientDatabaseContactNumbers = Stream.of(recipientDatabase.getAllRecipients()).map(recipient -> recipient.getAddress().serialize());
|
||||
Stream<String> eligibleSystemDatabaseContactNumbers = Stream.of(ContactAccessor.getInstance().getAllContactsWithNumbers(context)).map(Address::serialize);
|
||||
Set<String> eligibleContactNumbers = Stream.concat(eligibleRecipientDatabaseContactNumbers, eligibleSystemDatabaseContactNumbers).collect(Collectors.toSet());
|
||||
|
||||
Set<String> serializedAddress = Stream.of(eligibleContactNumbers).map(Address::serialize).collect(Collectors.toSet());
|
||||
List<ContactTokenDetails> activeTokens = accountManager.getContacts(serializedAddress);
|
||||
List<ContactTokenDetails> activeTokens = accountManager.getContacts(eligibleContactNumbers);
|
||||
|
||||
if (activeTokens != null) {
|
||||
List<Address> activeAddresses = new LinkedList<>();
|
||||
Set<Address> inactiveAddresses = new HashSet<>(eligibleContactNumbers);
|
||||
List<Recipient> activeRecipients = new LinkedList<>();
|
||||
List<Recipient> inactiveRecipients = new LinkedList<>();
|
||||
|
||||
Set<String> inactiveContactNumbers = new HashSet<>(eligibleContactNumbers);
|
||||
|
||||
for (ContactTokenDetails activeToken : activeTokens) {
|
||||
Address activeAddress = Address.fromSerialized(activeToken.getNumber());
|
||||
activeAddresses.add(activeAddress);
|
||||
inactiveAddresses.remove(activeAddress);
|
||||
activeRecipients.add(Recipient.from(context, Address.fromSerialized(activeToken.getNumber()), true));
|
||||
inactiveContactNumbers.remove(activeToken.getNumber());
|
||||
}
|
||||
|
||||
recipientDatabase.setRegistered(activeAddresses, new LinkedList<>(inactiveAddresses));
|
||||
return updateContactsDatabase(context, activeAddresses, true);
|
||||
for (String inactiveContactNumber : inactiveContactNumbers) {
|
||||
inactiveRecipients.add(Recipient.from(context, Address.fromSerialized(inactiveContactNumber), true));
|
||||
}
|
||||
|
||||
recipientDatabase.setRegistered(activeRecipients, inactiveRecipients);
|
||||
return updateContactsDatabase(context, Stream.of(activeRecipients).map(Recipient::getAddress).toList(), true);
|
||||
}
|
||||
|
||||
return new RefreshResult(new LinkedList<>(), false);
|
||||
}
|
||||
|
||||
public static Capability refreshDirectoryFor(@NonNull Context context,
|
||||
@Nullable MasterSecret masterSecret,
|
||||
@NonNull Recipient recipient)
|
||||
public static RegisteredState refreshDirectoryFor(@NonNull Context context,
|
||||
@Nullable MasterSecret masterSecret,
|
||||
@NonNull Recipient recipient)
|
||||
throws IOException
|
||||
{
|
||||
RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
|
||||
@ -110,7 +112,7 @@ public class DirectoryHelper {
|
||||
Optional<ContactTokenDetails> details = accountManager.getContact(number);
|
||||
|
||||
if (details.isPresent()) {
|
||||
recipientDatabase.setRegistered(Util.asList(recipient.getAddress()), new LinkedList<>());
|
||||
recipientDatabase.setRegistered(recipient, RegisteredState.REGISTERED);
|
||||
|
||||
RefreshResult result = updateContactsDatabase(context, Util.asList(recipient.getAddress()), false);
|
||||
|
||||
@ -122,38 +124,13 @@ public class DirectoryHelper {
|
||||
notifyNewUsers(context, masterSecret, result.getNewUsers());
|
||||
}
|
||||
|
||||
return Capability.SUPPORTED;
|
||||
return RegisteredState.REGISTERED;
|
||||
} else {
|
||||
recipientDatabase.setRegistered(new LinkedList<>(), Util.asList(recipient.getAddress()));
|
||||
return Capability.UNSUPPORTED;
|
||||
recipientDatabase.setRegistered(recipient, RegisteredState.NOT_REGISTERED);
|
||||
return RegisteredState.NOT_REGISTERED;
|
||||
}
|
||||
}
|
||||
|
||||
public static @NonNull Capability getUserCapabilities(@NonNull Context context, @Nullable Recipient recipient) {
|
||||
if (recipient == null) {
|
||||
return Capability.UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (!TextSecurePreferences.isPushRegistered(context)) {
|
||||
return Capability.UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (recipient.isMmsGroupRecipient()) {
|
||||
return Capability.UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (recipient.isPushGroupRecipient()) {
|
||||
return Capability.SUPPORTED;
|
||||
}
|
||||
|
||||
final RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context);
|
||||
final Optional<RecipientSettings> recipientSettings = recipientDatabase.getRecipientSettings(recipient.getAddress());
|
||||
|
||||
if (recipientSettings.isPresent() && recipientSettings.get().isRegistered()) return Capability.SUPPORTED;
|
||||
else if (recipientSettings.isPresent()) return Capability.UNSUPPORTED;
|
||||
else return Capability.UNKNOWN;
|
||||
}
|
||||
|
||||
private static @NonNull RefreshResult updateContactsDatabase(@NonNull Context context, @NonNull List<Address> activeAddresses, boolean removeMissing) {
|
||||
Optional<AccountHolder> account = getOrCreateAccount(context);
|
||||
|
||||
@ -162,7 +139,7 @@ public class DirectoryHelper {
|
||||
List<Address> newUsers = DatabaseFactory.getContactsDatabase(context)
|
||||
.setRegisteredUsers(account.get().getAccount(), activeAddresses, removeMissing);
|
||||
|
||||
Cursor cursor = ContactAccessor.getInstance().getAllSystemContacts(context);
|
||||
Cursor cursor = ContactAccessor.getInstance().getAllSystemContacts(context);
|
||||
RecipientDatabase.BulkOperationsHandle handle = DatabaseFactory.getRecipientDatabase(context).resetAllDisplayNames();
|
||||
|
||||
try {
|
||||
@ -170,10 +147,11 @@ public class DirectoryHelper {
|
||||
String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER));
|
||||
|
||||
if (!TextUtils.isEmpty(number)) {
|
||||
Address address = Address.fromExternal(context, number);
|
||||
String displayName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
|
||||
Address address = Address.fromExternal(context, number);
|
||||
Recipient recipient = Recipient.from(context, address, true);
|
||||
String displayName = cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
|
||||
|
||||
handle.setDisplayName(address, displayName);
|
||||
handle.setDisplayName(recipient, displayName);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
|
Loading…
x
Reference in New Issue
Block a user