mirror of
https://github.com/oxen-io/session-android.git
synced 2025-03-13 21:30:56 +00:00
Switch MMS groups to use the group database infrastructure
Eliminate the concept of 'Recipients' (plural). There is now just a 'Recipient', which contains an Address that is either an individual or a group ID. MMS groups now exist as part of the group database, just like push groups. // FREEBIE
This commit is contained in:
parent
81682e0302
commit
375207f073
@ -4,7 +4,7 @@ import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
@ -14,7 +14,7 @@ public interface BindableConversationItem extends Unbindable {
|
||||
@NonNull MessageRecord messageRecord,
|
||||
@NonNull Locale locale,
|
||||
@NonNull Set<MessageRecord> batchSelected,
|
||||
@NonNull Recipients recipients);
|
||||
@NonNull Recipient recipients);
|
||||
|
||||
MessageRecord getMessageRecord();
|
||||
}
|
||||
|
@ -20,13 +20,11 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.loaders.BlockedContactsLoader;
|
||||
import org.thoughtcrime.securesms.preferences.BlockedContactListItem;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity {
|
||||
|
||||
private final DynamicTheme dynamicTheme = new DynamicTheme();
|
||||
@ -106,9 +104,9 @@ public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
Recipients recipients = ((BlockedContactListItem)view).getRecipients();
|
||||
Intent intent = new Intent(getActivity(), RecipientPreferenceActivity.class);
|
||||
intent.putExtra(RecipientPreferenceActivity.ADDRESSES_EXTRA, recipients.getAddresses());
|
||||
Recipient recipient = ((BlockedContactListItem)view).getRecipient();
|
||||
Intent intent = new Intent(getActivity(), RecipientPreferenceActivity.class);
|
||||
intent.putExtra(RecipientPreferenceActivity.ADDRESS_EXTRA, recipient.getAddress());
|
||||
|
||||
startActivity(intent);
|
||||
}
|
||||
@ -127,12 +125,10 @@ public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
String addressesConcat = cursor.getString(1);
|
||||
List<Address> addresses = Address.fromSerializedList(addressesConcat, ' ');
|
||||
String address = cursor.getString(1);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, Address.fromSerialized(address), true);
|
||||
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, addresses.toArray(new Address[0]), true);
|
||||
|
||||
((BlockedContactListItem) view).set(recipients);
|
||||
((BlockedContactListItem) view).set(recipient);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,6 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.crypto.storage.TextSecureIdentityKeyStore;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MmsAddressDatabase;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.PushDatabase;
|
||||
@ -24,7 +23,6 @@ import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.jobs.PushDecryptJob;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.thoughtcrime.securesms.util.VerifySpan;
|
||||
@ -138,17 +136,17 @@ public class ConfirmIdentityDialog extends AlertDialog {
|
||||
private void processOutgoingMessageRecord(MessageRecord messageRecord) {
|
||||
SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(getContext());
|
||||
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(getContext());
|
||||
MmsAddressDatabase mmsAddressDatabase = DatabaseFactory.getMmsAddressDatabase(getContext());
|
||||
|
||||
if (messageRecord.isMms()) {
|
||||
mmsDatabase.removeMismatchedIdentity(messageRecord.getId(),
|
||||
mismatch.getAddress(),
|
||||
mismatch.getIdentityKey());
|
||||
|
||||
Recipients recipients = mmsAddressDatabase.getRecipientsForId(messageRecord.getId());
|
||||
|
||||
if (recipients.isGroupRecipient()) MessageSender.resendGroupMessage(getContext(), masterSecret, messageRecord, mismatch.getAddress());
|
||||
else MessageSender.resend(getContext(), masterSecret, messageRecord);
|
||||
if (messageRecord.getRecipient().isPushGroupRecipient()) {
|
||||
MessageSender.resendGroupMessage(getContext(), messageRecord, mismatch.getAddress());
|
||||
} else {
|
||||
MessageSender.resend(getContext(), masterSecret, messageRecord);
|
||||
}
|
||||
} else {
|
||||
smsDatabase.removeMismatchedIdentity(messageRecord.getId(),
|
||||
mismatch.getAddress(),
|
||||
|
@ -132,8 +132,7 @@ import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients.RecipientsModifiedListener;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.service.WebRtcCallService;
|
||||
@ -165,7 +164,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
@ -184,7 +183,7 @@ import static org.whispersystems.signalservice.internal.push.SignalServiceProtos
|
||||
public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
implements ConversationFragment.ConversationFragmentListener,
|
||||
AttachmentManager.AttachmentListener,
|
||||
RecipientsModifiedListener,
|
||||
RecipientModifiedListener,
|
||||
OnKeyboardShownListener,
|
||||
AttachmentDrawerListener,
|
||||
InputPanel.Listener,
|
||||
@ -192,7 +191,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
{
|
||||
private static final String TAG = ConversationActivity.class.getSimpleName();
|
||||
|
||||
public static final String ADDRESSES_EXTRA = "addresses";
|
||||
public static final String ADDRESS_EXTRA = "address";
|
||||
public static final String THREAD_ID_EXTRA = "thread_id";
|
||||
public static final String IS_ARCHIVED_EXTRA = "is_archived";
|
||||
public static final String TEXT_EXTRA = "draft_text";
|
||||
@ -236,7 +235,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private QuickAttachmentDrawer quickAttachmentDrawer;
|
||||
private InputPanel inputPanel;
|
||||
|
||||
private Recipients recipients;
|
||||
private Recipient recipient;
|
||||
private long threadId;
|
||||
private int distributionType;
|
||||
private boolean archived;
|
||||
@ -325,9 +324,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
initializeIdentityRecords();
|
||||
composeText.setTransport(sendButton.getSelectedTransport());
|
||||
|
||||
titleView.setTitle(recipients);
|
||||
setActionBarColor(recipients.getColor());
|
||||
setBlockedUserState(recipients, isSecureText, isDefaultSms);
|
||||
titleView.setTitle(recipient);
|
||||
setActionBarColor(recipient.getColor());
|
||||
setBlockedUserState(recipient, isSecureText, isDefaultSms);
|
||||
calculateCharactersRemaining();
|
||||
|
||||
MessageNotifier.setVisibleThread(threadId);
|
||||
@ -371,7 +370,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
saveDraft();
|
||||
if (recipients != null) recipients.removeListener(this);
|
||||
if (recipient != null) recipient.removeListener(this);
|
||||
if (securityUpdateReceiver != null) unregisterReceiver(securityUpdateReceiver);
|
||||
if (recipientsStaleReceiver != null) unregisterReceiver(recipientsStaleReceiver);
|
||||
super.onDestroy();
|
||||
@ -410,10 +409,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
addAttachmentContactInfo(data.getData());
|
||||
break;
|
||||
case GROUP_EDIT:
|
||||
recipients = RecipientFactory.getRecipientsFor(this, RecipientFactory.getRecipientFor(this, (Address)data.getParcelableExtra(GroupCreateActivity.GROUP_ADDRESS_EXTRA), true), true);
|
||||
recipients.addListener(this);
|
||||
titleView.setTitle(recipients);
|
||||
setBlockedUserState(recipients, isSecureText, isDefaultSms);
|
||||
recipient = RecipientFactory.getRecipientFor(this, (Address)data.getParcelableExtra(GroupCreateActivity.GROUP_ADDRESS_EXTRA), true);
|
||||
recipient.addListener(this);
|
||||
titleView.setTitle(recipient);
|
||||
setBlockedUserState(recipient, isSecureText, isDefaultSms);
|
||||
supportInvalidateOptionsMenu();
|
||||
break;
|
||||
case TAKE_PHOTO:
|
||||
@ -422,8 +421,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
break;
|
||||
case ADD_CONTACT:
|
||||
recipients = RecipientFactory.getRecipientsFor(this, recipients.getAddresses(), true);
|
||||
recipients.addListener(this);
|
||||
recipient = RecipientFactory.getRecipientFor(this, recipient.getAddress(), true);
|
||||
recipient.addListener(this);
|
||||
fragment.reloadList();
|
||||
break;
|
||||
case PICK_LOCATION:
|
||||
@ -462,14 +461,14 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
menu.clear();
|
||||
|
||||
if (isSecureText) {
|
||||
if (recipients.getExpireMessages() > 0) {
|
||||
if (recipient.getExpireMessages() > 0) {
|
||||
inflater.inflate(R.menu.conversation_expiring_on, menu);
|
||||
|
||||
final MenuItem item = menu.findItem(R.id.menu_expiring_messages);
|
||||
final View actionView = MenuItemCompat.getActionView(item);
|
||||
final TextView badgeView = (TextView)actionView.findViewById(R.id.expiration_badge);
|
||||
|
||||
badgeView.setText(ExpirationUtil.getExpirationAbbreviatedDisplayValue(this, recipients.getExpireMessages()));
|
||||
badgeView.setText(ExpirationUtil.getExpirationAbbreviatedDisplayValue(this, recipient.getExpireMessages()));
|
||||
actionView.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@ -507,10 +506,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
inflater.inflate(R.menu.conversation_insecure, menu);
|
||||
}
|
||||
|
||||
if (recipients != null && recipients.isMuted()) inflater.inflate(R.menu.conversation_muted, menu);
|
||||
else inflater.inflate(R.menu.conversation_unmuted, menu);
|
||||
if (recipient != null && recipient.isMuted()) inflater.inflate(R.menu.conversation_muted, menu);
|
||||
else inflater.inflate(R.menu.conversation_unmuted, menu);
|
||||
|
||||
if (isSingleConversation() && getRecipients().getPrimaryRecipient().getContactUri() == null) {
|
||||
if (isSingleConversation() && getRecipient().getContactUri() == null) {
|
||||
inflater.inflate(R.menu.conversation_add_to_contacts, menu);
|
||||
}
|
||||
|
||||
@ -523,7 +522,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
super.onOptionsItemSelected(item);
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_call_secure:
|
||||
case R.id.menu_call_insecure: handleDial(getRecipients().getPrimaryRecipient()); return true;
|
||||
case R.id.menu_call_insecure: handleDial(getRecipient()); return true;
|
||||
case R.id.menu_add_attachment: handleAddAttachment(); return true;
|
||||
case R.id.menu_view_media: handleViewMedia(); return true;
|
||||
case R.id.menu_add_to_contacts: handleAddToContacts(); return true;
|
||||
@ -571,17 +570,17 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
return;
|
||||
}
|
||||
|
||||
ExpirationDialog.show(this, recipients.getExpireMessages(), new ExpirationDialog.OnClickListener() {
|
||||
ExpirationDialog.show(this, recipient.getExpireMessages(), new ExpirationDialog.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(final int expirationTime) {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(ConversationActivity.this)
|
||||
.setExpireMessages(recipients, expirationTime);
|
||||
recipients.setExpireMessages(expirationTime);
|
||||
.setExpireMessages(recipient, expirationTime);
|
||||
recipient.setExpireMessages(expirationTime);
|
||||
|
||||
OutgoingExpirationUpdateMessage outgoingMessage = new OutgoingExpirationUpdateMessage(getRecipients(), System.currentTimeMillis(), expirationTime * 1000);
|
||||
OutgoingExpirationUpdateMessage outgoingMessage = new OutgoingExpirationUpdateMessage(getRecipient(), System.currentTimeMillis(), expirationTime * 1000);
|
||||
MessageSender.send(ConversationActivity.this, masterSecret, outgoingMessage, threadId, false, null);
|
||||
|
||||
return null;
|
||||
@ -601,13 +600,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
MuteDialog.show(this, new MuteDialog.MuteSelectionListener() {
|
||||
@Override
|
||||
public void onMuted(final long until) {
|
||||
recipients.setMuted(until);
|
||||
recipient.setMuted(until);
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(ConversationActivity.this)
|
||||
.setMuted(recipients, until);
|
||||
.setMuted(recipient, until);
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -621,13 +620,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private void handleUnmuteNotifications() {
|
||||
recipients.setMuted(0);
|
||||
recipient.setMuted(0);
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(ConversationActivity.this)
|
||||
.setMuted(recipients, 0);
|
||||
.setMuted(recipient, 0);
|
||||
|
||||
return null;
|
||||
}
|
||||
@ -642,13 +641,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
.setPositiveButton(R.string.ConversationActivity_unblock, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
recipients.setBlocked(false);
|
||||
recipient.setBlocked(false);
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(ConversationActivity.this)
|
||||
.setBlocked(recipients, false);
|
||||
.setBlocked(recipient, false);
|
||||
|
||||
ApplicationContext.getInstance(ConversationActivity.this)
|
||||
.getJobManager()
|
||||
@ -680,7 +679,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
composeText.appendInvite(inviteText);
|
||||
} else {
|
||||
Intent intent = new Intent(Intent.ACTION_SENDTO);
|
||||
intent.setData(Uri.parse("smsto:" + recipients.getPrimaryRecipient().getAddress().serialize()));
|
||||
intent.setData(Uri.parse("smsto:" + recipient.getAddress().serialize()));
|
||||
intent.putExtra("sms_body", inviteText);
|
||||
intent.putExtra(Intent.EXTRA_TEXT, inviteText);
|
||||
startActivity(intent);
|
||||
@ -703,7 +702,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
final Context context = getApplicationContext();
|
||||
|
||||
OutgoingEndSessionMessage endSessionMessage =
|
||||
new OutgoingEndSessionMessage(new OutgoingTextMessage(getRecipients(), "TERMINATE", 0, -1));
|
||||
new OutgoingEndSessionMessage(new OutgoingTextMessage(getRecipient(), "TERMINATE", 0, -1));
|
||||
|
||||
new AsyncTask<OutgoingEndSessionMessage, Void, Long>() {
|
||||
@Override
|
||||
@ -726,12 +725,12 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private void handleViewMedia() {
|
||||
Intent intent = new Intent(this, MediaOverviewActivity.class);
|
||||
intent.putExtra(MediaOverviewActivity.THREAD_ID_EXTRA, threadId);
|
||||
intent.putExtra(MediaOverviewActivity.ADDRESSES_EXTRA, recipients.getAddresses());
|
||||
intent.putExtra(MediaOverviewActivity.ADDRESS_EXTRA, recipient.getAddress());
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
private void handleLeavePushGroup() {
|
||||
if (getRecipients() == null) {
|
||||
if (getRecipient() == null) {
|
||||
Toast.makeText(this, getString(R.string.ConversationActivity_invalid_recipient),
|
||||
Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
@ -747,15 +746,15 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Context self = ConversationActivity.this;
|
||||
try {
|
||||
byte[] groupId = GroupUtil.getDecodedId(getRecipients().getPrimaryRecipient().getAddress().toGroupString());
|
||||
String groupId = getRecipient().getAddress().toGroupString();
|
||||
DatabaseFactory.getGroupDatabase(self).setActive(groupId, false);
|
||||
|
||||
GroupContext context = GroupContext.newBuilder()
|
||||
.setId(ByteString.copyFrom(groupId))
|
||||
.setId(ByteString.copyFrom(GroupUtil.getDecodedId(groupId)))
|
||||
.setType(GroupContext.Type.QUIT)
|
||||
.build();
|
||||
|
||||
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(getRecipients(), context, null, System.currentTimeMillis(), 0);
|
||||
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(getRecipient(), context, null, System.currentTimeMillis(), 0);
|
||||
MessageSender.send(self, masterSecret, outgoingMessage, threadId, false, null);
|
||||
DatabaseFactory.getGroupDatabase(self).remove(groupId, Address.fromSerialized(TextSecurePreferences.getLocalNumber(self)));
|
||||
initializeEnabledCheck();
|
||||
@ -772,7 +771,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
private void handleEditPushGroup() {
|
||||
Intent intent = new Intent(ConversationActivity.this, GroupCreateActivity.class);
|
||||
intent.putExtra(GroupCreateActivity.GROUP_ADDRESS_EXTRA, recipients.getPrimaryRecipient().getAddress());
|
||||
intent.putExtra(GroupCreateActivity.GROUP_ADDRESS_EXTRA, recipient.getAddress());
|
||||
startActivityForResult(intent, GROUP_EDIT);
|
||||
}
|
||||
|
||||
@ -835,18 +834,18 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private void handleDisplayGroupRecipients() {
|
||||
new GroupMembersDialog(this, getRecipients()).display();
|
||||
new GroupMembersDialog(this, getRecipient()).display();
|
||||
}
|
||||
|
||||
private void handleAddToContacts() {
|
||||
if (recipients.getPrimaryRecipient().getAddress().isGroup()) return;
|
||||
if (recipient.getAddress().isGroup()) return;
|
||||
|
||||
try {
|
||||
final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
|
||||
if (recipients.getPrimaryRecipient().getAddress().isEmail()) {
|
||||
intent.putExtra(ContactsContract.Intents.Insert.EMAIL, recipients.getPrimaryRecipient().getAddress().toEmailString());
|
||||
if (recipient.getAddress().isEmail()) {
|
||||
intent.putExtra(ContactsContract.Intents.Insert.EMAIL, recipient.getAddress().toEmailString());
|
||||
} else {
|
||||
intent.putExtra(ContactsContract.Intents.Insert.PHONE, recipients.getPrimaryRecipient().getAddress().toPhoneString());
|
||||
intent.putExtra(ContactsContract.Intents.Insert.PHONE, recipient.getAddress().toPhoneString());
|
||||
}
|
||||
intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
|
||||
startActivityForResult(intent, ADD_CONTACT);
|
||||
@ -928,19 +927,19 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
this.isSecureText = isSecureText;
|
||||
this.isDefaultSms = isDefaultSms;
|
||||
|
||||
boolean isMediaMessage = !recipients.isSingleRecipient() || attachmentManager.isAttachmentPresent();
|
||||
boolean isMediaMessage = recipient.isMmsGroupRecipient() || attachmentManager.isAttachmentPresent();
|
||||
|
||||
sendButton.resetAvailableTransports(isMediaMessage);
|
||||
|
||||
if (!isSecureText) sendButton.disableTransport(Type.TEXTSECURE);
|
||||
if (recipients.isGroupRecipient()) sendButton.disableTransport(Type.SMS);
|
||||
if (!isSecureText) sendButton.disableTransport(Type.TEXTSECURE);
|
||||
if (recipient.isPushGroupRecipient()) sendButton.disableTransport(Type.SMS);
|
||||
|
||||
if (isSecureText) sendButton.setDefaultTransport(Type.TEXTSECURE);
|
||||
else sendButton.setDefaultTransport(Type.SMS);
|
||||
|
||||
calculateCharactersRemaining();
|
||||
supportInvalidateOptionsMenu();
|
||||
setBlockedUserState(recipients, isSecureText, isDefaultSms);
|
||||
setBlockedUserState(recipient, isSecureText, isDefaultSms);
|
||||
}
|
||||
|
||||
///// Initializers
|
||||
@ -1012,18 +1011,18 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
handleSecurityChange(currentSecureText || isPushGroupConversation(), currentIsDefaultSms);
|
||||
|
||||
new AsyncTask<Recipients, Void, boolean[]>() {
|
||||
new AsyncTask<Recipient, Void, boolean[]>() {
|
||||
@Override
|
||||
protected boolean[] doInBackground(Recipients... params) {
|
||||
protected boolean[] doInBackground(Recipient... params) {
|
||||
Context context = ConversationActivity.this;
|
||||
Recipients recipients = params[0];
|
||||
UserCapabilities capabilities = DirectoryHelper.getUserCapabilities(context, recipients);
|
||||
Recipient recipient = params[0];
|
||||
UserCapabilities capabilities = DirectoryHelper.getUserCapabilities(context, recipient);
|
||||
|
||||
if (capabilities.getTextCapability() == Capability.UNKNOWN ||
|
||||
capabilities.getVideoCapability() == Capability.UNKNOWN)
|
||||
{
|
||||
try {
|
||||
capabilities = DirectoryHelper.refreshDirectoryFor(context, masterSecret, recipients);
|
||||
capabilities = DirectoryHelper.refreshDirectoryFor(context, masterSecret, recipient);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
@ -1040,7 +1039,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
future.set(true);
|
||||
onSecurityUpdated();
|
||||
}
|
||||
}.execute(recipients);
|
||||
}.execute(recipient);
|
||||
|
||||
return future;
|
||||
}
|
||||
@ -1050,7 +1049,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private void updateRecipientPreferences() {
|
||||
new RecipientPreferencesTask().execute(recipients);
|
||||
new RecipientPreferencesTask().execute(recipient);
|
||||
}
|
||||
|
||||
protected void updateInviteReminder(boolean seenInvite) {
|
||||
@ -1059,11 +1058,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
TextSecurePreferences.isShowInviteReminders(this) &&
|
||||
!isSecureText &&
|
||||
!seenInvite &&
|
||||
recipients.isSingleRecipient() &&
|
||||
recipients.getPrimaryRecipient() != null &&
|
||||
recipients.getPrimaryRecipient().getContactUri() != null)
|
||||
!recipient.isGroupRecipient())
|
||||
{
|
||||
InviteReminder reminder = new InviteReminder(this, recipients);
|
||||
InviteReminder reminder = new InviteReminder(this, recipient);
|
||||
reminder.setOkListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@ -1099,34 +1096,32 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
private ListenableFuture<Boolean> initializeIdentityRecords() {
|
||||
final SettableFuture<Boolean> future = new SettableFuture<>();
|
||||
|
||||
new AsyncTask<Recipients, Void, Pair<IdentityRecordList, String>>() {
|
||||
new AsyncTask<Recipient, Void, Pair<IdentityRecordList, String>>() {
|
||||
@Override
|
||||
protected @NonNull Pair<IdentityRecordList, String> doInBackground(Recipients... params) {
|
||||
try {
|
||||
IdentityDatabase identityDatabase = DatabaseFactory.getIdentityDatabase(ConversationActivity.this);
|
||||
IdentityRecordList identityRecordList = new IdentityRecordList();
|
||||
Recipients recipients = params[0];
|
||||
protected @NonNull Pair<IdentityRecordList, String> doInBackground(Recipient... params) {
|
||||
IdentityDatabase identityDatabase = DatabaseFactory.getIdentityDatabase(ConversationActivity.this);
|
||||
IdentityRecordList identityRecordList = new IdentityRecordList();
|
||||
List<Recipient> recipients = new LinkedList<>();
|
||||
|
||||
if (recipients.isGroupRecipient()) {
|
||||
recipients = DatabaseFactory.getGroupDatabase(ConversationActivity.this)
|
||||
.getGroupMembers(GroupUtil.getDecodedId(recipients.getPrimaryRecipient().getAddress().toGroupString()), false);
|
||||
}
|
||||
|
||||
for (Address recipientAddress : recipients.getAddresses()) {
|
||||
Log.w(TAG, "Loading identity for: " + recipientAddress);
|
||||
identityRecordList.add(identityDatabase.getIdentity(recipientAddress));
|
||||
}
|
||||
|
||||
String message = null;
|
||||
|
||||
if (identityRecordList.isUnverified()) {
|
||||
message = IdentityUtil.getUnverifiedBannerDescription(ConversationActivity.this, identityRecordList.getUnverifiedRecipients(ConversationActivity.this));
|
||||
}
|
||||
|
||||
return new Pair<>(identityRecordList, message);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
if (params[0].isGroupRecipient()) {
|
||||
recipients.addAll(DatabaseFactory.getGroupDatabase(ConversationActivity.this)
|
||||
.getGroupMembers(params[0].getAddress().toGroupString(), false));
|
||||
} else {
|
||||
recipients.add(params[0]);
|
||||
}
|
||||
|
||||
for (Recipient recipient : recipients) {
|
||||
Log.w(TAG, "Loading identity for: " + recipient.getAddress());
|
||||
identityRecordList.add(identityDatabase.getIdentity(recipient.getAddress()));
|
||||
}
|
||||
|
||||
String message = null;
|
||||
|
||||
if (identityRecordList.isUnverified()) {
|
||||
message = IdentityUtil.getUnverifiedBannerDescription(ConversationActivity.this, identityRecordList.getUnverifiedRecipients(ConversationActivity.this));
|
||||
}
|
||||
|
||||
return new Pair<>(identityRecordList, message);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1149,7 +1144,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
future.set(true);
|
||||
}
|
||||
|
||||
}.execute(recipients);
|
||||
}.execute(recipient);
|
||||
|
||||
return future;
|
||||
}
|
||||
@ -1212,7 +1207,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(ConversationActivity.this, RecipientPreferenceActivity.class);
|
||||
intent.putExtra(RecipientPreferenceActivity.ADDRESSES_EXTRA, recipients.getAddresses());
|
||||
intent.putExtra(RecipientPreferenceActivity.ADDRESS_EXTRA, recipient.getAddress());
|
||||
intent.putExtra(RecipientPreferenceActivity.CAN_HAVE_SAFETY_NUMBER_EXTRA,
|
||||
isSecureText && !isSelfConversation());
|
||||
|
||||
@ -1257,9 +1252,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private void initializeResources() {
|
||||
if (recipients != null) recipients.removeListener(this);
|
||||
if (recipient != null) recipient.removeListener(this);
|
||||
|
||||
recipients = RecipientFactory.getRecipientsFor(this, Address.fromParcelable(getIntent().getParcelableArrayExtra(ADDRESSES_EXTRA)), true);
|
||||
recipient = RecipientFactory.getRecipientFor(this, (Address)getIntent().getParcelableExtra(ADDRESS_EXTRA), true);
|
||||
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
|
||||
archived = getIntent().getBooleanExtra(IS_ARCHIVED_EXTRA, false);
|
||||
distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
|
||||
@ -1270,7 +1265,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
conversationContainer.setClipToPadding(true);
|
||||
}
|
||||
|
||||
recipients.addListener(this);
|
||||
recipient.addListener(this);
|
||||
}
|
||||
|
||||
private void initializeProfiles() {
|
||||
@ -1281,18 +1276,18 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
ApplicationContext.getInstance(this)
|
||||
.getJobManager()
|
||||
.add(new RetrieveProfileJob(this, recipients));
|
||||
.add(new RetrieveProfileJob(this, recipient));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModified(final Recipients recipients) {
|
||||
public void onModified(final Recipient recipient) {
|
||||
titleView.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
titleView.setTitle(recipients);
|
||||
titleView.setTitle(recipient);
|
||||
titleView.setVerified(identityRecords.isVerified());
|
||||
setBlockedUserState(recipients, isSecureText, isDefaultSms);
|
||||
setActionBarColor(recipients.getColor());
|
||||
setBlockedUserState(recipient, isSecureText, isDefaultSms);
|
||||
setActionBarColor(recipient.getColor());
|
||||
invalidateOptionsMenu();
|
||||
updateRecipientPreferences();
|
||||
}
|
||||
@ -1301,8 +1296,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onRecipientPreferenceUpdate(final RecipientPreferenceEvent event) {
|
||||
if (Arrays.equals(event.getRecipients().getAddresses(), this.recipients.getAddresses())) {
|
||||
new RecipientPreferencesTask().execute(this.recipients);
|
||||
if (event.getRecipient().getAddress().equals(this.recipient.getAddress())) {
|
||||
new RecipientPreferencesTask().execute(this.recipient);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1324,11 +1319,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Log.w(TAG, "Group update received...");
|
||||
if (recipients != null) {
|
||||
if (recipient != null) {
|
||||
Log.w(TAG, "Looking up new recipients...");
|
||||
recipients = RecipientFactory.getRecipientsFor(context, recipients.getAddresses(), true);
|
||||
recipients.addListener(ConversationActivity.this);
|
||||
onModified(recipients);
|
||||
recipient = RecipientFactory.getRecipientFor(context, recipient.getAddress(), true);
|
||||
recipient.addListener(ConversationActivity.this);
|
||||
onModified(recipient);
|
||||
fragment.reloadList();
|
||||
}
|
||||
}
|
||||
@ -1422,7 +1417,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
protected ListenableFuture<Long> saveDraft() {
|
||||
final SettableFuture<Long> future = new SettableFuture<>();
|
||||
|
||||
if (this.recipients == null || this.recipients.isEmpty()) {
|
||||
if (this.recipient == null) {
|
||||
future.set(threadId);
|
||||
return future;
|
||||
}
|
||||
@ -1440,7 +1435,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
long threadId = params[0];
|
||||
|
||||
if (drafts.size() > 0) {
|
||||
if (threadId == -1) threadId = threadDatabase.getThreadIdFor(getRecipients(), thisDistributionType);
|
||||
if (threadId == -1) threadId = threadDatabase.getThreadIdFor(getRecipient(), thisDistributionType);
|
||||
|
||||
draftDatabase.insertDrafts(new MasterCipher(thisMasterSecret), threadId, drafts);
|
||||
threadDatabase.updateSnippet(threadId, drafts.getSnippet(ConversationActivity.this),
|
||||
@ -1468,8 +1463,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
setStatusBarColor(color.toStatusBarColor(this));
|
||||
}
|
||||
|
||||
private void setBlockedUserState(Recipients recipients, boolean isSecureText, boolean isDefaultSms) {
|
||||
if (recipients.isBlocked()) {
|
||||
private void setBlockedUserState(Recipient recipient, boolean isSecureText, boolean isDefaultSms) {
|
||||
if (recipient.isBlocked()) {
|
||||
unblockButton.setVisibility(View.VISIBLE);
|
||||
composePanel.setVisibility(View.GONE);
|
||||
makeDefaultSmsButton.setVisibility(View.GONE);
|
||||
@ -1499,42 +1494,33 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private boolean isSingleConversation() {
|
||||
return getRecipients() != null && getRecipients().isSingleRecipient() && !getRecipients().isGroupRecipient();
|
||||
return getRecipient() != null && !getRecipient().isGroupRecipient();
|
||||
}
|
||||
|
||||
private boolean isActiveGroup() {
|
||||
if (!isGroupConversation()) return false;
|
||||
|
||||
try {
|
||||
byte[] groupId = GroupUtil.getDecodedId(getRecipients().getPrimaryRecipient().getAddress().toGroupString());
|
||||
GroupRecord record = DatabaseFactory.getGroupDatabase(this).getGroup(groupId);
|
||||
|
||||
return record != null && record.isActive();
|
||||
} catch (IOException e) {
|
||||
Log.w("ConversationActivity", e);
|
||||
return false;
|
||||
}
|
||||
GroupRecord record = DatabaseFactory.getGroupDatabase(this).getGroup(getRecipient().getAddress().toGroupString());
|
||||
return record != null && record.isActive();
|
||||
}
|
||||
|
||||
private boolean isSelfConversation() {
|
||||
if (!TextSecurePreferences.isPushRegistered(this)) return false;
|
||||
if (!recipients.isSingleRecipient()) return false;
|
||||
if (recipients.getPrimaryRecipient().isGroupRecipient()) return false;
|
||||
if (!TextSecurePreferences.isPushRegistered(this)) return false;
|
||||
if (recipient.isGroupRecipient()) return false;
|
||||
|
||||
return Util.isOwnNumber(this, recipients.getPrimaryRecipient().getAddress());
|
||||
return Util.isOwnNumber(this, recipient.getAddress());
|
||||
}
|
||||
|
||||
private boolean isGroupConversation() {
|
||||
return getRecipients() != null &&
|
||||
(!getRecipients().isSingleRecipient() || getRecipients().isGroupRecipient());
|
||||
return getRecipient() != null && getRecipient().isGroupRecipient();
|
||||
}
|
||||
|
||||
private boolean isPushGroupConversation() {
|
||||
return getRecipients() != null && getRecipients().isGroupRecipient();
|
||||
return getRecipient() != null && getRecipient().isPushGroupRecipient();
|
||||
}
|
||||
|
||||
protected Recipients getRecipients() {
|
||||
return this.recipients;
|
||||
protected Recipient getRecipient() {
|
||||
return this.recipient;
|
||||
}
|
||||
|
||||
protected long getThreadId() {
|
||||
@ -1592,7 +1578,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
fragment.setLastSeen(0);
|
||||
|
||||
if (refreshFragment) {
|
||||
fragment.reload(recipients, threadId);
|
||||
fragment.reload(recipient, threadId);
|
||||
MessageNotifier.setVisibleThread(threadId);
|
||||
}
|
||||
|
||||
@ -1602,26 +1588,26 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
private void sendMessage() {
|
||||
try {
|
||||
Recipients recipients = getRecipients();
|
||||
Recipient recipient = getRecipient();
|
||||
|
||||
if (recipients == null) {
|
||||
if (recipient == null) {
|
||||
throw new RecipientFormattingException("Badly formatted");
|
||||
}
|
||||
|
||||
boolean forceSms = sendButton.isManualSelection() && sendButton.getSelectedTransport().isSms();
|
||||
int subscriptionId = sendButton.getSelectedTransport().getSimSubscriptionId().or(-1);
|
||||
long expiresIn = recipients.getExpireMessages() * 1000;
|
||||
long expiresIn = recipient.getExpireMessages() * 1000;
|
||||
|
||||
Log.w(TAG, "isManual Selection: " + sendButton.isManualSelection());
|
||||
Log.w(TAG, "forceSms: " + forceSms);
|
||||
|
||||
if ((!recipients.isSingleRecipient() || recipients.isEmailRecipient()) && !isMmsEnabled) {
|
||||
if ((!recipient.isMmsGroupRecipient() || recipient.getAddress().isEmail()) && !isMmsEnabled) {
|
||||
handleManualMmsRequired();
|
||||
} else if (!forceSms && identityRecords.isUnverified()) {
|
||||
handleUnverifiedRecipients();
|
||||
} else if (!forceSms && identityRecords.isUntrusted()) {
|
||||
handleUntrustedRecipients();
|
||||
} else if (attachmentManager.isAttachmentPresent() || !recipients.isSingleRecipient() || recipients.isGroupRecipient() || recipients.isEmailRecipient()) {
|
||||
} else if (attachmentManager.isAttachmentPresent() || recipient.isGroupRecipient() || recipient.getAddress().isEmail()) {
|
||||
sendMediaMessage(forceSms, expiresIn, subscriptionId);
|
||||
} else {
|
||||
sendTextMessage(forceSms, expiresIn, subscriptionId);
|
||||
@ -1649,7 +1635,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
{
|
||||
final SettableFuture<Void> future = new SettableFuture<>();
|
||||
final Context context = getApplicationContext();
|
||||
OutgoingMediaMessage outgoingMessage = new OutgoingMediaMessage(recipients,
|
||||
OutgoingMediaMessage outgoingMessage = new OutgoingMediaMessage(recipient,
|
||||
slideDeck,
|
||||
body,
|
||||
System.currentTimeMillis(),
|
||||
@ -1693,9 +1679,9 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
OutgoingTextMessage message;
|
||||
|
||||
if (isSecureText && !forceSms) {
|
||||
message = new OutgoingEncryptedMessage(recipients, getMessage(), expiresIn);
|
||||
message = new OutgoingEncryptedMessage(recipient, getMessage(), expiresIn);
|
||||
} else {
|
||||
message = new OutgoingTextMessage(recipients, getMessage(), expiresIn, subscriptionId);
|
||||
message = new OutgoingTextMessage(recipient, getMessage(), expiresIn, subscriptionId);
|
||||
}
|
||||
|
||||
this.composeText.setText("");
|
||||
@ -1734,7 +1720,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(ConversationActivity.this)
|
||||
.setDefaultSubscriptionId(recipients, subscriptionId.or(-1));
|
||||
.setDefaultSubscriptionId(recipient, subscriptionId.or(-1));
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
@ -1796,7 +1782,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
try {
|
||||
boolean forceSms = sendButton.isManualSelection() && sendButton.getSelectedTransport().isSms();
|
||||
int subscriptionId = sendButton.getSelectedTransport().getSimSubscriptionId().or(-1);
|
||||
long expiresIn = recipients.getExpireMessages() * 1000;
|
||||
long expiresIn = recipient.getExpireMessages() * 1000;
|
||||
AudioSlide audioSlide = new AudioSlide(ConversationActivity.this, result.first, result.second, MediaUtil.AUDIO_AAC, true);
|
||||
SlideDeck slideDeck = new SlideDeck();
|
||||
slideDeck.addSlide(audioSlide);
|
||||
@ -1997,21 +1983,21 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
||||
updateToggleButtonState();
|
||||
}
|
||||
|
||||
private class RecipientPreferencesTask extends AsyncTask<Recipients, Void, Pair<Recipients,RecipientsPreferences>> {
|
||||
private class RecipientPreferencesTask extends AsyncTask<Recipient, Void, Pair<Recipient,RecipientsPreferences>> {
|
||||
@Override
|
||||
protected Pair<Recipients, RecipientsPreferences> doInBackground(Recipients... recipients) {
|
||||
if (recipients.length != 1 || recipients[0] == null) {
|
||||
protected Pair<Recipient, RecipientsPreferences> doInBackground(Recipient... recipient) {
|
||||
if (recipient.length != 1 || recipient[0] == null) {
|
||||
throw new AssertionError("task needs exactly one Recipients object");
|
||||
}
|
||||
|
||||
Optional<RecipientsPreferences> prefs = DatabaseFactory.getRecipientPreferenceDatabase(ConversationActivity.this)
|
||||
.getRecipientsPreferences(recipients[0].getAddresses());
|
||||
return new Pair<>(recipients[0], prefs.orNull());
|
||||
.getRecipientsPreferences(recipient[0].getAddress());
|
||||
return new Pair<>(recipient[0], prefs.orNull());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(@NonNull Pair<Recipients, RecipientsPreferences> result) {
|
||||
if (result.first == recipients) {
|
||||
protected void onPostExecute(@NonNull Pair<Recipient, RecipientsPreferences> result) {
|
||||
if (result.first == recipient) {
|
||||
updateInviteReminder(result.second != null && result.second.hasSeenInviteReminder());
|
||||
updateDefaultSubscriptionId(result.second != null ? result.second.getDefaultSubscriptionId() : Optional.<Integer>absent());
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Conversions;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.thoughtcrime.securesms.util.LRUCache;
|
||||
@ -93,7 +93,7 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
|
||||
private final @Nullable ItemClickListener clickListener;
|
||||
private final @NonNull MasterSecret masterSecret;
|
||||
private final @NonNull Locale locale;
|
||||
private final @NonNull Recipients recipients;
|
||||
private final @NonNull Recipient recipient;
|
||||
private final @NonNull MmsSmsDatabase db;
|
||||
private final @NonNull LayoutInflater inflater;
|
||||
private final @NonNull Calendar calendar;
|
||||
@ -143,7 +143,7 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
|
||||
this.masterSecret = null;
|
||||
this.locale = null;
|
||||
this.clickListener = null;
|
||||
this.recipients = null;
|
||||
this.recipient = null;
|
||||
this.inflater = null;
|
||||
this.db = null;
|
||||
this.calendar = null;
|
||||
@ -158,7 +158,7 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
|
||||
@NonNull Locale locale,
|
||||
@Nullable ItemClickListener clickListener,
|
||||
@Nullable Cursor cursor,
|
||||
@NonNull Recipients recipients)
|
||||
@NonNull Recipient recipient)
|
||||
{
|
||||
super(context, cursor);
|
||||
|
||||
@ -166,7 +166,7 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
|
||||
this.masterSecret = masterSecret;
|
||||
this.locale = locale;
|
||||
this.clickListener = clickListener;
|
||||
this.recipients = recipients;
|
||||
this.recipient = recipient;
|
||||
this.inflater = LayoutInflater.from(context);
|
||||
this.db = DatabaseFactory.getMmsSmsDatabase(context);
|
||||
this.calendar = Calendar.getInstance();
|
||||
@ -188,7 +188,7 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
|
||||
@Override
|
||||
protected void onBindItemViewHolder(ViewHolder viewHolder, @NonNull MessageRecord messageRecord) {
|
||||
long start = System.currentTimeMillis();
|
||||
viewHolder.getView().bind(masterSecret, messageRecord, locale, batchSelected, recipients);
|
||||
viewHolder.getView().bind(masterSecret, messageRecord, locale, batchSelected, recipient);
|
||||
Log.w(TAG, "Bind time: " + (System.currentTimeMillis() - start));
|
||||
}
|
||||
|
||||
|
@ -61,8 +61,8 @@ import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
|
||||
@ -91,7 +91,7 @@ public class ConversationFragment extends Fragment
|
||||
private ConversationFragmentListener listener;
|
||||
|
||||
private MasterSecret masterSecret;
|
||||
private Recipients recipients;
|
||||
private Recipient recipient;
|
||||
private long threadId;
|
||||
private long lastSeen;
|
||||
private boolean firstLoad;
|
||||
@ -184,7 +184,7 @@ public class ConversationFragment extends Fragment
|
||||
}
|
||||
|
||||
private void initializeResources() {
|
||||
this.recipients = RecipientFactory.getRecipientsFor(getActivity(), Address.fromParcelable(getActivity().getIntent().getParcelableArrayExtra(ConversationActivity.ADDRESSES_EXTRA)), true);
|
||||
this.recipient = RecipientFactory.getRecipientFor(getActivity(), (Address)getActivity().getIntent().getParcelableExtra(ConversationActivity.ADDRESS_EXTRA), true);
|
||||
this.threadId = this.getActivity().getIntent().getLongExtra(ConversationActivity.THREAD_ID_EXTRA, -1);
|
||||
this.lastSeen = this.getActivity().getIntent().getLongExtra(ConversationActivity.LAST_SEEN_EXTRA, -1);
|
||||
this.firstLoad = true;
|
||||
@ -194,8 +194,8 @@ public class ConversationFragment extends Fragment
|
||||
}
|
||||
|
||||
private void initializeListAdapter() {
|
||||
if (this.recipients != null && this.threadId != -1) {
|
||||
ConversationAdapter adapter = new ConversationAdapter(getActivity(), masterSecret, locale, selectionClickListener, null, this.recipients);
|
||||
if (this.recipient != null && this.threadId != -1) {
|
||||
ConversationAdapter adapter = new ConversationAdapter(getActivity(), masterSecret, locale, selectionClickListener, null, this.recipient);
|
||||
list.setAdapter(adapter);
|
||||
list.addItemDecoration(new StickyHeaderDecoration(adapter, false, false));
|
||||
|
||||
@ -256,8 +256,8 @@ public class ConversationFragment extends Fragment
|
||||
else throw new AssertionError();
|
||||
}
|
||||
|
||||
public void reload(Recipients recipients, long threadId) {
|
||||
this.recipients = recipients;
|
||||
public void reload(Recipient recipient, long threadId) {
|
||||
this.recipient = recipient;
|
||||
|
||||
if (this.threadId != threadId) {
|
||||
this.threadId = threadId;
|
||||
@ -359,8 +359,8 @@ public class ConversationFragment extends Fragment
|
||||
intent.putExtra(MessageDetailsActivity.MESSAGE_ID_EXTRA, message.getId());
|
||||
intent.putExtra(MessageDetailsActivity.THREAD_ID_EXTRA, threadId);
|
||||
intent.putExtra(MessageDetailsActivity.TYPE_EXTRA, message.isMms() ? MmsSmsDatabase.MMS_TRANSPORT : MmsSmsDatabase.SMS_TRANSPORT);
|
||||
intent.putExtra(MessageDetailsActivity.ADDRESSES_EXTRA, recipients.getAddresses());
|
||||
intent.putExtra(MessageDetailsActivity.IS_PUSH_GROUP_EXTRA, (!recipients.isSingleRecipient() || recipients.isGroupRecipient()) && message.isPush());
|
||||
intent.putExtra(MessageDetailsActivity.ADDRESS_EXTRA, recipient.getAddress());
|
||||
intent.putExtra(MessageDetailsActivity.IS_PUSH_GROUP_EXTRA, recipient.isGroupRecipient() && message.isPush());
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
|
@ -70,7 +70,7 @@ import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.mms.SlideClickListener;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
@ -97,7 +97,7 @@ import java.util.Set;
|
||||
*/
|
||||
|
||||
public class ConversationItem extends LinearLayout
|
||||
implements Recipient.RecipientModifiedListener, Recipients.RecipientsModifiedListener, BindableConversationItem
|
||||
implements RecipientModifiedListener, BindableConversationItem
|
||||
{
|
||||
private final static String TAG = ConversationItem.class.getSimpleName();
|
||||
|
||||
@ -119,7 +119,7 @@ public class ConversationItem extends LinearLayout
|
||||
private AlertView alertView;
|
||||
|
||||
private @NonNull Set<MessageRecord> batchSelected = new HashSet<>();
|
||||
private @Nullable Recipients conversationRecipients;
|
||||
private @Nullable Recipient conversationRecipient;
|
||||
private @NonNull Stub<ThumbnailView> mediaThumbnailStub;
|
||||
private @NonNull Stub<AudioView> audioViewStub;
|
||||
private @NonNull Stub<DocumentView> documentViewStub;
|
||||
@ -180,18 +180,18 @@ public class ConversationItem extends LinearLayout
|
||||
@NonNull MessageRecord messageRecord,
|
||||
@NonNull Locale locale,
|
||||
@NonNull Set<MessageRecord> batchSelected,
|
||||
@NonNull Recipients conversationRecipients)
|
||||
@NonNull Recipient conversationRecipient)
|
||||
{
|
||||
this.masterSecret = masterSecret;
|
||||
this.messageRecord = messageRecord;
|
||||
this.locale = locale;
|
||||
this.batchSelected = batchSelected;
|
||||
this.conversationRecipients = conversationRecipients;
|
||||
this.groupThread = !conversationRecipients.isSingleRecipient() || conversationRecipients.isGroupRecipient();
|
||||
this.conversationRecipient = conversationRecipient;
|
||||
this.groupThread = conversationRecipient.isGroupRecipient();
|
||||
this.recipient = messageRecord.getIndividualRecipient();
|
||||
|
||||
this.recipient.addListener(this);
|
||||
this.conversationRecipients.addListener(this);
|
||||
this.conversationRecipient.addListener(this);
|
||||
|
||||
setMediaAttributes(messageRecord);
|
||||
setInteractionState(messageRecord);
|
||||
@ -241,35 +241,35 @@ public class ConversationItem extends LinearLayout
|
||||
}
|
||||
|
||||
if (audioViewStub.resolved()) {
|
||||
setAudioViewTint(messageRecord, conversationRecipients);
|
||||
setAudioViewTint(messageRecord, conversationRecipient);
|
||||
}
|
||||
|
||||
if (documentViewStub.resolved()) {
|
||||
setDocumentViewTint(messageRecord, conversationRecipients);
|
||||
setDocumentViewTint(messageRecord, conversationRecipient);
|
||||
}
|
||||
}
|
||||
|
||||
private void setAudioViewTint(MessageRecord messageRecord, Recipients recipients) {
|
||||
private void setAudioViewTint(MessageRecord messageRecord, Recipient recipient) {
|
||||
if (messageRecord.isOutgoing()) {
|
||||
if (DynamicTheme.LIGHT.equals(TextSecurePreferences.getTheme(context))) {
|
||||
audioViewStub.get().setTint(recipients.getColor().toConversationColor(context), defaultBubbleColor);
|
||||
audioViewStub.get().setTint(recipient.getColor().toConversationColor(context), defaultBubbleColor);
|
||||
} else {
|
||||
audioViewStub.get().setTint(Color.WHITE, defaultBubbleColor);
|
||||
}
|
||||
} else {
|
||||
audioViewStub.get().setTint(Color.WHITE, recipients.getColor().toConversationColor(context));
|
||||
audioViewStub.get().setTint(Color.WHITE, recipient.getColor().toConversationColor(context));
|
||||
}
|
||||
}
|
||||
|
||||
private void setDocumentViewTint(MessageRecord messageRecord, Recipients recipients) {
|
||||
private void setDocumentViewTint(MessageRecord messageRecord, Recipient recipient) {
|
||||
if (messageRecord.isOutgoing()) {
|
||||
if (DynamicTheme.LIGHT.equals(TextSecurePreferences.getTheme(context))) {
|
||||
documentViewStub.get().setTint(recipients.getColor().toConversationColor(context), defaultBubbleColor);
|
||||
documentViewStub.get().setTint(recipient.getColor().toConversationColor(context), defaultBubbleColor);
|
||||
} else {
|
||||
documentViewStub.get().setTint(Color.WHITE, defaultBubbleColor);
|
||||
}
|
||||
} else {
|
||||
documentViewStub.get().setTint(Color.WHITE, recipients.getColor().toConversationColor(context));
|
||||
documentViewStub.get().setTint(Color.WHITE, recipient.getColor().toConversationColor(context));
|
||||
}
|
||||
}
|
||||
|
||||
@ -535,16 +535,7 @@ public class ConversationItem extends LinearLayout
|
||||
setBubbleState(messageRecord, recipient);
|
||||
setContactPhoto(recipient);
|
||||
setGroupMessageStatus(messageRecord, recipient);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModified(final Recipients recipients) {
|
||||
Util.runOnMain(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setAudioViewTint(messageRecord, recipients);
|
||||
setAudioViewTint(messageRecord, recipient);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -635,7 +626,7 @@ public class ConversationItem extends LinearLayout
|
||||
intent.putExtra(MessageDetailsActivity.THREAD_ID_EXTRA, messageRecord.getThreadId());
|
||||
intent.putExtra(MessageDetailsActivity.TYPE_EXTRA, messageRecord.isMms() ? MmsSmsDatabase.MMS_TRANSPORT : MmsSmsDatabase.SMS_TRANSPORT);
|
||||
intent.putExtra(MessageDetailsActivity.IS_PUSH_GROUP_EXTRA, groupThread && messageRecord.isPush());
|
||||
intent.putExtra(MessageDetailsActivity.ADDRESSES_EXTRA, conversationRecipients.getAddresses());
|
||||
intent.putExtra(MessageDetailsActivity.ADDRESS_EXTRA, conversationRecipient.getAddress());
|
||||
context.startActivity(intent);
|
||||
} else if (!messageRecord.isOutgoing() && messageRecord.isIdentityMismatchFailure()) {
|
||||
handleApproveIdentity();
|
||||
|
@ -37,8 +37,8 @@ import org.thoughtcrime.securesms.components.RatingManager;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
@ -160,9 +160,9 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateConversation(long threadId, Recipients recipients, int distributionType, long lastSeen) {
|
||||
public void onCreateConversation(long threadId, Recipient recipient, int distributionType, long lastSeen) {
|
||||
Intent intent = new Intent(this, ConversationActivity.class);
|
||||
intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, recipients.getAddresses());
|
||||
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.getAddress());
|
||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
|
||||
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType);
|
||||
intent.putExtra(ConversationActivity.TIMING_EXTRA, System.currentTimeMillis());
|
||||
|
@ -78,13 +78,8 @@ public class ConversationListAdapter extends CursorRecyclerViewAdapter<Conversat
|
||||
@Override
|
||||
public long getItemId(@NonNull Cursor cursor) {
|
||||
ThreadRecord record = getThreadRecord(cursor);
|
||||
StringBuilder builder = new StringBuilder("" + record.getThreadId());
|
||||
|
||||
for (Address address : record.getRecipients().getAddresses()) {
|
||||
builder.append("::").append(address.serialize());
|
||||
}
|
||||
|
||||
return Conversions.byteArrayToLong(digest.digest(builder.toString().getBytes()));
|
||||
return Conversions.byteArrayToLong(digest.digest(record.getRecipient().getAddress().serialize().getBytes()));
|
||||
}
|
||||
|
||||
public ConversationListAdapter(@NonNull Context context,
|
||||
|
@ -6,7 +6,7 @@ import android.support.annotation.NonNull;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
|
||||
@ -54,9 +54,9 @@ public class ConversationListArchiveActivity extends PassphraseRequiredActionBar
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateConversation(long threadId, Recipients recipients, int distributionType, long lastSeenTime) {
|
||||
public void onCreateConversation(long threadId, Recipient recipient, int distributionType, long lastSeenTime) {
|
||||
Intent intent = new Intent(this, ConversationActivity.class);
|
||||
intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, recipients.getAddresses());
|
||||
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.getAddress());
|
||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
|
||||
intent.putExtra(ConversationActivity.IS_ARCHIVED_EXTRA, true);
|
||||
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType);
|
||||
|
@ -69,7 +69,7 @@ import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||
import org.thoughtcrime.securesms.database.loaders.ConversationListLoader;
|
||||
import org.thoughtcrime.securesms.notifications.MarkReadReceiver;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
import org.thoughtcrime.securesms.util.task.SnackbarAsyncTask;
|
||||
@ -309,8 +309,8 @@ public class ConversationListFragment extends Fragment
|
||||
getListAdapter().getBatchSelections().size()));
|
||||
}
|
||||
|
||||
private void handleCreateConversation(long threadId, Recipients recipients, int distributionType, long lastSeen) {
|
||||
((ConversationSelectedListener)getActivity()).onCreateConversation(threadId, recipients, distributionType, lastSeen);
|
||||
private void handleCreateConversation(long threadId, Recipient recipient, int distributionType, long lastSeen) {
|
||||
((ConversationSelectedListener)getActivity()).onCreateConversation(threadId, recipient, distributionType, lastSeen);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -331,7 +331,7 @@ public class ConversationListFragment extends Fragment
|
||||
@Override
|
||||
public void onItemClick(ConversationListItem item) {
|
||||
if (actionMode == null) {
|
||||
handleCreateConversation(item.getThreadId(), item.getRecipients(),
|
||||
handleCreateConversation(item.getThreadId(), item.getRecipient(),
|
||||
item.getDistributionType(), item.getLastSeen());
|
||||
} else {
|
||||
ConversationListAdapter adapter = (ConversationListAdapter)list.getAdapter();
|
||||
@ -363,7 +363,7 @@ public class ConversationListFragment extends Fragment
|
||||
}
|
||||
|
||||
public interface ConversationSelectedListener {
|
||||
void onCreateConversation(long threadId, Recipients recipients, int distributionType, long lastSeen);
|
||||
void onCreateConversation(long threadId, Recipient recipient, int distributionType, long lastSeen);
|
||||
void onSwitchToArchive();
|
||||
}
|
||||
|
||||
|
@ -31,14 +31,15 @@ import android.view.View;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.thoughtcrime.securesms.components.AlertView;
|
||||
import org.thoughtcrime.securesms.components.AvatarImageView;
|
||||
import org.thoughtcrime.securesms.components.DeliveryStatusView;
|
||||
import org.thoughtcrime.securesms.components.AlertView;
|
||||
import org.thoughtcrime.securesms.components.FromTextView;
|
||||
import org.thoughtcrime.securesms.components.ThumbnailView;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.thoughtcrime.securesms.util.ResUtil;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
@ -56,7 +57,7 @@ import static org.thoughtcrime.securesms.util.SpanUtil.color;
|
||||
*/
|
||||
|
||||
public class ConversationListItem extends RelativeLayout
|
||||
implements Recipients.RecipientsModifiedListener,
|
||||
implements RecipientModifiedListener,
|
||||
BindableConversationListItem, Unbindable
|
||||
{
|
||||
private final static String TAG = ConversationListItem.class.getSimpleName();
|
||||
@ -65,7 +66,7 @@ public class ConversationListItem extends RelativeLayout
|
||||
private final static Typeface LIGHT_TYPEFACE = Typeface.create("sans-serif-light", Typeface.NORMAL);
|
||||
|
||||
private Set<Long> selectedThreads;
|
||||
private Recipients recipients;
|
||||
private Recipient recipient;
|
||||
private long threadId;
|
||||
private TextView subjectView;
|
||||
private FromTextView fromView;
|
||||
@ -116,14 +117,14 @@ public class ConversationListItem extends RelativeLayout
|
||||
@NonNull Locale locale, @NonNull Set<Long> selectedThreads, boolean batchMode)
|
||||
{
|
||||
this.selectedThreads = selectedThreads;
|
||||
this.recipients = thread.getRecipients();
|
||||
this.recipient = thread.getRecipient();
|
||||
this.threadId = thread.getThreadId();
|
||||
this.read = thread.isRead();
|
||||
this.distributionType = thread.getDistributionType();
|
||||
this.lastSeen = thread.getLastSeen();
|
||||
|
||||
this.recipients.addListener(this);
|
||||
this.fromView.setText(recipients, read);
|
||||
this.recipient.addListener(this);
|
||||
this.fromView.setText(recipient, read);
|
||||
|
||||
this.subjectView.setText(thread.getDisplayBody());
|
||||
this.subjectView.setTypeface(read ? LIGHT_TYPEFACE : BOLD_TYPEFACE);
|
||||
@ -144,21 +145,21 @@ public class ConversationListItem extends RelativeLayout
|
||||
setThumbnailSnippet(masterSecret, thread);
|
||||
setBatchState(batchMode);
|
||||
setBackground(thread);
|
||||
setRippleColor(recipients);
|
||||
this.contactPhotoImage.setAvatar(recipients, true);
|
||||
setRippleColor(recipient);
|
||||
this.contactPhotoImage.setAvatar(recipient, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbind() {
|
||||
if (this.recipients != null) this.recipients.removeListener(this);
|
||||
if (this.recipient != null) this.recipient.removeListener(this);
|
||||
}
|
||||
|
||||
private void setBatchState(boolean batch) {
|
||||
setSelected(batch && selectedThreads.contains(threadId));
|
||||
}
|
||||
|
||||
public Recipients getRecipients() {
|
||||
return recipients;
|
||||
public Recipient getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
public long getThreadId() {
|
||||
@ -226,21 +227,21 @@ public class ConversationListItem extends RelativeLayout
|
||||
}
|
||||
|
||||
@TargetApi(VERSION_CODES.LOLLIPOP)
|
||||
private void setRippleColor(Recipients recipients) {
|
||||
private void setRippleColor(Recipient recipient) {
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) {
|
||||
((RippleDrawable)(getBackground()).mutate())
|
||||
.setColor(ColorStateList.valueOf(recipients.getColor().toConversationColor(getContext())));
|
||||
.setColor(ColorStateList.valueOf(recipient.getColor().toConversationColor(getContext())));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModified(final Recipients recipients) {
|
||||
public void onModified(final Recipient recipient) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fromView.setText(recipients, read);
|
||||
contactPhotoImage.setAvatar(recipients, true);
|
||||
setRippleColor(recipients);
|
||||
fromView.setText(recipient, read);
|
||||
contactPhotoImage.setAvatar(recipient, true);
|
||||
setRippleColor(recipient);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ public class ConversationPopupActivity extends ConversationActivity {
|
||||
public void onSuccess(Long result) {
|
||||
ActivityOptionsCompat transition = ActivityOptionsCompat.makeScaleUpAnimation(getWindow().getDecorView(), 0, 0, getWindow().getAttributes().width, getWindow().getAttributes().height);
|
||||
Intent intent = new Intent(ConversationPopupActivity.this, ConversationActivity.class);
|
||||
intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, getRecipients().getAddresses());
|
||||
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, getRecipient().getAddress());
|
||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, result);
|
||||
|
||||
if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
|
||||
|
@ -10,7 +10,6 @@ import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public class ConversationTitleView extends LinearLayout {
|
||||
@ -42,14 +41,13 @@ public class ConversationTitleView extends LinearLayout {
|
||||
ViewUtil.setTextViewGravityStart(this.subtitle, getContext());
|
||||
}
|
||||
|
||||
public void setTitle(@Nullable Recipients recipients) {
|
||||
if (recipients == null) setComposeTitle();
|
||||
else if (recipients.isSingleRecipient()) setRecipientTitle(recipients.getPrimaryRecipient());
|
||||
else setRecipientsTitle(recipients);
|
||||
public void setTitle(@Nullable Recipient recipient) {
|
||||
if (recipient == null) setComposeTitle();
|
||||
else setRecipientTitle(recipient);
|
||||
|
||||
if (recipients != null && recipients.isBlocked()) {
|
||||
if (recipient != null && recipient.isBlocked()) {
|
||||
title.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_block_white_18dp, 0, 0, 0);
|
||||
} else if (recipients != null && recipients.isMuted()) {
|
||||
} else if (recipient != null && recipient.isMuted()) {
|
||||
title.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_volume_off_white_18dp, 0, 0, 0);
|
||||
} else {
|
||||
title.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||
@ -86,17 +84,4 @@ public class ConversationTitleView extends LinearLayout {
|
||||
this.subtitle.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setRecipientsTitle(Recipients recipients) {
|
||||
int size = recipients.getRecipientsList().size();
|
||||
|
||||
title.setText(getContext().getString(R.string.ConversationActivity_group_conversation));
|
||||
subtitle.setText(getContext().getResources().getQuantityString(R.plurals.ConversationActivity_d_recipients_in_group, size, size));
|
||||
subtitle.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import org.thoughtcrime.securesms.database.IdentityDatabase;
|
||||
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.IdentityUtil;
|
||||
@ -33,7 +33,7 @@ import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class ConversationUpdateItem extends LinearLayout
|
||||
implements Recipients.RecipientsModifiedListener, Recipient.RecipientModifiedListener, BindableConversationItem
|
||||
implements RecipientModifiedListener, BindableConversationItem
|
||||
{
|
||||
private static final String TAG = ConversationUpdateItem.class.getSimpleName();
|
||||
|
||||
@ -71,7 +71,7 @@ public class ConversationUpdateItem extends LinearLayout
|
||||
@NonNull MessageRecord messageRecord,
|
||||
@NonNull Locale locale,
|
||||
@NonNull Set<MessageRecord> batchSelected,
|
||||
@NonNull Recipients conversationRecipients)
|
||||
@NonNull Recipient conversationRecipient)
|
||||
{
|
||||
this.masterSecret = masterSecret;
|
||||
this.batchSelected = batchSelected;
|
||||
@ -167,12 +167,7 @@ public class ConversationUpdateItem extends LinearLayout
|
||||
body.setText(messageRecord.getDisplayBody());
|
||||
date.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModified(Recipients recipients) {
|
||||
onModified(recipients.getPrimaryRecipient());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onModified(Recipient recipient) {
|
||||
Util.runOnMain(new Runnable() {
|
||||
|
@ -62,11 +62,9 @@ import org.thoughtcrime.securesms.groups.GroupManager.GroupActionResult;
|
||||
import org.thoughtcrime.securesms.mms.RoundedCorners;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.SelectedRecipientsAdapter;
|
||||
import org.thoughtcrime.securesms.util.SelectedRecipientsAdapter.OnRecipientDeletedListener;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
@ -76,7 +74,6 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
@ -214,17 +211,8 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
private void initializeExistingGroup() {
|
||||
final Address groupAddress = getIntent().getParcelableExtra(GROUP_ADDRESS_EXTRA);
|
||||
|
||||
byte[] groupId;
|
||||
|
||||
try {
|
||||
if (groupAddress != null) groupId = GroupUtil.getDecodedId(groupAddress.toGroupString());
|
||||
else groupId = null;
|
||||
} catch (IOException ioe) {
|
||||
Log.w(TAG, "Couldn't decode the encoded groupId passed in via intent", ioe);
|
||||
groupId = null;
|
||||
}
|
||||
if (groupId != null) {
|
||||
new FillExistingGroupInfoAsyncTask(this).execute(groupId);
|
||||
if (groupAddress != null) {
|
||||
new FillExistingGroupInfoAsyncTask(this).execute(groupAddress.toGroupString());
|
||||
}
|
||||
}
|
||||
|
||||
@ -261,8 +249,8 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecipientsPanelUpdate(Recipients recipients) {
|
||||
if (recipients != null) addSelectedContacts(recipients.getRecipientsList());
|
||||
public void onRecipientsPanelUpdate(List<Recipient> recipients) {
|
||||
if (recipients != null && !recipients.isEmpty()) addSelectedContacts(recipients);
|
||||
}
|
||||
|
||||
private void handleGroupCreate() {
|
||||
@ -274,7 +262,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
if (isSignalGroup()) {
|
||||
new CreateSignalGroupTask(this, masterSecret, avatarBmp, getGroupName(), getAdapter().getRecipients()).execute();
|
||||
} else {
|
||||
new CreateMmsGroupTask(this, getAdapter().getRecipients()).execute();
|
||||
new CreateMmsGroupTask(this, masterSecret, getAdapter().getRecipients()).execute();
|
||||
}
|
||||
}
|
||||
|
||||
@ -283,11 +271,11 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
getGroupName(), getAdapter().getRecipients()).execute();
|
||||
}
|
||||
|
||||
private void handleOpenConversation(long threadId, Recipients recipients) {
|
||||
private void handleOpenConversation(long threadId, Recipient recipient) {
|
||||
Intent intent = new Intent(this, ConversationActivity.class);
|
||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
|
||||
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
|
||||
intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, recipients.getAddresses());
|
||||
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.getAddress());
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
@ -347,31 +335,35 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
}
|
||||
|
||||
private static class CreateMmsGroupTask extends AsyncTask<Void,Void,Long> {
|
||||
private GroupCreateActivity activity;
|
||||
private Set<Recipient> members;
|
||||
private static class CreateMmsGroupTask extends AsyncTask<Void,Void,GroupActionResult> {
|
||||
private final GroupCreateActivity activity;
|
||||
private final MasterSecret masterSecret;
|
||||
private final Set<Recipient> members;
|
||||
|
||||
public CreateMmsGroupTask(GroupCreateActivity activity, Set<Recipient> members) {
|
||||
this.activity = activity;
|
||||
this.members = members;
|
||||
public CreateMmsGroupTask(GroupCreateActivity activity, MasterSecret masterSecret, Set<Recipient> members) {
|
||||
this.activity = activity;
|
||||
this.masterSecret = masterSecret;
|
||||
this.members = members;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Long doInBackground(Void... avoid) {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(activity, members, false);
|
||||
return DatabaseFactory.getThreadDatabase(activity)
|
||||
.getThreadIdFor(recipients, ThreadDatabase.DistributionTypes.CONVERSATION);
|
||||
}
|
||||
protected GroupActionResult doInBackground(Void... avoid) {
|
||||
List<Address> memberAddresses = new LinkedList<>();
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Long resultThread) {
|
||||
if (resultThread > -1) {
|
||||
activity.handleOpenConversation(resultThread,
|
||||
RecipientFactory.getRecipientsFor(activity, members, true));
|
||||
} else {
|
||||
Toast.makeText(activity, R.string.GroupCreateActivity_contacts_mms_exception, Toast.LENGTH_LONG).show();
|
||||
activity.finish();
|
||||
for (Recipient recipient : members) {
|
||||
memberAddresses.add(recipient.getAddress());
|
||||
}
|
||||
|
||||
String groupId = DatabaseFactory.getGroupDatabase(activity).getOrCreateGroupForMembers(memberAddresses, true);
|
||||
Recipient groupRecipient = RecipientFactory.getRecipientFor(activity, Address.fromSerialized(groupId), true);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(activity).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.DEFAULT);
|
||||
|
||||
return new GroupActionResult(groupRecipient, threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(GroupActionResult result) {
|
||||
activity.handleOpenConversation(result.getThreadId(), result.getGroupRecipient());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -427,11 +419,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
@Override
|
||||
protected Optional<GroupActionResult> doInBackground(Void... aVoid) {
|
||||
try {
|
||||
return Optional.of(GroupManager.createGroup(activity, masterSecret, members, avatar, name));
|
||||
} catch (InvalidNumberException e) {
|
||||
return Optional.absent();
|
||||
}
|
||||
return Optional.of(GroupManager.createGroup(activity, masterSecret, members, avatar, name, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -449,10 +437,10 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private static class UpdateSignalGroupTask extends SignalGroupTask {
|
||||
private byte[] groupId;
|
||||
private String groupId;
|
||||
|
||||
public UpdateSignalGroupTask(GroupCreateActivity activity,
|
||||
MasterSecret masterSecret, byte[] groupId, Bitmap avatar, String name,
|
||||
MasterSecret masterSecret, String groupId, Bitmap avatar, String name,
|
||||
Set<Recipient> members)
|
||||
{
|
||||
super(activity, masterSecret, avatar, name, members);
|
||||
@ -474,7 +462,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
if (!activity.isFinishing()) {
|
||||
Intent intent = activity.getIntent();
|
||||
intent.putExtra(GROUP_THREAD_EXTRA, result.get().getThreadId());
|
||||
intent.putExtra(GROUP_ADDRESS_EXTRA, result.get().getGroupRecipient().getPrimaryRecipient().getAddress());
|
||||
intent.putExtra(GROUP_ADDRESS_EXTRA, result.get().getGroupRecipient().getAddress());
|
||||
activity.setResult(RESULT_OK, intent);
|
||||
activity.finish();
|
||||
}
|
||||
@ -541,7 +529,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
}
|
||||
|
||||
private static class FillExistingGroupInfoAsyncTask extends ProgressDialogAsyncTask<byte[],Void,Optional<GroupData>> {
|
||||
private static class FillExistingGroupInfoAsyncTask extends ProgressDialogAsyncTask<String,Void,Optional<GroupData>> {
|
||||
private GroupCreateActivity activity;
|
||||
|
||||
public FillExistingGroupInfoAsyncTask(GroupCreateActivity activity) {
|
||||
@ -552,12 +540,12 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<GroupData> doInBackground(byte[]... groupIds) {
|
||||
protected Optional<GroupData> doInBackground(String... groupIds) {
|
||||
final GroupDatabase db = DatabaseFactory.getGroupDatabase(activity);
|
||||
final Recipients recipients = db.getGroupMembers(groupIds[0], false);
|
||||
final List<Recipient> recipients = db.getGroupMembers(groupIds[0], false);
|
||||
final GroupRecord group = db.getGroup(groupIds[0]);
|
||||
final Set<Recipient> existingContacts = new HashSet<>(recipients.getRecipientsList().size());
|
||||
existingContacts.addAll(recipients.getRecipientsList());
|
||||
final Set<Recipient> existingContacts = new HashSet<>(recipients.size());
|
||||
existingContacts.addAll(recipients);
|
||||
|
||||
if (group != null) {
|
||||
return Optional.of(new GroupData(groupIds[0],
|
||||
@ -600,13 +588,13 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
private static class GroupData {
|
||||
byte[] id;
|
||||
String id;
|
||||
Set<Recipient> recipients;
|
||||
Bitmap avatarBmp;
|
||||
byte[] avatarBytes;
|
||||
String name;
|
||||
|
||||
public GroupData(byte[] id, Set<Recipient> recipients, Bitmap avatarBmp, byte[] avatarBytes, String name) {
|
||||
public GroupData(String id, Set<Recipient> recipients, Bitmap avatarBmp, byte[] avatarBytes, String name) {
|
||||
this.id = id;
|
||||
this.recipients = recipients;
|
||||
this.avatarBmp = avatarBmp;
|
||||
|
@ -7,48 +7,36 @@ import android.graphics.Rect;
|
||||
import android.os.AsyncTask;
|
||||
import android.provider.ContactsContract;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class GroupMembersDialog extends AsyncTask<Void, Void, Recipients> {
|
||||
public class GroupMembersDialog extends AsyncTask<Void, Void, List<Recipient>> {
|
||||
|
||||
private static final String TAG = GroupMembersDialog.class.getSimpleName();
|
||||
|
||||
private final Recipients recipients;
|
||||
private final Recipient recipient;
|
||||
private final Context context;
|
||||
|
||||
public GroupMembersDialog(Context context, Recipients recipients) {
|
||||
this.recipients = recipients;
|
||||
this.context = context;
|
||||
public GroupMembersDialog(Context context, Recipient recipient) {
|
||||
this.recipient = recipient;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreExecute() {}
|
||||
|
||||
@Override
|
||||
protected Recipients doInBackground(Void... params) {
|
||||
try {
|
||||
String groupId = recipients.getPrimaryRecipient().getAddress().toGroupString();
|
||||
return DatabaseFactory.getGroupDatabase(context)
|
||||
.getGroupMembers(GroupUtil.getDecodedId(groupId), true);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
return RecipientFactory.getRecipientsFor(context, new LinkedList<Recipient>(), true);
|
||||
}
|
||||
protected List<Recipient> doInBackground(Void... params) {
|
||||
return DatabaseFactory.getGroupDatabase(context).getGroupMembers(recipient.getAddress().toGroupString(), true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostExecute(Recipients members) {
|
||||
public void onPostExecute(List<Recipient> members) {
|
||||
GroupMembers groupMembers = new GroupMembers(members);
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||
builder.setTitle(R.string.ConversationActivity_group_members);
|
||||
@ -60,8 +48,7 @@ public class GroupMembersDialog extends AsyncTask<Void, Void, Recipients> {
|
||||
}
|
||||
|
||||
public void display() {
|
||||
if (recipients.isGroupRecipient()) execute();
|
||||
else onPostExecute(recipients);
|
||||
execute();
|
||||
}
|
||||
|
||||
private static class GroupMembersOnClickListener implements DialogInterface.OnClickListener {
|
||||
@ -107,8 +94,8 @@ public class GroupMembersDialog extends AsyncTask<Void, Void, Recipients> {
|
||||
|
||||
private final LinkedList<Recipient> members = new LinkedList<>();
|
||||
|
||||
public GroupMembers(Recipients recipients) {
|
||||
for (Recipient recipient : recipients.getRecipientsList()) {
|
||||
public GroupMembers(List<Recipient> recipients) {
|
||||
for (Recipient recipient : recipients) {
|
||||
if (isLocalNumber(recipient)) {
|
||||
members.push(recipient);
|
||||
} else {
|
||||
|
@ -30,8 +30,8 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
@ -231,19 +231,17 @@ public class InviteActivity extends PassphraseRequiredActionBarActivity implemen
|
||||
if (context == null) return null;
|
||||
|
||||
for (String number : numbers) {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, number)}, false);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, Address.fromExternal(context, number), false);
|
||||
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(recipient.getAddress());
|
||||
int subscriptionId = preferences.isPresent() ? preferences.get().getDefaultSubscriptionId().or(-1) : -1;
|
||||
|
||||
if (recipients.getPrimaryRecipient() != null) {
|
||||
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(recipients.getAddresses());
|
||||
int subscriptionId = preferences.isPresent() ? preferences.get().getDefaultSubscriptionId().or(-1) : -1;
|
||||
MessageSender.send(context, masterSecret, new OutgoingTextMessage(recipient, message, subscriptionId), -1L, true, null);
|
||||
|
||||
MessageSender.send(context, masterSecret, new OutgoingTextMessage(recipients, message, subscriptionId), -1L, true, null);
|
||||
|
||||
if (recipients.getPrimaryRecipient().getContactUri() != null) {
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(context).setSeenInviteReminder(recipients, true);
|
||||
}
|
||||
if (recipient.getContactUri() != null) {
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(context).setSeenInviteReminder(recipient, true);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,6 @@ import android.database.Cursor;
|
||||
import android.os.Build.VERSION;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.Loader;
|
||||
@ -43,8 +42,9 @@ import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MediaDatabase.MediaRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.util.AbstractCursorLoader;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
|
||||
@ -59,7 +59,7 @@ import java.util.List;
|
||||
public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity implements LoaderManager.LoaderCallbacks<Cursor> {
|
||||
private final static String TAG = MediaOverviewActivity.class.getSimpleName();
|
||||
|
||||
public static final String ADDRESSES_EXTRA = "addresses";
|
||||
public static final String ADDRESS_EXTRA = "address";
|
||||
public static final String THREAD_ID_EXTRA = "thread_id";
|
||||
|
||||
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
||||
@ -69,7 +69,7 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
|
||||
private RecyclerView gridView;
|
||||
private GridLayoutManager gridManager;
|
||||
private TextView noImages;
|
||||
private Recipients recipients;
|
||||
private Recipient recipient;
|
||||
private long threadId;
|
||||
|
||||
@Override
|
||||
@ -114,9 +114,9 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
|
||||
}
|
||||
|
||||
private void initializeActionBar() {
|
||||
getSupportActionBar().setTitle(recipients == null
|
||||
getSupportActionBar().setTitle(recipient == null
|
||||
? getString(R.string.AndroidManifest__all_media)
|
||||
: getString(R.string.AndroidManifest__all_media_named, recipients.toShortString()));
|
||||
: getString(R.string.AndroidManifest__all_media_named, recipient.toShortString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -133,20 +133,20 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
|
||||
gridView.setLayoutManager(gridManager);
|
||||
gridView.setHasFixedSize(true);
|
||||
|
||||
Parcelable[] parcelables = getIntent().getParcelableArrayExtra(ADDRESSES_EXTRA);
|
||||
Address address = getIntent().getParcelableExtra(ADDRESS_EXTRA);
|
||||
|
||||
if (parcelables != null) {
|
||||
recipients = RecipientFactory.getRecipientsFor(this, Address.fromParcelable(parcelables), true);
|
||||
if (address != null) {
|
||||
recipient = RecipientFactory.getRecipientFor(this, address, true);
|
||||
} else if (threadId > -1) {
|
||||
recipients = DatabaseFactory.getThreadDatabase(this).getRecipientsForThreadId(threadId);
|
||||
recipient = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(threadId);
|
||||
} else {
|
||||
recipients = null;
|
||||
recipient = null;
|
||||
}
|
||||
|
||||
if (recipients != null) {
|
||||
recipients.addListener(new Recipients.RecipientsModifiedListener() {
|
||||
if (recipient != null) {
|
||||
recipient.addListener(new RecipientModifiedListener() {
|
||||
@Override
|
||||
public void onModified(Recipients recipients) {
|
||||
public void onModified(Recipient recipients) {
|
||||
initializeActionBar();
|
||||
}
|
||||
});
|
||||
|
@ -37,7 +37,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.mms.VideoSlide;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
|
@ -47,26 +47,25 @@ import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.util.DateUtils;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.ExpirationUtil;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.sql.Date;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* @author Jake McGinty
|
||||
*/
|
||||
public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity implements LoaderCallbacks<Cursor>, Recipients.RecipientsModifiedListener {
|
||||
public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity implements LoaderCallbacks<Cursor>, RecipientModifiedListener {
|
||||
private final static String TAG = MessageDetailsActivity.class.getSimpleName();
|
||||
|
||||
public final static String MASTER_SECRET_EXTRA = "master_secret";
|
||||
@ -74,7 +73,7 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
||||
public final static String THREAD_ID_EXTRA = "thread_id";
|
||||
public final static String IS_PUSH_GROUP_EXTRA = "is_push_group";
|
||||
public final static String TYPE_EXTRA = "type";
|
||||
public final static String ADDRESSES_EXTRA = "addresses";
|
||||
public final static String ADDRESS_EXTRA = "address";
|
||||
|
||||
private MasterSecret masterSecret;
|
||||
private long threadId;
|
||||
@ -139,10 +138,10 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
||||
private void initializeActionBar() {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(this, Address.fromParcelable(getIntent().getParcelableArrayExtra(ADDRESSES_EXTRA)), true);
|
||||
recipients.addListener(this);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(this, (Address)getIntent().getParcelableExtra(ADDRESS_EXTRA), true);
|
||||
recipient.addListener(this);
|
||||
|
||||
setActionBarColor(recipients.getColor());
|
||||
setActionBarColor(recipient.getColor());
|
||||
}
|
||||
|
||||
private void setActionBarColor(MaterialColor color) {
|
||||
@ -154,11 +153,11 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModified(final Recipients recipients) {
|
||||
public void onModified(final Recipient recipient) {
|
||||
Util.runOnMain(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setActionBarColor(recipients.getColor());
|
||||
setActionBarColor(recipient.getColor());
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -243,7 +242,7 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
||||
});
|
||||
}
|
||||
|
||||
private void updateRecipients(MessageRecord messageRecord, Recipients recipients) {
|
||||
private void updateRecipients(MessageRecord messageRecord, Recipient recipient, List<Recipient> recipients) {
|
||||
final int toFromRes;
|
||||
if (messageRecord.isMms() && !messageRecord.isPush() && !messageRecord.isOutgoing()) {
|
||||
toFromRes = R.string.message_details_header__with;
|
||||
@ -254,7 +253,7 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
toFrom.setText(toFromRes);
|
||||
conversationItem.bind(masterSecret, messageRecord, dynamicLanguage.getCurrentLocale(),
|
||||
new HashSet<MessageRecord>(), recipients);
|
||||
new HashSet<MessageRecord>(), recipient);
|
||||
recipientsList.setAdapter(new MessageDetailsRecipientAdapter(this, masterSecret, messageRecord,
|
||||
recipients, isPushGroup));
|
||||
}
|
||||
@ -321,7 +320,7 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
||||
return false;
|
||||
}
|
||||
|
||||
private class MessageRecipientAsyncTask extends AsyncTask<Void,Void,Recipients> {
|
||||
private class MessageRecipientAsyncTask extends AsyncTask<Void,Void,List<Recipient>> {
|
||||
private WeakReference<Context> weakContext;
|
||||
private MessageRecord messageRecord;
|
||||
|
||||
@ -335,41 +334,27 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
@Override
|
||||
public Recipients doInBackground(Void... voids) {
|
||||
public List<Recipient> doInBackground(Void... voids) {
|
||||
Context context = getContext();
|
||||
if (context == null) {
|
||||
Log.w(TAG, "associated context is destroyed, finishing early");
|
||||
return null;
|
||||
}
|
||||
|
||||
Recipients recipients;
|
||||
List<Recipient> recipients = new LinkedList<>();
|
||||
|
||||
final Recipients intermediaryRecipients;
|
||||
if (messageRecord.isMms()) {
|
||||
intermediaryRecipients = DatabaseFactory.getMmsAddressDatabase(context).getRecipientsForId(messageRecord.getId());
|
||||
} else {
|
||||
intermediaryRecipients = messageRecord.getRecipients();
|
||||
}
|
||||
|
||||
if (!intermediaryRecipients.isGroupRecipient()) {
|
||||
if (!messageRecord.getRecipient().isGroupRecipient()) {
|
||||
Log.w(TAG, "Recipient is not a group, resolving members immediately.");
|
||||
recipients = intermediaryRecipients;
|
||||
recipients.add(messageRecord.getRecipient());
|
||||
} else {
|
||||
try {
|
||||
Address groupId = intermediaryRecipients.getPrimaryRecipient().getAddress();
|
||||
recipients = DatabaseFactory.getGroupDatabase(context)
|
||||
.getGroupMembers(GroupUtil.getDecodedId(groupId.toGroupString()), false);
|
||||
} catch (IOException e) {
|
||||
Log.w(TAG, e);
|
||||
recipients = RecipientFactory.getRecipientsFor(MessageDetailsActivity.this, new LinkedList<Recipient>(), false);
|
||||
}
|
||||
recipients.addAll(DatabaseFactory.getGroupDatabase(context).getGroupMembers(messageRecord.getRecipient().getAddress().toGroupString(), false));
|
||||
}
|
||||
|
||||
return recipients;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPostExecute(Recipients recipients) {
|
||||
public void onPostExecute(List<Recipient> recipients) {
|
||||
if (getContext() == null) {
|
||||
Log.w(TAG, "AsyncTask finished with a destroyed context, leaving early.");
|
||||
return;
|
||||
@ -377,7 +362,7 @@ public class MessageDetailsActivity extends PassphraseRequiredActionBarActivity
|
||||
|
||||
inflateMessageViewIfAbsent(messageRecord);
|
||||
|
||||
updateRecipients(messageRecord, recipients);
|
||||
updateRecipients(messageRecord, messageRecord.getRecipient(), recipients);
|
||||
if (messageRecord.isFailed()) {
|
||||
errorText.setVisibility(View.VISIBLE);
|
||||
metadataContainer.setVisibility(View.GONE);
|
||||
|
@ -10,22 +10,22 @@ import android.widget.BaseAdapter;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.Conversions;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.List;
|
||||
|
||||
public class MessageDetailsRecipientAdapter extends BaseAdapter implements AbsListView.RecyclerListener {
|
||||
|
||||
private final Context context;
|
||||
private final MasterSecret masterSecret;
|
||||
private final MessageRecord record;
|
||||
private final Recipients recipients;
|
||||
private final boolean isPushGroup;
|
||||
private final Context context;
|
||||
private final MasterSecret masterSecret;
|
||||
private final MessageRecord record;
|
||||
private final List<Recipient> recipients;
|
||||
private final boolean isPushGroup;
|
||||
|
||||
public MessageDetailsRecipientAdapter(Context context, MasterSecret masterSecret,
|
||||
MessageRecord record, Recipients recipients,
|
||||
MessageRecord record, List<Recipient> recipients,
|
||||
boolean isPushGroup)
|
||||
{
|
||||
this.context = context;
|
||||
@ -37,18 +37,18 @@ public class MessageDetailsRecipientAdapter extends BaseAdapter implements AbsLi
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return recipients.getRecipientsList().size();
|
||||
return recipients.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getItem(int position) {
|
||||
return recipients.getRecipientsList().get(position);
|
||||
return recipients.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
try {
|
||||
return Conversions.byteArrayToLong(MessageDigest.getInstance("SHA1").digest(recipients.getRecipientsList().get(position).getAddress().serialize().getBytes()));
|
||||
return Conversions.byteArrayToLong(MessageDigest.getInstance("SHA1").digest(recipients.get(position).getAddress().serialize().getBytes()));
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
@ -60,7 +60,7 @@ public class MessageDetailsRecipientAdapter extends BaseAdapter implements AbsLi
|
||||
convertView = LayoutInflater.from(context).inflate(R.layout.message_recipient_list_item, parent, false);
|
||||
}
|
||||
|
||||
Recipient recipient = recipients.getRecipientsList().get(position);
|
||||
Recipient recipient = recipients.get(position);
|
||||
((MessageRecipientListItem)convertView).set(masterSecret, record, recipient, isPushGroup);
|
||||
return convertView;
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
|
||||
/**
|
||||
@ -43,7 +44,7 @@ import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
* @author Jake McGinty
|
||||
*/
|
||||
public class MessageRecipientListItem extends RelativeLayout
|
||||
implements Recipient.RecipientModifiedListener
|
||||
implements RecipientModifiedListener
|
||||
{
|
||||
private final static String TAG = MessageRecipientListItem.class.getSimpleName();
|
||||
|
||||
@ -67,6 +68,7 @@ public class MessageRecipientListItem extends RelativeLayout
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
this.fromView = (FromTextView) findViewById(R.id.from);
|
||||
this.errorDescription = (TextView) findViewById(R.id.error_description);
|
||||
this.actionDescription = (TextView) findViewById(R.id.action_description);
|
||||
@ -172,11 +174,13 @@ public class MessageRecipientListItem extends RelativeLayout
|
||||
}
|
||||
|
||||
private class ResendAsyncTask extends AsyncTask<Void,Void,Void> {
|
||||
private final Context context;
|
||||
private final MasterSecret masterSecret;
|
||||
private final MessageRecord record;
|
||||
private final NetworkFailure failure;
|
||||
|
||||
public ResendAsyncTask(MasterSecret masterSecret, MessageRecord record, NetworkFailure failure) {
|
||||
this.context = getContext().getApplicationContext();
|
||||
this.masterSecret = masterSecret;
|
||||
this.record = record;
|
||||
this.failure = failure;
|
||||
@ -184,13 +188,13 @@ public class MessageRecipientListItem extends RelativeLayout
|
||||
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(getContext());
|
||||
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
|
||||
mmsDatabase.removeFailure(record.getId(), failure);
|
||||
|
||||
if (record.getRecipients().isGroupRecipient()) {
|
||||
MessageSender.resendGroupMessage(getContext(), masterSecret, record, failure.getAddress());
|
||||
if (record.getRecipient().isPushGroupRecipient()) {
|
||||
MessageSender.resendGroupMessage(context, record, failure.getAddress());
|
||||
} else {
|
||||
MessageSender.resend(getContext(), masterSecret, record);
|
||||
MessageSender.resend(context, masterSecret, record);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -28,8 +28,8 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
/**
|
||||
* Activity container for starting a new conversation.
|
||||
@ -50,14 +50,14 @@ public class NewConversationActivity extends ContactSelectionActivity {
|
||||
|
||||
@Override
|
||||
public void onContactSelected(String number) {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(this, new Address[] {Address.fromExternal(this, number)}, true);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(this, Address.fromExternal(this, number), true);
|
||||
|
||||
Intent intent = new Intent(this, ConversationActivity.class);
|
||||
intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, recipients.getAddresses());
|
||||
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.getAddress());
|
||||
intent.putExtra(ConversationActivity.TEXT_EXTRA, getIntent().getStringExtra(ConversationActivity.TEXT_EXTRA));
|
||||
intent.setDataAndType(getIntent().getData(), getIntent().getType());
|
||||
|
||||
long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipients);
|
||||
long existingThread = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient);
|
||||
|
||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, existingThread);
|
||||
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, ThreadDatabase.DistributionTypes.DEFAULT);
|
||||
|
@ -41,8 +41,9 @@ import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob;
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
|
||||
import org.thoughtcrime.securesms.preferences.AdvancedRingtonePreference;
|
||||
import org.thoughtcrime.securesms.preferences.ColorPreference;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.util.DirectoryHelper;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
|
||||
@ -53,11 +54,11 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActivity implements Recipients.RecipientsModifiedListener
|
||||
public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActivity implements RecipientModifiedListener
|
||||
{
|
||||
private static final String TAG = RecipientPreferenceActivity.class.getSimpleName();
|
||||
|
||||
public static final String ADDRESSES_EXTRA = "recipient_addresses";
|
||||
public static final String ADDRESS_EXTRA = "recipient_address";
|
||||
public static final String CAN_HAVE_SAFETY_NUMBER_EXTRA = "can_have_safety_number";
|
||||
|
||||
private static final String PREFERENCE_MUTED = "pref_key_recipient_mute";
|
||||
@ -86,16 +87,16 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
public void onCreate(Bundle instanceState, @NonNull MasterSecret masterSecret) {
|
||||
setContentView(R.layout.recipient_preference_activity);
|
||||
|
||||
Address[] addresses = Address.fromParcelable(getIntent().getParcelableArrayExtra(ADDRESSES_EXTRA));
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(this, addresses, true);
|
||||
Address address = getIntent().getParcelableExtra(ADDRESS_EXTRA);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(this, address, true);
|
||||
|
||||
initializeToolbar();
|
||||
initializeReceivers();
|
||||
setHeader(recipients);
|
||||
recipients.addListener(this);
|
||||
setHeader(recipient);
|
||||
recipient.addListener(this);
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putParcelableArray(ADDRESSES_EXTRA, addresses);
|
||||
bundle.putParcelable(ADDRESS_EXTRA, address);
|
||||
initFragment(R.id.preference_fragment, new RecipientPreferenceFragment(), masterSecret, null, bundle);
|
||||
}
|
||||
|
||||
@ -149,9 +150,9 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
this.staleReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, Address.fromParcelable(getIntent().getParcelableArrayExtra(ADDRESSES_EXTRA)), true);
|
||||
recipients.addListener(RecipientPreferenceActivity.this);
|
||||
onModified(recipients);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, (Address)getIntent().getParcelableExtra(ADDRESS_EXTRA), true);
|
||||
recipient.addListener(RecipientPreferenceActivity.this);
|
||||
onModified(recipient);
|
||||
}
|
||||
};
|
||||
|
||||
@ -162,37 +163,37 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
registerReceiver(staleReceiver, staleFilter);
|
||||
}
|
||||
|
||||
private void setHeader(Recipients recipients) {
|
||||
this.avatar.setAvatar(recipients, true);
|
||||
this.title.setText(recipients.toShortString());
|
||||
this.toolbar.setBackgroundColor(recipients.getColor().toActionBarColor(this));
|
||||
private void setHeader(Recipient recipient) {
|
||||
this.avatar.setAvatar(recipient, true);
|
||||
this.title.setText(recipient.toShortString());
|
||||
this.toolbar.setBackgroundColor(recipient.getColor().toActionBarColor(this));
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
getWindow().setStatusBarColor(recipients.getColor().toStatusBarColor(this));
|
||||
getWindow().setStatusBarColor(recipient.getColor().toStatusBarColor(this));
|
||||
}
|
||||
|
||||
if (recipients.isBlocked()) this.blockedIndicator.setVisibility(View.VISIBLE);
|
||||
else this.blockedIndicator.setVisibility(View.GONE);
|
||||
if (recipient.isBlocked()) this.blockedIndicator.setVisibility(View.VISIBLE);
|
||||
else this.blockedIndicator.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModified(final Recipients recipients) {
|
||||
public void onModified(final Recipient recipient) {
|
||||
title.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setHeader(recipients);
|
||||
setHeader(recipient);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static class RecipientPreferenceFragment
|
||||
extends PreferenceFragment
|
||||
implements Recipients.RecipientsModifiedListener
|
||||
implements RecipientModifiedListener
|
||||
{
|
||||
|
||||
private final Handler handler = new Handler();
|
||||
|
||||
private Recipients recipients;
|
||||
private Recipient recipient;
|
||||
private BroadcastReceiver staleReceiver;
|
||||
private MasterSecret masterSecret;
|
||||
private boolean canHaveSafetyNumber;
|
||||
@ -223,29 +224,29 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
setSummaries(recipients);
|
||||
setSummaries(recipient);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
this.recipients.removeListener(this);
|
||||
this.recipient.removeListener(this);
|
||||
getActivity().unregisterReceiver(staleReceiver);
|
||||
}
|
||||
|
||||
private void initializeRecipients() {
|
||||
this.recipients = RecipientFactory.getRecipientsFor(getActivity(),
|
||||
Address.fromParcelable(getArguments().getParcelableArray(ADDRESSES_EXTRA)),
|
||||
true);
|
||||
this.recipient = RecipientFactory.getRecipientFor(getActivity(),
|
||||
(Address)getArguments().getParcelable(ADDRESS_EXTRA),
|
||||
true);
|
||||
|
||||
this.recipients.addListener(this);
|
||||
this.recipient.addListener(this);
|
||||
|
||||
this.staleReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
recipients.removeListener(RecipientPreferenceFragment.this);
|
||||
recipients = RecipientFactory.getRecipientsFor(getActivity(), Address.fromParcelable(getArguments().getParcelableArray(ADDRESSES_EXTRA)), true);
|
||||
onModified(recipients);
|
||||
recipient.removeListener(RecipientPreferenceFragment.this);
|
||||
recipient = RecipientFactory.getRecipientFor(getActivity(), (Address)getArguments().getParcelable(ADDRESS_EXTRA), true);
|
||||
onModified(recipient);
|
||||
}
|
||||
};
|
||||
|
||||
@ -256,7 +257,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
getActivity().registerReceiver(staleReceiver, intentFilter);
|
||||
}
|
||||
|
||||
private void setSummaries(Recipients recipients) {
|
||||
private void setSummaries(Recipient recipient) {
|
||||
CheckBoxPreference mutePreference = (CheckBoxPreference) this.findPreference(PREFERENCE_MUTED);
|
||||
AdvancedRingtonePreference ringtonePreference = (AdvancedRingtonePreference) this.findPreference(PREFERENCE_TONE);
|
||||
ListPreference vibratePreference = (ListPreference) this.findPreference(PREFERENCE_VIBRATE);
|
||||
@ -264,9 +265,9 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
Preference blockPreference = this.findPreference(PREFERENCE_BLOCK);
|
||||
final Preference identityPreference = this.findPreference(PREFERENCE_IDENTITY);
|
||||
|
||||
mutePreference.setChecked(recipients.isMuted());
|
||||
mutePreference.setChecked(recipient.isMuted());
|
||||
|
||||
final Uri toneUri = recipients.getRingtone();
|
||||
final Uri toneUri = recipient.getRingtone();
|
||||
|
||||
if (toneUri == null) {
|
||||
ringtonePreference.setSummary(R.string.preferences__default);
|
||||
@ -283,10 +284,10 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
}
|
||||
}
|
||||
|
||||
if (recipients.getVibrate() == VibrateState.DEFAULT) {
|
||||
if (recipient.getVibrate() == VibrateState.DEFAULT) {
|
||||
vibratePreference.setSummary(R.string.preferences__default);
|
||||
vibratePreference.setValueIndex(0);
|
||||
} else if (recipients.getVibrate() == VibrateState.ENABLED) {
|
||||
} else if (recipient.getVibrate() == VibrateState.ENABLED) {
|
||||
vibratePreference.setSummary(R.string.RecipientPreferenceActivity_enabled);
|
||||
vibratePreference.setValueIndex(1);
|
||||
} else {
|
||||
@ -294,18 +295,18 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
vibratePreference.setValueIndex(2);
|
||||
}
|
||||
|
||||
if (!recipients.isSingleRecipient() || recipients.isGroupRecipient()) {
|
||||
if (recipient.isGroupRecipient()) {
|
||||
if (colorPreference != null) getPreferenceScreen().removePreference(colorPreference);
|
||||
if (blockPreference != null) getPreferenceScreen().removePreference(blockPreference);
|
||||
if (identityPreference != null) getPreferenceScreen().removePreference(identityPreference);
|
||||
} else {
|
||||
colorPreference.setChoices(MaterialColors.CONVERSATION_PALETTE.asConversationColorArray(getActivity()));
|
||||
colorPreference.setValue(recipients.getColor().toActionBarColor(getActivity()));
|
||||
colorPreference.setValue(recipient.getColor().toActionBarColor(getActivity()));
|
||||
|
||||
if (recipients.isBlocked()) blockPreference.setTitle(R.string.RecipientPreferenceActivity_unblock);
|
||||
if (recipient.isBlocked()) blockPreference.setTitle(R.string.RecipientPreferenceActivity_unblock);
|
||||
else blockPreference.setTitle(R.string.RecipientPreferenceActivity_block);
|
||||
|
||||
IdentityUtil.getRemoteIdentityKey(getActivity(), recipients.getPrimaryRecipient()).addListener(new ListenableFuture.Listener<Optional<IdentityRecord>>() {
|
||||
IdentityUtil.getRemoteIdentityKey(getActivity(), recipient).addListener(new ListenableFuture.Listener<Optional<IdentityRecord>>() {
|
||||
@Override
|
||||
public void onSuccess(Optional<IdentityRecord> result) {
|
||||
if (result.isPresent()) {
|
||||
@ -328,11 +329,11 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModified(final Recipients recipients) {
|
||||
public void onModified(final Recipient recipient) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setSummaries(recipients);
|
||||
setSummaries(recipient);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -350,13 +351,13 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
uri = Uri.parse(value);
|
||||
}
|
||||
|
||||
recipients.setRingtone(uri);
|
||||
recipient.setRingtone(uri);
|
||||
|
||||
new AsyncTask<Uri, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Uri... params) {
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(getActivity())
|
||||
.setRingtone(recipients, params[0]);
|
||||
.setRingtone(recipient, params[0]);
|
||||
return null;
|
||||
}
|
||||
}.execute(uri);
|
||||
@ -371,13 +372,13 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
int value = Integer.parseInt((String) newValue);
|
||||
final VibrateState vibrateState = VibrateState.fromId(value);
|
||||
|
||||
recipients.setVibrate(vibrateState);
|
||||
recipient.setVibrate(vibrateState);
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(getActivity())
|
||||
.setVibrate(recipients, vibrateState);
|
||||
.setVibrate(recipient, vibrateState);
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
@ -392,26 +393,26 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final int value = (Integer) newValue;
|
||||
final MaterialColor selectedColor = MaterialColors.CONVERSATION_PALETTE.getByColor(getActivity(), value);
|
||||
final MaterialColor currentColor = recipients.getColor();
|
||||
final MaterialColor currentColor = recipient.getColor();
|
||||
|
||||
if (selectedColor == null) return true;
|
||||
|
||||
if (preference.isEnabled() && !currentColor.equals(selectedColor)) {
|
||||
recipients.setColor(selectedColor);
|
||||
recipient.setColor(selectedColor);
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
Context context = getActivity();
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(context)
|
||||
.setColor(recipients, selectedColor);
|
||||
.setColor(recipient, selectedColor);
|
||||
|
||||
if (DirectoryHelper.getUserCapabilities(context, recipients)
|
||||
if (DirectoryHelper.getUserCapabilities(context, recipient)
|
||||
.getTextCapability() == DirectoryHelper.UserCapabilities.Capability.SUPPORTED)
|
||||
{
|
||||
ApplicationContext.getInstance(context)
|
||||
.getJobManager()
|
||||
.add(new MultiDeviceContactUpdateJob(context, recipients.getPrimaryRecipient().getAddress()));
|
||||
.add(new MultiDeviceContactUpdateJob(context, recipient.getAddress()));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -424,8 +425,8 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
private class MuteClickedListener implements Preference.OnPreferenceClickListener {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
if (recipients.isMuted()) handleUnmute();
|
||||
else handleMute();
|
||||
if (recipient.isMuted()) handleUnmute();
|
||||
else handleMute();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -434,25 +435,25 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
MuteDialog.show(getActivity(), new MuteDialog.MuteSelectionListener() {
|
||||
@Override
|
||||
public void onMuted(long until) {
|
||||
setMuted(recipients, until);
|
||||
setMuted(recipient, until);
|
||||
}
|
||||
});
|
||||
|
||||
setSummaries(recipients);
|
||||
setSummaries(recipient);
|
||||
}
|
||||
|
||||
private void handleUnmute() {
|
||||
setMuted(recipients, 0);
|
||||
setMuted(recipient, 0);
|
||||
}
|
||||
|
||||
private void setMuted(final Recipients recipients, final long until) {
|
||||
recipients.setMuted(until);
|
||||
private void setMuted(final Recipient recipient, final long until) {
|
||||
recipient.setMuted(until);
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(getActivity())
|
||||
.setMuted(recipients, until);
|
||||
.setMuted(recipient, until);
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
@ -471,7 +472,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
Intent verifyIdentityIntent = new Intent(getActivity(), VerifyIdentityActivity.class);
|
||||
verifyIdentityIntent.putExtra(VerifyIdentityActivity.ADDRESS_EXTRA, recipients.getPrimaryRecipient().getAddress());
|
||||
verifyIdentityIntent.putExtra(VerifyIdentityActivity.ADDRESS_EXTRA, recipient.getAddress());
|
||||
verifyIdentityIntent.putExtra(VerifyIdentityActivity.IDENTITY_EXTRA, new IdentityKeyParcelable(identityKey.getIdentityKey()));
|
||||
verifyIdentityIntent.putExtra(VerifyIdentityActivity.VERIFIED_EXTRA, identityKey.getVerifiedStatus() == IdentityDatabase.VerifiedStatus.VERIFIED);
|
||||
startActivity(verifyIdentityIntent);
|
||||
@ -483,8 +484,8 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
private class BlockClickedListener implements Preference.OnPreferenceClickListener {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
if (recipients.isBlocked()) handleUnblock();
|
||||
else handleBlock();
|
||||
if (recipient.isBlocked()) handleUnblock();
|
||||
else handleBlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -498,7 +499,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
.setPositiveButton(R.string.RecipientPreferenceActivity_block, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
setBlocked(recipients, true);
|
||||
setBlocked(recipient, true);
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
@ -512,13 +513,13 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
.setPositiveButton(R.string.RecipientPreferenceActivity_unblock, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
setBlocked(recipients, false);
|
||||
setBlocked(recipient, false);
|
||||
}
|
||||
}).show();
|
||||
}
|
||||
|
||||
private void setBlocked(final Recipients recipients, final boolean blocked) {
|
||||
recipients.setBlocked(blocked);
|
||||
private void setBlocked(final Recipient recipient, final boolean blocked) {
|
||||
recipient.setBlocked(blocked);
|
||||
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
@ -526,7 +527,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
||||
Context context = getActivity();
|
||||
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(context)
|
||||
.setBlocked(recipients, blocked);
|
||||
.setBlocked(recipient, blocked);
|
||||
|
||||
ApplicationContext.getInstance(context)
|
||||
.getJobManager()
|
||||
|
@ -39,7 +39,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.FileUtils;
|
||||
@ -60,9 +60,9 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
|
||||
{
|
||||
private static final String TAG = ShareActivity.class.getSimpleName();
|
||||
|
||||
public static final String EXTRA_THREAD_ID = "thread_id";
|
||||
public static final String EXTRA_ADDRESSES_MARSHALLED = "addresses";
|
||||
public static final String EXTRA_DISTRIBUTION_TYPE = "distribution_type";
|
||||
public static final String EXTRA_THREAD_ID = "thread_id";
|
||||
public static final String EXTRA_ADDRESS_MARSHALLED = "address_marshalled";
|
||||
public static final String EXTRA_DISTRIBUTION_TYPE = "distribution_type";
|
||||
|
||||
private final DynamicTheme dynamicTheme = new DynamicTheme ();
|
||||
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
|
||||
@ -165,25 +165,25 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateConversation(long threadId, Recipients recipients, int distributionType) {
|
||||
createConversation(threadId, recipients.getAddresses(), distributionType);
|
||||
public void onCreateConversation(long threadId, Recipient recipient, int distributionType) {
|
||||
createConversation(threadId, recipient.getAddress(), distributionType);
|
||||
}
|
||||
|
||||
private void handleResolvedMedia(Intent intent, boolean animate) {
|
||||
long threadId = intent.getLongExtra(EXTRA_THREAD_ID, -1);
|
||||
int distributionType = intent.getIntExtra(EXTRA_DISTRIBUTION_TYPE, -1);
|
||||
Address[] addresses = null;
|
||||
Address address = null;
|
||||
|
||||
if (intent.hasExtra(EXTRA_ADDRESSES_MARSHALLED)) {
|
||||
if (intent.hasExtra(EXTRA_ADDRESS_MARSHALLED)) {
|
||||
Parcel parcel = Parcel.obtain();
|
||||
byte[] marshalled = intent.getByteArrayExtra(EXTRA_ADDRESSES_MARSHALLED);
|
||||
byte[] marshalled = intent.getByteArrayExtra(EXTRA_ADDRESS_MARSHALLED);
|
||||
parcel.unmarshall(marshalled, 0, marshalled.length);
|
||||
parcel.setDataPosition(0);
|
||||
addresses = parcel.createTypedArray(Address.CREATOR);
|
||||
address = parcel.readParcelable(getClassLoader());
|
||||
parcel.recycle();
|
||||
}
|
||||
|
||||
boolean hasResolvedDestination = threadId != -1 && addresses != null && distributionType != -1;
|
||||
boolean hasResolvedDestination = threadId != -1 && address != null && distributionType != -1;
|
||||
|
||||
if (!hasResolvedDestination && animate) {
|
||||
ViewUtil.fadeIn(fragmentContainer, 300);
|
||||
@ -192,13 +192,13 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity
|
||||
fragmentContainer.setVisibility(View.VISIBLE);
|
||||
progressWheel.setVisibility(View.GONE);
|
||||
} else {
|
||||
createConversation(threadId, addresses, distributionType);
|
||||
createConversation(threadId, address, distributionType);
|
||||
}
|
||||
}
|
||||
|
||||
private void createConversation(long threadId, Address[] addresses, int distributionType) {
|
||||
private void createConversation(long threadId, Address address, int distributionType) {
|
||||
final Intent intent = getBaseShareIntent(ConversationActivity.class);
|
||||
intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, addresses);
|
||||
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, address);
|
||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
|
||||
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType);
|
||||
|
||||
|
@ -28,10 +28,9 @@ import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ListView;
|
||||
|
||||
|
||||
import org.thoughtcrime.securesms.database.loaders.ConversationListLoader;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.loaders.ConversationListLoader;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
/**
|
||||
* A fragment to select and share to open conversations
|
||||
@ -73,7 +72,7 @@ public class ShareFragment extends ListFragment implements LoaderManager.LoaderC
|
||||
if (v instanceof ShareListItem) {
|
||||
ShareListItem headerView = (ShareListItem) v;
|
||||
|
||||
handleCreateConversation(headerView.getThreadId(), headerView.getRecipients(),
|
||||
handleCreateConversation(headerView.getThreadId(), headerView.getRecipient(),
|
||||
headerView.getDistributionType());
|
||||
}
|
||||
}
|
||||
@ -84,8 +83,8 @@ public class ShareFragment extends ListFragment implements LoaderManager.LoaderC
|
||||
getLoaderManager().restartLoader(0, null, this);
|
||||
}
|
||||
|
||||
private void handleCreateConversation(long threadId, Recipients recipients, int distributionType) {
|
||||
listener.onCreateConversation(threadId, recipients, distributionType);
|
||||
private void handleCreateConversation(long threadId, Recipient recipient, int distributionType) {
|
||||
listener.onCreateConversation(threadId, recipient, distributionType);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -104,6 +103,6 @@ public class ShareFragment extends ListFragment implements LoaderManager.LoaderC
|
||||
}
|
||||
|
||||
public interface ConversationSelectedListener {
|
||||
public void onCreateConversation(long threadId, Recipients recipients, int distributionType);
|
||||
public void onCreateConversation(long threadId, Recipient recipient, int distributionType);
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,8 @@ import android.widget.RelativeLayout;
|
||||
import org.thoughtcrime.securesms.components.AvatarImageView;
|
||||
import org.thoughtcrime.securesms.components.FromTextView;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
|
||||
/**
|
||||
* A simple view to show the recipients of an open conversation
|
||||
@ -33,12 +34,12 @@ import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
* @author Jake McGinty
|
||||
*/
|
||||
public class ShareListItem extends RelativeLayout
|
||||
implements Recipients.RecipientsModifiedListener
|
||||
implements RecipientModifiedListener
|
||||
{
|
||||
private final static String TAG = ShareListItem.class.getSimpleName();
|
||||
|
||||
private Context context;
|
||||
private Recipients recipients;
|
||||
private Recipient recipient;
|
||||
private long threadId;
|
||||
private FromTextView fromView;
|
||||
|
||||
@ -59,24 +60,25 @@ public class ShareListItem extends RelativeLayout
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
this.fromView = (FromTextView) findViewById(R.id.from);
|
||||
this.contactPhotoImage = (AvatarImageView) findViewById(R.id.contact_photo_image);
|
||||
}
|
||||
|
||||
public void set(ThreadRecord thread) {
|
||||
this.recipients = thread.getRecipients();
|
||||
this.recipient = thread.getRecipient();
|
||||
this.threadId = thread.getThreadId();
|
||||
this.distributionType = thread.getDistributionType();
|
||||
|
||||
this.recipients.addListener(this);
|
||||
this.fromView.setText(recipients);
|
||||
this.recipient.addListener(this);
|
||||
this.fromView.setText(recipient);
|
||||
|
||||
setBackground();
|
||||
this.contactPhotoImage.setAvatar(this.recipients, false);
|
||||
this.contactPhotoImage.setAvatar(this.recipient, false);
|
||||
}
|
||||
|
||||
public void unbind() {
|
||||
if (this.recipients != null) this.recipients.removeListener(this);
|
||||
if (this.recipient != null) this.recipient.removeListener(this);
|
||||
}
|
||||
|
||||
private void setBackground() {
|
||||
@ -88,8 +90,8 @@ public class ShareListItem extends RelativeLayout
|
||||
drawables.recycle();
|
||||
}
|
||||
|
||||
public Recipients getRecipients() {
|
||||
return recipients;
|
||||
public Recipient getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
public long getThreadId() {
|
||||
@ -101,12 +103,12 @@ public class ShareListItem extends RelativeLayout
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModified(final Recipients recipients) {
|
||||
public void onModified(final Recipient recipient) {
|
||||
handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
fromView.setText(recipients);
|
||||
contactPhotoImage.setAvatar(recipients, false);
|
||||
fromView.setText(recipient);
|
||||
contactPhotoImage.setAvatar(recipient, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -12,8 +12,8 @@ import android.widget.Toast;
|
||||
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.Rfc5724Uri;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
@ -47,13 +47,13 @@ public class SmsSendtoActivity extends Activity {
|
||||
nextIntent.putExtra(ConversationActivity.TEXT_EXTRA, destination.getBody());
|
||||
Toast.makeText(this, R.string.ConversationActivity_specify_recipient, Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(this, new Address[] {Address.fromExternal(this, destination.getDestination())}, true);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipients);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(this, Address.fromExternal(this, destination.getDestination()), true);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(this).getThreadIdIfExistsFor(recipient);
|
||||
|
||||
nextIntent = new Intent(this, ConversationActivity.class);
|
||||
nextIntent.putExtra(ConversationActivity.TEXT_EXTRA, destination.getBody());
|
||||
nextIntent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
|
||||
nextIntent.putExtra(ConversationActivity.ADDRESSES_EXTRA, recipients.getAddresses());
|
||||
nextIntent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.getAddress());
|
||||
}
|
||||
return nextIntent;
|
||||
}
|
||||
|
@ -74,6 +74,7 @@ import org.thoughtcrime.securesms.qr.ScanListener;
|
||||
import org.thoughtcrime.securesms.qr.ScanningThread;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.util.DynamicLanguage;
|
||||
import org.thoughtcrime.securesms.util.DynamicTheme;
|
||||
import org.thoughtcrime.securesms.util.IdentityUtil;
|
||||
@ -96,7 +97,7 @@ import static org.whispersystems.libsignal.SessionCipher.SESSION_LOCK;
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*/
|
||||
public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity implements Recipient.RecipientModifiedListener, ScanListener, View.OnClickListener {
|
||||
public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity implements RecipientModifiedListener, ScanListener, View.OnClickListener {
|
||||
|
||||
private static final String TAG = VerifyIdentityActivity.class.getSimpleName();
|
||||
|
||||
@ -191,7 +192,7 @@ public class VerifyIdentityActivity extends PassphraseRequiredActionBarActivity
|
||||
}
|
||||
}
|
||||
|
||||
public static class VerifyDisplayFragment extends Fragment implements Recipient.RecipientModifiedListener, CompoundButton.OnCheckedChangeListener {
|
||||
public static class VerifyDisplayFragment extends Fragment implements RecipientModifiedListener, CompoundButton.OnCheckedChangeListener {
|
||||
|
||||
public static final String REMOTE_ADDRESS = "remote_address";
|
||||
public static final String REMOTE_NUMBER = "remote_number";
|
||||
|
@ -14,8 +14,6 @@ import org.thoughtcrime.securesms.color.MaterialColor;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhotoFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
public class AvatarImageView extends ImageView {
|
||||
|
||||
@ -37,31 +35,25 @@ public class AvatarImageView extends ImageView {
|
||||
}
|
||||
}
|
||||
|
||||
public void setAvatar(final @Nullable Recipients recipients, boolean quickContactEnabled) {
|
||||
if (recipients != null) {
|
||||
MaterialColor backgroundColor = recipients.getColor();
|
||||
setImageDrawable(recipients.getContactPhoto().asDrawable(getContext(), backgroundColor.toConversationColor(getContext()), inverted));
|
||||
setAvatarClickHandler(recipients, quickContactEnabled);
|
||||
public void setAvatar(final @Nullable Recipient recipient, boolean quickContactEnabled) {
|
||||
if (recipient != null) {
|
||||
MaterialColor backgroundColor = recipient.getColor();
|
||||
setImageDrawable(recipient.getContactPhoto().asDrawable(getContext(), backgroundColor.toConversationColor(getContext()), inverted));
|
||||
setAvatarClickHandler(recipient, quickContactEnabled);
|
||||
} else {
|
||||
setImageDrawable(ContactPhotoFactory.getDefaultContactPhoto(null).asDrawable(getContext(), ContactColors.UNKNOWN_COLOR.toConversationColor(getContext()), inverted));
|
||||
setOnClickListener(null);
|
||||
}
|
||||
}
|
||||
|
||||
public void setAvatar(@Nullable Recipient recipient, boolean quickContactEnabled) {
|
||||
setAvatar(RecipientFactory.getRecipientsFor(getContext(), recipient, true), quickContactEnabled);
|
||||
}
|
||||
|
||||
private void setAvatarClickHandler(final Recipients recipients, boolean quickContactEnabled) {
|
||||
if (!recipients.isGroupRecipient() && quickContactEnabled) {
|
||||
private void setAvatarClickHandler(final Recipient recipient, boolean quickContactEnabled) {
|
||||
if (!recipient.isGroupRecipient() && quickContactEnabled) {
|
||||
setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Recipient recipient = recipients.getPrimaryRecipient();
|
||||
|
||||
if (recipient != null && recipient.getContactUri() != null) {
|
||||
if (recipient.getContactUri() != null) {
|
||||
ContactsContract.QuickContact.showQuickContact(getContext(), AvatarImageView.this, recipient.getContactUri(), ContactsContract.QuickContact.MODE_LARGE, null);
|
||||
} else if (recipient != null) {
|
||||
} else {
|
||||
final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
|
||||
if (recipient.getAddress().isEmail()) {
|
||||
intent.putExtra(ContactsContract.Intents.Insert.EMAIL, recipient.getAddress().toEmailString());
|
||||
|
@ -11,8 +11,6 @@ import android.util.AttributeSet;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
public class FromTextView extends EmojiTextView {
|
||||
|
||||
@ -27,17 +25,13 @@ public class FromTextView extends EmojiTextView {
|
||||
}
|
||||
|
||||
public void setText(Recipient recipient) {
|
||||
setText(RecipientFactory.getRecipientsFor(getContext(), recipient, true));
|
||||
setText(recipient, true);
|
||||
}
|
||||
|
||||
public void setText(Recipients recipients) {
|
||||
setText(recipients, true);
|
||||
}
|
||||
|
||||
public void setText(Recipients recipients, boolean read) {
|
||||
public void setText(Recipient recipient, boolean read) {
|
||||
int attributes[] = new int[]{R.attr.conversation_list_item_count_color};
|
||||
TypedArray colors = getContext().obtainStyledAttributes(attributes);
|
||||
String fromString = recipients.toShortString();
|
||||
String fromString = recipient.toShortString();
|
||||
|
||||
int typeface;
|
||||
|
||||
@ -55,9 +49,9 @@ public class FromTextView extends EmojiTextView {
|
||||
|
||||
setText(builder);
|
||||
|
||||
if (recipients.isBlocked()) setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_block_grey600_18dp, 0, 0, 0);
|
||||
else if (recipients.isMuted()) setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_volume_off_grey600_18dp, 0, 0, 0);
|
||||
else setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||
if (recipient.isBlocked()) setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_block_grey600_18dp, 0, 0, 0);
|
||||
else if (recipient.isMuted()) setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_volume_off_grey600_18dp, 0, 0, 0);
|
||||
else setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,7 +19,6 @@ package org.thoughtcrime.securesms.components;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
@ -33,9 +32,7 @@ import org.thoughtcrime.securesms.contacts.RecipientsEditor;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients.RecipientsModifiedListener;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -47,7 +44,7 @@ import java.util.StringTokenizer;
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*/
|
||||
public class PushRecipientsPanel extends RelativeLayout implements RecipientsModifiedListener {
|
||||
public class PushRecipientsPanel extends RelativeLayout implements RecipientModifiedListener {
|
||||
private final String TAG = PushRecipientsPanel.class.getSimpleName();
|
||||
private RecipientsPanelChangedListener panelChangeListener;
|
||||
|
||||
@ -71,14 +68,9 @@ public class PushRecipientsPanel extends RelativeLayout implements RecipientsMod
|
||||
initialize();
|
||||
}
|
||||
|
||||
public Recipients getRecipients() throws RecipientFormattingException {
|
||||
String rawText = recipientsText.getText().toString();
|
||||
Recipients recipients = getRecipientsFromString(getContext(), rawText, true);
|
||||
|
||||
if (recipients == null || recipients.isEmpty())
|
||||
throw new RecipientFormattingException("Recipient List Is Empty!");
|
||||
|
||||
return recipients;
|
||||
public List<Recipient> getRecipients() {
|
||||
String rawText = recipientsText.getText().toString();
|
||||
return getRecipientsFromString(getContext(), rawText, true);
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
@ -104,15 +96,14 @@ public class PushRecipientsPanel extends RelativeLayout implements RecipientsMod
|
||||
}
|
||||
|
||||
private void initRecipientsEditor() {
|
||||
Recipients recipients;
|
||||
recipientsText = (RecipientsEditor)findViewById(R.id.recipients_text);
|
||||
|
||||
try {
|
||||
recipients = getRecipients();
|
||||
} catch (RecipientFormattingException e) {
|
||||
recipients = RecipientFactory.getRecipientsFor(getContext(), new LinkedList<Recipient>(), true);
|
||||
this.recipientsText = (RecipientsEditor)findViewById(R.id.recipients_text);
|
||||
|
||||
List<Recipient> recipients = getRecipients();
|
||||
|
||||
for (Recipient recipient : recipients) {
|
||||
recipient.addListener(this);
|
||||
}
|
||||
recipients.addListener(this);
|
||||
|
||||
recipientsText.setAdapter(new RecipientsAdapter(this.getContext()));
|
||||
recipientsText.populate(recipients);
|
||||
@ -122,32 +113,27 @@ public class PushRecipientsPanel extends RelativeLayout implements RecipientsMod
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
|
||||
if (panelChangeListener != null) {
|
||||
try {
|
||||
panelChangeListener.onRecipientsPanelUpdate(getRecipients());
|
||||
} catch (RecipientFormattingException rfe) {
|
||||
panelChangeListener.onRecipientsPanelUpdate(null);
|
||||
}
|
||||
panelChangeListener.onRecipientsPanelUpdate(getRecipients());
|
||||
}
|
||||
recipientsText.setText("");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private @Nullable Recipients getRecipientsFromString(Context context, @NonNull String rawText, boolean asynchronous) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(rawText, ",");
|
||||
List<Address> addresses = new LinkedList<>();
|
||||
private @NonNull List<Recipient> getRecipientsFromString(Context context, @NonNull String rawText, boolean asynchronous) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(rawText, ",");
|
||||
List<Recipient> recipients = new LinkedList<>();
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
String token = tokenizer.nextToken().trim();
|
||||
|
||||
if (!TextUtils.isEmpty(token)) {
|
||||
if (hasBracketedNumber(token)) addresses.add(Address.fromExternal(context, parseBracketedNumber(token)));
|
||||
else addresses.add(Address.fromExternal(context, token));
|
||||
if (hasBracketedNumber(token)) recipients.add(RecipientFactory.getRecipientFor(context, Address.fromExternal(context, parseBracketedNumber(token)), asynchronous));
|
||||
else recipients.add(RecipientFactory.getRecipientFor(context, Address.fromExternal(context, token), asynchronous));
|
||||
}
|
||||
}
|
||||
|
||||
if (addresses.size() == 0) return null;
|
||||
else return RecipientFactory.getRecipientsFor(context, addresses.toArray(new Address[0]), asynchronous);
|
||||
return recipients;
|
||||
}
|
||||
|
||||
private boolean hasBracketedNumber(String recipient) {
|
||||
@ -166,24 +152,20 @@ public class PushRecipientsPanel extends RelativeLayout implements RecipientsMod
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModified(Recipients recipients) {
|
||||
recipientsText.populate(recipients);
|
||||
public void onModified(Recipient recipient) {
|
||||
recipientsText.populate(getRecipients());
|
||||
}
|
||||
|
||||
private class FocusChangedListener implements View.OnFocusChangeListener {
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (!hasFocus && (panelChangeListener != null)) {
|
||||
try {
|
||||
panelChangeListener.onRecipientsPanelUpdate(getRecipients());
|
||||
} catch (RecipientFormattingException rfe) {
|
||||
panelChangeListener.onRecipientsPanelUpdate(null);
|
||||
}
|
||||
panelChangeListener.onRecipientsPanelUpdate(getRecipients());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface RecipientsPanelChangedListener {
|
||||
public void onRecipientsPanelUpdate(Recipients recipients);
|
||||
public void onRecipientsPanelUpdate(List<Recipient> recipients);
|
||||
}
|
||||
|
||||
}
|
@ -8,22 +8,22 @@ import android.view.View.OnClickListener;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
public class InviteReminder extends Reminder {
|
||||
|
||||
public InviteReminder(final @NonNull Context context,
|
||||
final @NonNull Recipients recipients)
|
||||
final @NonNull Recipient recipient)
|
||||
{
|
||||
super(context.getString(R.string.reminder_header_invite_title),
|
||||
context.getString(R.string.reminder_header_invite_text, recipients.toShortString()));
|
||||
context.getString(R.string.reminder_header_invite_text, recipient.toShortString()));
|
||||
|
||||
setDismissListener(new OnClickListener() {
|
||||
@Override public void onClick(View v) {
|
||||
new AsyncTask<Void,Void,Void>() {
|
||||
|
||||
@Override protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(context).setSeenInviteReminder(recipients, true);
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(context).setSeenInviteReminder(recipient, true);
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
|
@ -44,6 +44,7 @@ import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhotoFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.service.WebRtcCallService;
|
||||
import org.thoughtcrime.securesms.util.VerifySpan;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
@ -57,7 +58,7 @@ import org.whispersystems.libsignal.IdentityKey;
|
||||
* @author Moxie Marlinspike
|
||||
*
|
||||
*/
|
||||
public class WebRtcCallScreen extends FrameLayout implements Recipient.RecipientModifiedListener {
|
||||
public class WebRtcCallScreen extends FrameLayout implements RecipientModifiedListener {
|
||||
|
||||
private static final String TAG = WebRtcCallScreen.class.getSimpleName();
|
||||
|
||||
|
@ -11,12 +11,12 @@ import android.widget.TextView;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.AvatarImageView;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientsFormatter;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
||||
public class ContactSelectionListItem extends LinearLayout implements Recipients.RecipientsModifiedListener {
|
||||
public class ContactSelectionListItem extends LinearLayout implements RecipientModifiedListener {
|
||||
|
||||
private AvatarImageView contactPhotoImage;
|
||||
private TextView numberView;
|
||||
@ -24,9 +24,9 @@ public class ContactSelectionListItem extends LinearLayout implements Recipients
|
||||
private TextView labelView;
|
||||
private CheckBox checkBox;
|
||||
|
||||
private long id;
|
||||
private String number;
|
||||
private Recipients recipients;
|
||||
private long id;
|
||||
private String number;
|
||||
private Recipient recipient;
|
||||
|
||||
public ContactSelectionListItem(Context context) {
|
||||
super(context);
|
||||
@ -53,24 +53,22 @@ public class ContactSelectionListItem extends LinearLayout implements Recipients
|
||||
this.number = number;
|
||||
|
||||
if (type == ContactsDatabase.NEW_TYPE) {
|
||||
this.recipients = null;
|
||||
this.recipient = null;
|
||||
this.contactPhotoImage.setAvatar(RecipientFactory.getRecipientFor(getContext(), Address.UNKNOWN, true), false);
|
||||
} else if (!TextUtils.isEmpty(number)) {
|
||||
Address address = Address.fromExternal(getContext(), number);
|
||||
this.recipients = RecipientFactory.getRecipientsFor(getContext(), new Address[] {address}, true);
|
||||
this.recipient = RecipientFactory.getRecipientFor(getContext(), address, true);
|
||||
|
||||
if (this.recipients.getPrimaryRecipient() != null &&
|
||||
this.recipients.getPrimaryRecipient().getName() != null)
|
||||
{
|
||||
name = this.recipients.getPrimaryRecipient().getName();
|
||||
if (this.recipient.getName() != null) {
|
||||
name = this.recipient.getName();
|
||||
}
|
||||
|
||||
this.recipients.addListener(this);
|
||||
this.recipient.addListener(this);
|
||||
}
|
||||
|
||||
this.nameView.setTextColor(color);
|
||||
this.numberView.setTextColor(color);
|
||||
this.contactPhotoImage.setAvatar(recipients, false);
|
||||
this.contactPhotoImage.setAvatar(recipient, false);
|
||||
|
||||
setText(type, name, number, label);
|
||||
|
||||
@ -83,9 +81,9 @@ public class ContactSelectionListItem extends LinearLayout implements Recipients
|
||||
}
|
||||
|
||||
public void unbind() {
|
||||
if (recipients != null) {
|
||||
recipients.removeListener(this);
|
||||
recipients = null;
|
||||
if (recipient != null) {
|
||||
recipient.removeListener(this);
|
||||
recipient = null;
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,13 +115,13 @@ public class ContactSelectionListItem extends LinearLayout implements Recipients
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModified(final Recipients recipients) {
|
||||
if (this.recipients == recipients) {
|
||||
public void onModified(final Recipient recipient) {
|
||||
if (this.recipient == recipient) {
|
||||
this.contactPhotoImage.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
contactPhotoImage.setAvatar(recipients, false);
|
||||
nameView.setText(recipients.toShortString());
|
||||
contactPhotoImage.setAvatar(recipient, false);
|
||||
nameView.setText(recipient.toShortString());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.DirectoryHelper;
|
||||
import org.thoughtcrime.securesms.util.DirectoryHelper.UserCapabilities.Capability;
|
||||
import org.thoughtcrime.securesms.util.NumberUtil;
|
||||
@ -103,12 +103,10 @@ public class ContactsCursorLoader extends CursorLoader {
|
||||
ContactsDatabase.LABEL_COLUMN,
|
||||
ContactsDatabase.CONTACT_TYPE_COLUMN});
|
||||
while (cursor.moveToNext()) {
|
||||
final String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_COLUMN));
|
||||
final Recipients recipients = RecipientFactory.getRecipientsFor(getContext(), new Address[]{Address.fromExternal(getContext(), number)}, true);
|
||||
final String number = cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NUMBER_COLUMN));
|
||||
final Recipient recipient = RecipientFactory.getRecipientFor(getContext(), Address.fromExternal(getContext(), number), true);
|
||||
|
||||
if (DirectoryHelper.getUserCapabilities(getContext(), recipients)
|
||||
.getTextCapability() != Capability.SUPPORTED)
|
||||
{
|
||||
if (DirectoryHelper.getUserCapabilities(getContext(), recipient).getTextCapability() != Capability.SUPPORTED) {
|
||||
matrix.addRow(new Object[]{cursor.getLong(cursor.getColumnIndexOrThrow(ContactsDatabase.ID_COLUMN)),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(ContactsDatabase.NAME_COLUMN)),
|
||||
number,
|
||||
|
@ -30,16 +30,12 @@ import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.MultiAutoCompleteTextView;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientsFormatter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -205,10 +201,10 @@ public class RecipientsEditor extends AppCompatMultiAutoCompleteTextView {
|
||||
return s;
|
||||
}
|
||||
|
||||
public void populate(Recipients list) {
|
||||
public void populate(List<Recipient> list) {
|
||||
SpannableStringBuilder sb = new SpannableStringBuilder();
|
||||
|
||||
for (Recipient c : list.getRecipientsList()) {
|
||||
for (Recipient c : list) {
|
||||
if (sb.length() != 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
|
@ -96,20 +96,14 @@ public class Address implements Parcelable, Comparable<Address> {
|
||||
return Util.join(escapedAddresses, delimiter + "");
|
||||
}
|
||||
|
||||
public static Address[] fromParcelable(Parcelable[] parcelables) {
|
||||
Address[] addresses = new Address[parcelables.length];
|
||||
|
||||
for (int i=0;i<parcelables.length;i++) {
|
||||
addresses[i] = (Address)parcelables[i];
|
||||
}
|
||||
|
||||
return addresses;
|
||||
}
|
||||
|
||||
public boolean isGroup() {
|
||||
return GroupUtil.isEncodedGroup(address);
|
||||
}
|
||||
|
||||
public boolean isMmsGroup() {
|
||||
return GroupUtil.isMmsGroup(address);
|
||||
}
|
||||
|
||||
public boolean isEmail() {
|
||||
return NumberUtil.isValidEmail(address);
|
||||
}
|
||||
@ -204,9 +198,9 @@ public class Address implements Parcelable, Comparable<Address> {
|
||||
}
|
||||
|
||||
public String format(@Nullable String number) {
|
||||
if (number == null) return "Unknown";
|
||||
if (number.startsWith("__textsecure_group__!")) return number;
|
||||
if (ALPHA_PATTERN.matcher(number).find()) return number.trim();
|
||||
if (number == null) return "Unknown";
|
||||
if (GroupUtil.isEncodedGroup(number)) return number;
|
||||
if (ALPHA_PATTERN.matcher(number).find()) return number.trim();
|
||||
|
||||
String bareNumber = number.replaceAll("[^0-9+]", "");
|
||||
|
||||
|
@ -28,8 +28,6 @@ import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.google.i18n.phonenumbers.NumberParseException;
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||
import com.google.i18n.phonenumbers.Phonenumber;
|
||||
@ -41,10 +39,10 @@ import org.thoughtcrime.securesms.crypto.DecryptingPartInputStream;
|
||||
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.thoughtcrime.securesms.util.DelimiterUtil;
|
||||
import org.thoughtcrime.securesms.util.Hex;
|
||||
import org.thoughtcrime.securesms.util.JsonUtils;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
@ -56,12 +54,12 @@ import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class DatabaseFactory {
|
||||
@ -102,7 +100,8 @@ public class DatabaseFactory {
|
||||
private static final int INTRODUCED_IDENTITY_TIMESTAMP = 35;
|
||||
private static final int SANIFY_ATTACHMENT_DOWNLOAD = 36;
|
||||
private static final int NO_MORE_CANONICAL_ADDRESS_DATABASE = 37;
|
||||
private static final int DATABASE_VERSION = 37;
|
||||
private static final int NO_MORE_RECIPIENTS_PLURAL = 38;
|
||||
private static final int DATABASE_VERSION = 38;
|
||||
|
||||
private static final String DATABASE_NAME = "messages.db";
|
||||
private static final Object lock = new Object();
|
||||
@ -117,7 +116,6 @@ public class DatabaseFactory {
|
||||
private final AttachmentDatabase attachments;
|
||||
private final MediaDatabase media;
|
||||
private final ThreadDatabase thread;
|
||||
private final MmsAddressDatabase mmsAddress;
|
||||
private final MmsSmsDatabase mmsSmsDatabase;
|
||||
private final IdentityDatabase identityDatabase;
|
||||
private final DraftDatabase draftDatabase;
|
||||
@ -163,10 +161,6 @@ public class DatabaseFactory {
|
||||
return getInstance(context).media;
|
||||
}
|
||||
|
||||
public static MmsAddressDatabase getMmsAddressDatabase(Context context) {
|
||||
return getInstance(context).mmsAddress;
|
||||
}
|
||||
|
||||
public static IdentityDatabase getIdentityDatabase(Context context) {
|
||||
return getInstance(context).identityDatabase;
|
||||
}
|
||||
@ -199,7 +193,6 @@ public class DatabaseFactory {
|
||||
this.attachments = new AttachmentDatabase(context, databaseHelper);
|
||||
this.media = new MediaDatabase(context, databaseHelper);
|
||||
this.thread = new ThreadDatabase(context, databaseHelper);
|
||||
this.mmsAddress = new MmsAddressDatabase(context, databaseHelper);
|
||||
this.mmsSmsDatabase = new MmsSmsDatabase(context, databaseHelper);
|
||||
this.identityDatabase = new IdentityDatabase(context, databaseHelper);
|
||||
this.draftDatabase = new DraftDatabase(context, databaseHelper);
|
||||
@ -218,7 +211,6 @@ public class DatabaseFactory {
|
||||
this.mms.reset(databaseHelper);
|
||||
this.attachments.reset(databaseHelper);
|
||||
this.thread.reset(databaseHelper);
|
||||
this.mmsAddress.reset(databaseHelper);
|
||||
this.mmsSmsDatabase.reset(databaseHelper);
|
||||
this.identityDatabase.reset(databaseHelper);
|
||||
this.draftDatabase.reset(databaseHelper);
|
||||
@ -533,7 +525,6 @@ public class DatabaseFactory {
|
||||
db.execSQL(MmsDatabase.CREATE_TABLE);
|
||||
db.execSQL(AttachmentDatabase.CREATE_TABLE);
|
||||
db.execSQL(ThreadDatabase.CREATE_TABLE);
|
||||
db.execSQL(MmsAddressDatabase.CREATE_TABLE);
|
||||
db.execSQL(IdentityDatabase.CREATE_TABLE);
|
||||
db.execSQL(DraftDatabase.CREATE_TABLE);
|
||||
db.execSQL(PushDatabase.CREATE_TABLE);
|
||||
@ -544,7 +535,6 @@ public class DatabaseFactory {
|
||||
executeStatements(db, MmsDatabase.CREATE_INDEXS);
|
||||
executeStatements(db, AttachmentDatabase.CREATE_INDEXS);
|
||||
executeStatements(db, ThreadDatabase.CREATE_INDEXS);
|
||||
executeStatements(db, MmsAddressDatabase.CREATE_INDEXS);
|
||||
executeStatements(db, DraftDatabase.CREATE_INDEXS);
|
||||
executeStatements(db, GroupDatabase.CREATE_INDEXS);
|
||||
}
|
||||
@ -1209,6 +1199,80 @@ public class DatabaseFactory {
|
||||
|
||||
}
|
||||
|
||||
if (oldVersion < NO_MORE_RECIPIENTS_PLURAL) {
|
||||
db.execSQL("ALTER TABLE groups ADD COLUMN mms INTEGER DEFAULT 0");
|
||||
|
||||
Cursor cursor = db.query("thread", new String[] {"_id", "recipient_ids"}, null, null, null, null, null);
|
||||
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
long threadId = cursor.getLong(0);
|
||||
String addressListString = cursor.getString(1);
|
||||
String[] addressList = DelimiterUtil.split(addressListString, ' ');
|
||||
|
||||
if (addressList.length == 1) {
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put("recipient_ids", DelimiterUtil.unescape(addressListString, ' '));
|
||||
db.update("thread", contentValues, "_id = ?", new String[] {String.valueOf(threadId)});
|
||||
} else {
|
||||
byte[] groupId = new byte[16];
|
||||
List<String> members = new LinkedList<>();
|
||||
|
||||
new SecureRandom().nextBytes(groupId);
|
||||
|
||||
for (String address : addressList) {
|
||||
members.add(DelimiterUtil.escape(DelimiterUtil.unescape(address, ' '), ','));
|
||||
}
|
||||
|
||||
String encodedGroupId = "__signal_mms_group__!" + Hex.toStringCondensed(groupId);
|
||||
ContentValues groupValues = new ContentValues();
|
||||
ContentValues threadValues = new ContentValues();
|
||||
|
||||
groupValues.put("group_id", encodedGroupId);
|
||||
groupValues.put("members", Util.join(members, ","));
|
||||
groupValues.put("mms", 1);
|
||||
|
||||
threadValues.put("recipient_ids", encodedGroupId);
|
||||
|
||||
db.insert("groups", null, groupValues);
|
||||
db.update("thread", threadValues, "_id = ?", new String[] {String.valueOf(threadId)});
|
||||
db.update("recipient_preferences", threadValues, "recipient_ids = ?", new String[] {addressListString});
|
||||
}
|
||||
}
|
||||
|
||||
if (cursor != null) cursor.close();
|
||||
|
||||
cursor = db.query("recipient_preferences", new String[] {"_id", "recipient_ids"}, null, null, null, null, null);
|
||||
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
long id = cursor.getLong(0);
|
||||
String addressListString = cursor.getString(1);
|
||||
String[] addressList = DelimiterUtil.split(addressListString, ' ');
|
||||
|
||||
if (addressList.length == 1) {
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put("recipient_ids", DelimiterUtil.unescape(addressListString, ' '));
|
||||
db.update("recipient_preferences", contentValues, "_id = ?", new String[] {String.valueOf(id)});
|
||||
} else {
|
||||
Log.w(TAG, "Found preferences for MMS thread that appears to be gone: " + addressListString);
|
||||
db.delete("recipient_preferences", "_id = ?", new String[] {String.valueOf(id)});
|
||||
}
|
||||
}
|
||||
|
||||
if (cursor != null) cursor.close();
|
||||
|
||||
cursor = db.rawQuery("SELECT mms._id, thread.recipient_ids FROM mms, thread WHERE mms.address IS NULL AND mms.thread_id = thread._id", null);
|
||||
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
long id = cursor.getLong(0);
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
|
||||
contentValues.put("address", cursor.getString(1));
|
||||
db.update("mms", contentValues, "_id = ?", new String[] {String.valueOf(id)});
|
||||
}
|
||||
|
||||
if (cursor != null) cursor.close();
|
||||
}
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ import android.support.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
@ -23,6 +22,7 @@ import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPoin
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
@ -45,6 +45,7 @@ public class GroupDatabase extends Database {
|
||||
private static final String AVATAR_DIGEST = "avatar_digest";
|
||||
private static final String TIMESTAMP = "timestamp";
|
||||
private static final String ACTIVE = "active";
|
||||
private static final String MMS = "mms";
|
||||
|
||||
public static final String CREATE_TABLE =
|
||||
"CREATE TABLE " + TABLE_NAME +
|
||||
@ -59,7 +60,8 @@ public class GroupDatabase extends Database {
|
||||
AVATAR_RELAY + " TEXT, " +
|
||||
TIMESTAMP + " INTEGER, " +
|
||||
ACTIVE + " INTEGER DEFAULT 1, " +
|
||||
AVATAR_DIGEST + " BLOB);";
|
||||
AVATAR_DIGEST + " BLOB, " +
|
||||
MMS + " INTEGER DEFAULT 0);";
|
||||
|
||||
public static final String[] CREATE_INDEXS = {
|
||||
"CREATE UNIQUE INDEX IF NOT EXISTS group_id_index ON " + TABLE_NAME + " (" + GROUP_ID + ");",
|
||||
@ -69,10 +71,10 @@ public class GroupDatabase extends Database {
|
||||
super(context, databaseHelper);
|
||||
}
|
||||
|
||||
public @Nullable GroupRecord getGroup(byte[] groupId) {
|
||||
public @Nullable GroupRecord getGroup(String groupId) {
|
||||
@SuppressLint("Recycle")
|
||||
Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, GROUP_ID + " = ?",
|
||||
new String[] {GroupUtil.getEncodedId(groupId)},
|
||||
new String[] {groupId},
|
||||
null, null, null);
|
||||
|
||||
Reader reader = new Reader(cursor);
|
||||
@ -82,7 +84,7 @@ public class GroupDatabase extends Database {
|
||||
return record;
|
||||
}
|
||||
|
||||
public boolean isUnknownGroup(byte[] groupId) {
|
||||
public boolean isUnknownGroup(String groupId) {
|
||||
return getGroup(groupId) == null;
|
||||
}
|
||||
|
||||
@ -94,12 +96,32 @@ public class GroupDatabase extends Database {
|
||||
return new Reader(cursor);
|
||||
}
|
||||
|
||||
public String getOrCreateGroupForMembers(List<Address> members, boolean mms) {
|
||||
Collections.sort(members);
|
||||
|
||||
Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {GROUP_ID},
|
||||
MEMBERS + " = ? AND " + MMS + " = ?",
|
||||
new String[] {Address.toSerializedList(members, ','), mms ? "1" : "0"},
|
||||
null, null, null);
|
||||
try {
|
||||
if (cursor != null && cursor.moveToNext()) {
|
||||
return cursor.getString(cursor.getColumnIndexOrThrow(GROUP_ID));
|
||||
} else {
|
||||
String groupId = GroupUtil.getEncodedId(allocateGroupId(), mms);
|
||||
create(groupId, null, members, null, null);
|
||||
return groupId;
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null) cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
public Reader getGroups() {
|
||||
Cursor cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, null, null, null, null, null, null);
|
||||
return new Reader(cursor);
|
||||
}
|
||||
|
||||
public @NonNull Recipients getGroupMembers(byte[] groupId, boolean includeSelf) {
|
||||
public @NonNull List<Recipient> getGroupMembers(String groupId, boolean includeSelf) {
|
||||
List<Address> members = getCurrentMembers(groupId);
|
||||
List<Recipient> recipients = new LinkedList<>();
|
||||
|
||||
@ -110,14 +132,16 @@ public class GroupDatabase extends Database {
|
||||
recipients.add(RecipientFactory.getRecipientFor(context, member, false));
|
||||
}
|
||||
|
||||
return RecipientFactory.getRecipientsFor(context, recipients, false);
|
||||
return recipients;
|
||||
}
|
||||
|
||||
public void create(byte[] groupId, String title, List<Address> members,
|
||||
SignalServiceAttachmentPointer avatar, String relay)
|
||||
public void create(@NonNull String groupId, @Nullable String title, @NonNull List<Address> members,
|
||||
@Nullable SignalServiceAttachmentPointer avatar, @Nullable String relay)
|
||||
{
|
||||
Collections.sort(members);
|
||||
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(GROUP_ID, GroupUtil.getEncodedId(groupId));
|
||||
contentValues.put(GROUP_ID, groupId);
|
||||
contentValues.put(TITLE, title);
|
||||
contentValues.put(MEMBERS, Address.toSerializedList(members, ','));
|
||||
|
||||
@ -131,13 +155,14 @@ public class GroupDatabase extends Database {
|
||||
contentValues.put(AVATAR_RELAY, relay);
|
||||
contentValues.put(TIMESTAMP, System.currentTimeMillis());
|
||||
contentValues.put(ACTIVE, 1);
|
||||
contentValues.put(MMS, GroupUtil.isMmsGroup(groupId));
|
||||
|
||||
databaseHelper.getWritableDatabase().insert(TABLE_NAME, null, contentValues);
|
||||
RecipientFactory.clearCache(context);
|
||||
notifyConversationListListeners();
|
||||
}
|
||||
|
||||
public void update(byte[] groupId, String title, SignalServiceAttachmentPointer avatar) {
|
||||
public void update(String groupId, String title, SignalServiceAttachmentPointer avatar) {
|
||||
ContentValues contentValues = new ContentValues();
|
||||
if (title != null) contentValues.put(TITLE, title);
|
||||
|
||||
@ -150,65 +175,67 @@ public class GroupDatabase extends Database {
|
||||
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues,
|
||||
GROUP_ID + " = ?",
|
||||
new String[] {GroupUtil.getEncodedId(groupId)});
|
||||
new String[] {groupId});
|
||||
|
||||
RecipientFactory.clearCache(context);
|
||||
notifyDatabaseListeners();
|
||||
notifyConversationListListeners();
|
||||
}
|
||||
|
||||
public void updateTitle(byte[] groupId, String title) {
|
||||
public void updateTitle(String groupId, String title) {
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(TITLE, title);
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
|
||||
new String[] {GroupUtil.getEncodedId(groupId)});
|
||||
new String[] {groupId});
|
||||
|
||||
RecipientFactory.clearCache(context);
|
||||
notifyDatabaseListeners();
|
||||
}
|
||||
|
||||
public void updateAvatar(byte[] groupId, Bitmap avatar) {
|
||||
public void updateAvatar(String groupId, Bitmap avatar) {
|
||||
updateAvatar(groupId, BitmapUtil.toByteArray(avatar));
|
||||
}
|
||||
|
||||
public void updateAvatar(byte[] groupId, byte[] avatar) {
|
||||
public void updateAvatar(String groupId, byte[] avatar) {
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(AVATAR, avatar);
|
||||
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contentValues, GROUP_ID + " = ?",
|
||||
new String[] {GroupUtil.getEncodedId(groupId)});
|
||||
new String[] {groupId});
|
||||
|
||||
RecipientFactory.clearCache(context);
|
||||
notifyDatabaseListeners();
|
||||
}
|
||||
|
||||
public void updateMembers(byte[] id, List<Address> members) {
|
||||
public void updateMembers(String groupId, List<Address> members) {
|
||||
Collections.sort(members);
|
||||
|
||||
ContentValues contents = new ContentValues();
|
||||
contents.put(MEMBERS, Address.toSerializedList(members, ','));
|
||||
contents.put(ACTIVE, 1);
|
||||
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?",
|
||||
new String[] {GroupUtil.getEncodedId(id)});
|
||||
new String[] {groupId});
|
||||
}
|
||||
|
||||
public void remove(byte[] id, Address source) {
|
||||
List<Address> currentMembers = getCurrentMembers(id);
|
||||
public void remove(String groupId, Address source) {
|
||||
List<Address> currentMembers = getCurrentMembers(groupId);
|
||||
currentMembers.remove(source);
|
||||
|
||||
ContentValues contents = new ContentValues();
|
||||
contents.put(MEMBERS, Address.toSerializedList(currentMembers, ','));
|
||||
|
||||
databaseHelper.getWritableDatabase().update(TABLE_NAME, contents, GROUP_ID + " = ?",
|
||||
new String[] {GroupUtil.getEncodedId(id)});
|
||||
new String[] {groupId});
|
||||
}
|
||||
|
||||
private List<Address> getCurrentMembers(byte[] id) {
|
||||
private List<Address> getCurrentMembers(String groupId) {
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
cursor = databaseHelper.getReadableDatabase().query(TABLE_NAME, new String[] {MEMBERS},
|
||||
GROUP_ID + " = ?",
|
||||
new String[] {GroupUtil.getEncodedId(id)},
|
||||
new String[] {groupId},
|
||||
null, null, null);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
@ -223,16 +250,16 @@ public class GroupDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isActive(byte[] id) {
|
||||
GroupRecord record = getGroup(id);
|
||||
public boolean isActive(String groupId) {
|
||||
GroupRecord record = getGroup(groupId);
|
||||
return record != null && record.isActive();
|
||||
}
|
||||
|
||||
public void setActive(byte[] id, boolean active) {
|
||||
public void setActive(String groupId, boolean active) {
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(ACTIVE, active ? 1 : 0);
|
||||
database.update(TABLE_NAME, values, GROUP_ID + " = ?", new String[] {GroupUtil.getEncodedId(id)});
|
||||
database.update(TABLE_NAME, values, GROUP_ID + " = ?", new String[] {groupId});
|
||||
}
|
||||
|
||||
|
||||
@ -273,7 +300,8 @@ public class GroupDatabase extends Database {
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(AVATAR_CONTENT_TYPE)),
|
||||
cursor.getString(cursor.getColumnIndexOrThrow(AVATAR_RELAY)),
|
||||
cursor.getInt(cursor.getColumnIndexOrThrow(ACTIVE)) == 1,
|
||||
cursor.getBlob(cursor.getColumnIndexOrThrow(AVATAR_DIGEST)));
|
||||
cursor.getBlob(cursor.getColumnIndexOrThrow(AVATAR_DIGEST)),
|
||||
cursor.getInt(cursor.getColumnIndexOrThrow(MMS)) == 1);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
@ -294,10 +322,11 @@ public class GroupDatabase extends Database {
|
||||
private final String avatarContentType;
|
||||
private final String relay;
|
||||
private final boolean active;
|
||||
private final boolean mms;
|
||||
|
||||
public GroupRecord(String id, String title, String members, byte[] avatar,
|
||||
long avatarId, byte[] avatarKey, String avatarContentType,
|
||||
String relay, boolean active, byte[] avatarDigest)
|
||||
String relay, boolean active, byte[] avatarDigest, boolean mms)
|
||||
{
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
@ -309,6 +338,7 @@ public class GroupDatabase extends Database {
|
||||
this.avatarContentType = avatarContentType;
|
||||
this.relay = relay;
|
||||
this.active = active;
|
||||
this.mms = mms;
|
||||
}
|
||||
|
||||
public byte[] getId() {
|
||||
@ -358,5 +388,9 @@ public class GroupDatabase extends Database {
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
public boolean isMms() {
|
||||
return mms;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,150 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2011 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.database;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import com.google.android.mms.pdu_alt.PduHeaders;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class MmsAddressDatabase extends Database {
|
||||
|
||||
private static final String TAG = MmsAddressDatabase.class.getSimpleName();
|
||||
|
||||
private static final String TABLE_NAME = "mms_addresses";
|
||||
private static final String ID = "_id";
|
||||
private static final String MMS_ID = "mms_id";
|
||||
private static final String TYPE = "type";
|
||||
private static final String ADDRESS = "address";
|
||||
private static final String ADDRESS_CHARSET = "address_charset";
|
||||
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
MMS_ID + " INTEGER, " + TYPE + " INTEGER, " + ADDRESS + " TEXT, " +
|
||||
ADDRESS_CHARSET + " INTEGER);";
|
||||
|
||||
public static final String[] CREATE_INDEXS = {
|
||||
"CREATE INDEX IF NOT EXISTS mms_addresses_mms_id_index ON " + TABLE_NAME + " (" + MMS_ID + ");",
|
||||
};
|
||||
|
||||
public MmsAddressDatabase(Context context, SQLiteOpenHelper databaseHelper) {
|
||||
super(context, databaseHelper);
|
||||
}
|
||||
|
||||
private void insertAddress(long messageId, int type, @NonNull Address value) {
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(MMS_ID, messageId);
|
||||
contentValues.put(TYPE, type);
|
||||
contentValues.put(ADDRESS, value.serialize());
|
||||
contentValues.put(ADDRESS_CHARSET, "UTF-8");
|
||||
database.insert(TABLE_NAME, null, contentValues);
|
||||
}
|
||||
|
||||
private void insertAddress(long messageId, int type, @NonNull List<Address> addresses) {
|
||||
for (Address address : addresses) {
|
||||
insertAddress(messageId, type, address);
|
||||
}
|
||||
}
|
||||
|
||||
public void insertAddressesForId(long messageId, MmsAddresses addresses) {
|
||||
if (addresses.getFrom() != null) {
|
||||
insertAddress(messageId, PduHeaders.FROM, addresses.getFrom());
|
||||
}
|
||||
|
||||
insertAddress(messageId, PduHeaders.TO, addresses.getTo());
|
||||
insertAddress(messageId, PduHeaders.CC, addresses.getCc());
|
||||
insertAddress(messageId, PduHeaders.BCC, addresses.getBcc());
|
||||
}
|
||||
|
||||
public MmsAddresses getAddressesForId(long messageId) {
|
||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||
Cursor cursor = null;
|
||||
Address from = null;
|
||||
List<Address> to = new LinkedList<>();
|
||||
List<Address> cc = new LinkedList<>();
|
||||
List<Address> bcc = new LinkedList<>();
|
||||
|
||||
try {
|
||||
cursor = database.query(TABLE_NAME, null, MMS_ID + " = ?", new String[] {messageId+""}, null, null, null);
|
||||
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
long type = cursor.getLong(cursor.getColumnIndexOrThrow(TYPE));
|
||||
Address address = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
||||
|
||||
if (type == PduHeaders.FROM) from = address;
|
||||
if (type == PduHeaders.TO) to.add(address);
|
||||
if (type == PduHeaders.CC) cc.add(address);
|
||||
if (type == PduHeaders.BCC) bcc.add(address);
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
}
|
||||
|
||||
return new MmsAddresses(from, to, cc, bcc);
|
||||
}
|
||||
|
||||
public List<Address> getAddressesListForId(long messageId) {
|
||||
List<Address> results = new LinkedList<>();
|
||||
MmsAddresses addresses = getAddressesForId(messageId);
|
||||
|
||||
if (addresses.getFrom() != null) {
|
||||
results.add(addresses.getFrom());
|
||||
}
|
||||
|
||||
results.addAll(addresses.getTo());
|
||||
results.addAll(addresses.getCc());
|
||||
results.addAll(addresses.getBcc());
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public Recipients getRecipientsForId(long messageId) {
|
||||
List<Address> addresses = getAddressesListForId(messageId);
|
||||
List<Recipient> results = new LinkedList<>();
|
||||
|
||||
for (Address address : addresses) {
|
||||
if (!PduHeaders.FROM_INSERT_ADDRESS_TOKEN_STR.equals(address.serialize())) {
|
||||
results.add(RecipientFactory.getRecipientFor(context, address, false));
|
||||
}
|
||||
}
|
||||
|
||||
return RecipientFactory.getRecipientsFor(context, results, false);
|
||||
}
|
||||
|
||||
|
||||
public void deleteAddressesForId(long messageId) {
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
database.delete(TABLE_NAME, MMS_ID + " = ?", new String[] {messageId+""});
|
||||
}
|
||||
|
||||
public void deleteAllAddresses() {
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
database.delete(TABLE_NAME, null, null);
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package org.thoughtcrime.securesms.database;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class MmsAddresses {
|
||||
|
||||
private final @Nullable Address from;
|
||||
private final @NonNull List<Address> to;
|
||||
private final @NonNull List<Address> cc;
|
||||
private final @NonNull List<Address> bcc;
|
||||
|
||||
public MmsAddresses(@Nullable Address from, @NonNull List<Address> to,
|
||||
@NonNull List<Address> cc, @NonNull List<Address> bcc)
|
||||
{
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
this.cc = cc;
|
||||
this.bcc = bcc;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<Address> getTo() {
|
||||
return to;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<Address> getCc() {
|
||||
return cc;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public List<Address> getBcc() {
|
||||
return bcc;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Address getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
public static MmsAddresses forTo(@NonNull List<Address> to) {
|
||||
return new MmsAddresses(null, to, new LinkedList<Address>(), new LinkedList<Address>());
|
||||
}
|
||||
|
||||
public static MmsAddresses forBcc(@NonNull List<Address> bcc) {
|
||||
return new MmsAddresses(null, new LinkedList<Address>(), new LinkedList<Address>(), bcc);
|
||||
}
|
||||
|
||||
public static MmsAddresses forFrom(@NonNull Address from) {
|
||||
return new MmsAddresses(from, new LinkedList<Address>(), new LinkedList<Address>(), new LinkedList<Address>());
|
||||
}
|
||||
}
|
@ -30,7 +30,6 @@ import android.util.Pair;
|
||||
|
||||
import com.google.android.mms.pdu_alt.NotificationInd;
|
||||
import com.google.android.mms.pdu_alt.PduHeaders;
|
||||
import com.google.i18n.phonenumbers.PhoneNumberUtil;
|
||||
|
||||
import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
@ -57,12 +56,10 @@ import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.JsonUtils;
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.jobqueue.JobManager;
|
||||
import org.whispersystems.libsignal.InvalidMessageException;
|
||||
@ -195,34 +192,30 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
}
|
||||
|
||||
public void incrementDeliveryReceiptCount(SyncMessageId messageId) {
|
||||
MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
Cursor cursor = null;
|
||||
boolean found = false;
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
Cursor cursor = null;
|
||||
boolean found = false;
|
||||
|
||||
try {
|
||||
cursor = database.query(TABLE_NAME, new String[] {ID, THREAD_ID, MESSAGE_BOX}, DATE_SENT + " = ?", new String[] {String.valueOf(messageId.getTimetamp())}, null, null, null, null);
|
||||
cursor = database.query(TABLE_NAME, new String[] {ID, THREAD_ID, MESSAGE_BOX, ADDRESS}, DATE_SENT + " = ?", new String[] {String.valueOf(messageId.getTimetamp())}, null, null, null, null);
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
if (Types.isOutgoingMessageType(cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX)))) {
|
||||
List<Address> addresses = addressDatabase.getAddressesListForId(cursor.getLong(cursor.getColumnIndexOrThrow(ID)));
|
||||
Address theirAddress = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
||||
Address ourAddress = messageId.getAddress();
|
||||
|
||||
for (Address theirAddress : addresses) {
|
||||
Address ourAddress = messageId.getAddress();
|
||||
if (ourAddress.equals(theirAddress) || theirAddress.isGroup()) {
|
||||
long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
||||
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
|
||||
|
||||
if (ourAddress.equals(theirAddress) || theirAddress.isGroup()) {
|
||||
long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
||||
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
|
||||
found = true;
|
||||
|
||||
found = true;
|
||||
database.execSQL("UPDATE " + TABLE_NAME + " SET " +
|
||||
RECEIPT_COUNT + " = " + RECEIPT_COUNT + " + 1 WHERE " + ID + " = ?",
|
||||
new String[] {String.valueOf(id)});
|
||||
|
||||
database.execSQL("UPDATE " + TABLE_NAME + " SET " +
|
||||
RECEIPT_COUNT + " = " + RECEIPT_COUNT + " + 1 WHERE " + ID + " = ?",
|
||||
new String[] {String.valueOf(id)});
|
||||
|
||||
DatabaseFactory.getThreadDatabase(context).update(threadId, false);
|
||||
notifyConversationListeners(threadId);
|
||||
}
|
||||
DatabaseFactory.getThreadDatabase(context).update(threadId, false);
|
||||
notifyConversationListeners(threadId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -257,66 +250,20 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
|
||||
private long getThreadIdFor(IncomingMediaMessage retrieved) throws RecipientFormattingException, MmsException {
|
||||
if (retrieved.getGroupId() != null) {
|
||||
Recipients groupRecipients = RecipientFactory.getRecipientsFor(context, new Address[] {retrieved.getGroupId()}, true);
|
||||
Recipient groupRecipients = RecipientFactory.getRecipientFor(context, retrieved.getGroupId(), true);
|
||||
return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipients);
|
||||
}
|
||||
|
||||
String localNumber;
|
||||
Set<Address> group = new HashSet<>();
|
||||
|
||||
if (retrieved.getAddresses().getFrom() == null) {
|
||||
throw new MmsException("FROM value in PduHeaders did not exist.");
|
||||
}
|
||||
|
||||
group.add(retrieved.getAddresses().getFrom());
|
||||
|
||||
if (TextSecurePreferences.isPushRegistered(context)) {
|
||||
localNumber = TextSecurePreferences.getLocalNumber(context);
|
||||
} else {
|
||||
localNumber = ServiceUtil.getTelephonyManager(context).getLine1Number();
|
||||
Recipient sender = RecipientFactory.getRecipientFor(context, retrieved.getFrom(), true);
|
||||
return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(sender);
|
||||
}
|
||||
|
||||
for (Address cc : retrieved.getAddresses().getCc()) {
|
||||
PhoneNumberUtil.MatchType match;
|
||||
|
||||
if (localNumber == null) match = PhoneNumberUtil.MatchType.NO_MATCH;
|
||||
else match = PhoneNumberUtil.getInstance().isNumberMatch(localNumber, cc.serialize());
|
||||
|
||||
if (match == PhoneNumberUtil.MatchType.NO_MATCH ||
|
||||
match == PhoneNumberUtil.MatchType.NOT_A_NUMBER)
|
||||
{
|
||||
group.add(cc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (retrieved.getAddresses().getTo().size() > 1) {
|
||||
for (Address to : retrieved.getAddresses().getTo()) {
|
||||
PhoneNumberUtil.MatchType match;
|
||||
|
||||
if (localNumber == null) match = PhoneNumberUtil.MatchType.NO_MATCH;
|
||||
else match = PhoneNumberUtil.getInstance().isNumberMatch(localNumber, to.serialize());
|
||||
|
||||
if (match == PhoneNumberUtil.MatchType.NO_MATCH ||
|
||||
match == PhoneNumberUtil.MatchType.NOT_A_NUMBER)
|
||||
{
|
||||
group.add(to);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, group.toArray(new Address[0]), false);
|
||||
|
||||
return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||
}
|
||||
|
||||
private long getThreadIdFor(@NonNull NotificationInd notification) {
|
||||
String fromString = notification.getFrom() != null && notification.getFrom().getTextString() != null
|
||||
? Util.toIsoString(notification.getFrom().getTextString())
|
||||
: "";
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, fromString)}, false);
|
||||
return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, Address.fromExternal(context, fromString), false);
|
||||
return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
}
|
||||
|
||||
private Cursor rawQuery(@NonNull String where, @Nullable String[] arguments) {
|
||||
@ -489,39 +436,35 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
}
|
||||
|
||||
public List<Pair<Long, Long>> setTimestampRead(SyncMessageId messageId, long expireStarted) {
|
||||
MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
List<Pair<Long, Long>> expiring = new LinkedList<>();
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
cursor = database.query(TABLE_NAME, new String[] {ID, THREAD_ID, MESSAGE_BOX, EXPIRES_IN}, DATE_SENT + " = ?", new String[] {String.valueOf(messageId.getTimetamp())}, null, null, null, null);
|
||||
cursor = database.query(TABLE_NAME, new String[] {ID, THREAD_ID, MESSAGE_BOX, EXPIRES_IN, ADDRESS}, DATE_SENT + " = ?", new String[] {String.valueOf(messageId.getTimetamp())}, null, null, null, null);
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
List<Address> addresses = addressDatabase.getAddressesListForId(cursor.getLong(cursor.getColumnIndexOrThrow(ID)));
|
||||
Address theirAddress = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
||||
Address ourAddress = messageId.getAddress();
|
||||
|
||||
for (Address theirAddress : addresses) {
|
||||
Address ourAddress = messageId.getAddress();
|
||||
if (ourAddress.equals(theirAddress) || theirAddress.isGroup()) {
|
||||
long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
||||
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
|
||||
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRES_IN));
|
||||
|
||||
if (ourAddress.equals(theirAddress) || theirAddress.isGroup()) {
|
||||
long id = cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
||||
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
|
||||
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRES_IN));
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(READ, 1);
|
||||
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(READ, 1);
|
||||
|
||||
if (expiresIn > 0) {
|
||||
values.put(EXPIRE_STARTED, expireStarted);
|
||||
expiring.add(new Pair<>(id, expiresIn));
|
||||
}
|
||||
|
||||
database.update(TABLE_NAME, values, ID_WHERE, new String[]{String.valueOf(id)});
|
||||
|
||||
DatabaseFactory.getThreadDatabase(context).updateReadState(threadId);
|
||||
DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
|
||||
notifyConversationListeners(threadId);
|
||||
if (expiresIn > 0) {
|
||||
values.put(EXPIRE_STARTED, expireStarted);
|
||||
expiring.add(new Pair<>(id, expiresIn));
|
||||
}
|
||||
|
||||
database.update(TABLE_NAME, values, ID_WHERE, new String[]{String.valueOf(id)});
|
||||
|
||||
DatabaseFactory.getThreadDatabase(context).updateReadState(threadId);
|
||||
DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
|
||||
notifyConversationListeners(threadId);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
@ -592,7 +535,6 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
public OutgoingMediaMessage getOutgoingMessage(MasterSecret masterSecret, long messageId)
|
||||
throws MmsException, NoSuchMessageException
|
||||
{
|
||||
MmsAddressDatabase addr = DatabaseFactory.getMmsAddressDatabase(context);
|
||||
AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
|
||||
Cursor cursor = null;
|
||||
|
||||
@ -600,31 +542,27 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
cursor = rawQuery(RAW_ID_WHERE, new String[] {String.valueOf(messageId)});
|
||||
|
||||
if (cursor != null && cursor.moveToNext()) {
|
||||
long outboxType = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX));
|
||||
String messageText = cursor.getString(cursor.getColumnIndexOrThrow(BODY));
|
||||
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_SENT));
|
||||
int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SUBSCRIPTION_ID));
|
||||
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRES_IN));
|
||||
List<Attachment> attachments = new LinkedList<Attachment>(attachmentDatabase.getAttachmentsForMessage(masterSecret, messageId));
|
||||
MmsAddresses addresses = addr.getAddressesForId(messageId);
|
||||
List<Address> destinations = new LinkedList<>();
|
||||
String body = getDecryptedBody(masterSecret, messageText, outboxType);
|
||||
long outboxType = cursor.getLong(cursor.getColumnIndexOrThrow(MESSAGE_BOX));
|
||||
String messageText = cursor.getString(cursor.getColumnIndexOrThrow(BODY));
|
||||
long timestamp = cursor.getLong(cursor.getColumnIndexOrThrow(NORMALIZED_DATE_SENT));
|
||||
int subscriptionId = cursor.getInt(cursor.getColumnIndexOrThrow(SUBSCRIPTION_ID));
|
||||
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(EXPIRES_IN));
|
||||
List<Attachment> attachments = new LinkedList<Attachment>(attachmentDatabase.getAttachmentsForMessage(masterSecret, messageId));
|
||||
String address = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS));
|
||||
String body = getDecryptedBody(masterSecret, messageText, outboxType);
|
||||
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_ID));
|
||||
int distributionType = DatabaseFactory.getThreadDatabase(context).getDistributionType(threadId);
|
||||
|
||||
destinations.addAll(addresses.getBcc());
|
||||
destinations.addAll(addresses.getCc());
|
||||
destinations.addAll(addresses.getTo());
|
||||
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, destinations.toArray(new Address[0]), false);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, Address.fromSerialized(address), false);
|
||||
|
||||
if (body != null && (Types.isGroupQuit(outboxType) || Types.isGroupUpdate(outboxType))) {
|
||||
return new OutgoingGroupMediaMessage(recipients, body, attachments, timestamp, 0);
|
||||
return new OutgoingGroupMediaMessage(recipient, body, attachments, timestamp, 0);
|
||||
} else if (Types.isExpirationTimerUpdate(outboxType)) {
|
||||
return new OutgoingExpirationUpdateMessage(recipients, timestamp, expiresIn);
|
||||
return new OutgoingExpirationUpdateMessage(recipient, timestamp, expiresIn);
|
||||
}
|
||||
|
||||
OutgoingMediaMessage message = new OutgoingMediaMessage(recipients, body, attachments, timestamp, subscriptionId, expiresIn,
|
||||
!addresses.getBcc().isEmpty() ? ThreadDatabase.DistributionTypes.BROADCAST :
|
||||
ThreadDatabase.DistributionTypes.DEFAULT);
|
||||
OutgoingMediaMessage message = new OutgoingMediaMessage(recipient, body, attachments, timestamp, subscriptionId, expiresIn, distributionType);
|
||||
|
||||
if (Types.isSecureType(outboxType)) {
|
||||
return new OutgoingSecureMediaMessage(message);
|
||||
}
|
||||
@ -645,7 +583,7 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
try {
|
||||
OutgoingMediaMessage request = getOutgoingMessage(masterSecret, messageId);
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(ADDRESS, request.getRecipients().getPrimaryRecipient().getAddress().serialize());
|
||||
contentValues.put(ADDRESS, request.getRecipient().getAddress().serialize());
|
||||
contentValues.put(DATE_SENT, request.getSentTimeMillis());
|
||||
contentValues.put(MESSAGE_BOX, Types.BASE_INBOX_TYPE | Types.SECURE_MESSAGE_BIT | Types.ENCRYPTION_SYMMETRIC_BIT);
|
||||
contentValues.put(THREAD_ID, getThreadIdForMessage(messageId));
|
||||
@ -674,7 +612,6 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
}
|
||||
|
||||
return insertMediaMessage(new MasterSecretUnion(masterSecret),
|
||||
MmsAddresses.forTo(request.getRecipients().getAddressesList()),
|
||||
request.getBody(),
|
||||
attachments,
|
||||
contentValues,
|
||||
@ -703,7 +640,7 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
ContentValues contentValues = new ContentValues();
|
||||
|
||||
contentValues.put(DATE_SENT, retrieved.getSentTimeMillis());
|
||||
contentValues.put(ADDRESS, retrieved.getAddresses().getFrom().serialize());
|
||||
contentValues.put(ADDRESS, retrieved.getFrom().serialize());
|
||||
|
||||
contentValues.put(MESSAGE_BOX, mailbox);
|
||||
contentValues.put(MESSAGE_TYPE, PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF);
|
||||
@ -725,9 +662,7 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
long messageId = insertMediaMessage(masterSecret, retrieved.getAddresses(),
|
||||
retrieved.getBody(), retrieved.getAttachments(),
|
||||
contentValues, null);
|
||||
long messageId = insertMediaMessage(masterSecret, retrieved.getBody(), retrieved.getAttachments(), contentValues, null);
|
||||
|
||||
if (!Types.isExpirationTimerUpdate(mailbox)) {
|
||||
DatabaseFactory.getThreadDatabase(context).setUnread(threadId);
|
||||
@ -789,8 +724,7 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
}
|
||||
|
||||
public Pair<Long, Long> insertMessageInbox(@NonNull NotificationInd notification, int subscriptionId) {
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
long threadId = getThreadIdFor(notification);
|
||||
ContentValues contentValues = new ContentValues();
|
||||
ContentValuesBuilder contentBuilder = new ContentValuesBuilder(contentValues);
|
||||
@ -806,9 +740,7 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
contentBuilder.add(MESSAGE_TYPE, notification.getMessageType());
|
||||
|
||||
if (notification.getFrom() != null) {
|
||||
contentBuilder.add(ADDRESS, notification.getFrom().getTextString());
|
||||
} else {
|
||||
contentBuilder.add(ADDRESS, null);
|
||||
contentValues.put(ADDRESS, Address.fromExternal(context, Util.toIsoString(notification.getFrom().getTextString())).serialize());
|
||||
}
|
||||
|
||||
contentValues.put(MESSAGE_BOX, Types.BASE_INBOX_TYPE);
|
||||
@ -823,10 +755,6 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
|
||||
long messageId = db.insert(TABLE_NAME, null, contentValues);
|
||||
|
||||
if (notification.getFrom() != null) {
|
||||
addressDatabase.insertAddressesForId(messageId, MmsAddresses.forFrom(Address.fromExternal(context, Util.toIsoString(notification.getFrom().getTextString()))));
|
||||
}
|
||||
|
||||
return new Pair<>(messageId, threadId);
|
||||
}
|
||||
|
||||
@ -864,18 +792,6 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
type |= Types.EXPIRATION_TIMER_UPDATE_BIT;
|
||||
}
|
||||
|
||||
List<Address> recipientNumbers = message.getRecipients().getAddressesList();
|
||||
|
||||
MmsAddresses addresses;
|
||||
|
||||
if (!message.getRecipients().isSingleRecipient() &&
|
||||
message.getDistributionType() == ThreadDatabase.DistributionTypes.BROADCAST)
|
||||
{
|
||||
addresses = MmsAddresses.forBcc(recipientNumbers);
|
||||
} else {
|
||||
addresses = MmsAddresses.forTo(recipientNumbers);
|
||||
}
|
||||
|
||||
ContentValues contentValues = new ContentValues();
|
||||
contentValues.put(DATE_SENT, message.getSentTimeMillis());
|
||||
contentValues.put(MESSAGE_TYPE, PduHeaders.MESSAGE_TYPE_SEND_REQ);
|
||||
@ -886,15 +802,10 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
contentValues.put(DATE_RECEIVED, System.currentTimeMillis());
|
||||
contentValues.put(SUBSCRIPTION_ID, message.getSubscriptionId());
|
||||
contentValues.put(EXPIRES_IN, message.getExpiresIn());
|
||||
contentValues.put(ADDRESS, message.getRecipient().getAddress().serialize());
|
||||
contentValues.put(RECEIPT_COUNT, earlyReceiptCache.remove(message.getSentTimeMillis(), message.getRecipient().getAddress()));
|
||||
|
||||
if (message.getRecipients().isSingleRecipient()) {
|
||||
contentValues.put(RECEIPT_COUNT, earlyReceiptCache.remove(message.getSentTimeMillis(), message.getRecipients().getPrimaryRecipient().getAddress()));
|
||||
}
|
||||
|
||||
contentValues.remove(ADDRESS);
|
||||
|
||||
long messageId = insertMediaMessage(masterSecret, addresses, message.getBody(),
|
||||
message.getAttachments(), contentValues, insertListener);
|
||||
long messageId = insertMediaMessage(masterSecret, message.getBody(), message.getAttachments(), contentValues, insertListener);
|
||||
|
||||
DatabaseFactory.getThreadDatabase(context).setLastSeen(threadId);
|
||||
jobManager.add(new TrimThreadJob(context, threadId));
|
||||
@ -928,7 +839,6 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
}
|
||||
|
||||
private long insertMediaMessage(@NonNull MasterSecretUnion masterSecret,
|
||||
@NonNull MmsAddresses addresses,
|
||||
@Nullable String body,
|
||||
@NonNull List<Attachment> attachments,
|
||||
@NonNull ContentValues contentValues,
|
||||
@ -937,7 +847,6 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
{
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
AttachmentDatabase partsDatabase = DatabaseFactory.getAttachmentDatabase(context);
|
||||
MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
|
||||
|
||||
if (Types.isSymmetricEncryption(contentValues.getAsLong(MESSAGE_BOX)) ||
|
||||
Types.isAsymmetricEncryption(contentValues.getAsLong(MESSAGE_BOX)))
|
||||
@ -953,7 +862,6 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
try {
|
||||
long messageId = db.insert(TABLE_NAME, null, contentValues);
|
||||
|
||||
addressDatabase.insertAddressesForId(messageId, addresses);
|
||||
partsDatabase.insertAttachmentsForMessage(masterSecret, messageId, attachments);
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
@ -972,10 +880,8 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
|
||||
public boolean delete(long messageId) {
|
||||
long threadId = getThreadIdForMessage(messageId);
|
||||
MmsAddressDatabase addrDatabase = DatabaseFactory.getMmsAddressDatabase(context);
|
||||
AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
|
||||
attachmentDatabase.deleteAttachmentsForMessage(messageId);
|
||||
addrDatabase.deleteAddressesForId(messageId);
|
||||
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
database.delete(TABLE_NAME, ID_WHERE, new String[] {messageId+""});
|
||||
@ -993,7 +899,7 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
private boolean isDuplicate(IncomingMediaMessage message, long threadId) {
|
||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||
Cursor cursor = database.query(TABLE_NAME, null, DATE_SENT + " = ? AND " + ADDRESS + " = ? AND " + THREAD_ID + " = ?",
|
||||
new String[]{String.valueOf(message.getSentTimeMillis()), message.getAddresses().getFrom().serialize(), String.valueOf(threadId)},
|
||||
new String[]{String.valueOf(message.getSentTimeMillis()), message.getFrom().serialize(), String.valueOf(threadId)},
|
||||
null, null, null, "1");
|
||||
|
||||
try {
|
||||
@ -1058,7 +964,6 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
|
||||
public void deleteAllThreads() {
|
||||
DatabaseFactory.getAttachmentDatabase(context).deleteAllAttachments();
|
||||
DatabaseFactory.getMmsAddressDatabase(context).deleteAllAddresses();
|
||||
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
database.delete(TABLE_NAME, null, null);
|
||||
@ -1139,8 +1044,7 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
public MessageRecord getCurrent() {
|
||||
SlideDeck slideDeck = new SlideDeck(context, message.getAttachments());
|
||||
|
||||
return new MediaMmsMessageRecord(context, id, message.getRecipients(),
|
||||
message.getRecipients().getPrimaryRecipient(),
|
||||
return new MediaMmsMessageRecord(context, id, message.getRecipient(), message.getRecipient(),
|
||||
1, System.currentTimeMillis(), System.currentTimeMillis(),
|
||||
0, threadId, new DisplayRecord.Body(message.getBody(), true),
|
||||
slideDeck, slideDeck.getSlides().size(),
|
||||
@ -1192,7 +1096,7 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
long mailbox = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX));
|
||||
String address = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS));
|
||||
int addressDeviceId = cursor.getInt(cursor.getColumnIndexOrThrow(MmsDatabase.ADDRESS_DEVICE_ID));
|
||||
Recipients recipients = getRecipientsFor(address);
|
||||
Recipient recipient = getRecipientFor(address);
|
||||
|
||||
String contentLocation = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.CONTENT_LOCATION));
|
||||
String transactionId = cursor.getString(cursor.getColumnIndexOrThrow(MmsDatabase.TRANSACTION_ID));
|
||||
@ -1214,7 +1118,7 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
SlideDeck slideDeck = new SlideDeck(context, new MmsNotificationAttachment(status, messageSize));
|
||||
|
||||
|
||||
return new NotificationMmsMessageRecord(context, id, recipients, recipients.getPrimaryRecipient(),
|
||||
return new NotificationMmsMessageRecord(context, id, recipient, recipient,
|
||||
addressDeviceId, dateSent, dateReceived, receiptCount, threadId,
|
||||
contentLocationBytes, messageSize, expiry, status,
|
||||
transactionIdBytes, mailbox, subscriptionId, slideDeck);
|
||||
@ -1237,18 +1141,18 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.EXPIRES_IN));
|
||||
long expireStarted = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.EXPIRE_STARTED));
|
||||
|
||||
Recipients recipients = getRecipientsFor(address);
|
||||
Recipient recipient = getRecipientFor(address);
|
||||
List<IdentityKeyMismatch> mismatches = getMismatchedIdentities(mismatchDocument);
|
||||
List<NetworkFailure> networkFailures = getFailures(networkDocument);
|
||||
SlideDeck slideDeck = getSlideDeck(cursor);
|
||||
|
||||
return new MediaMmsMessageRecord(context, id, recipients, recipients.getPrimaryRecipient(),
|
||||
return new MediaMmsMessageRecord(context, id, recipient, recipient,
|
||||
addressDeviceId, dateSent, dateReceived, receiptCount,
|
||||
threadId, body, slideDeck, partCount, box, mismatches,
|
||||
networkFailures, subscriptionId, expiresIn, expireStarted);
|
||||
}
|
||||
|
||||
private Recipients getRecipientsFor(String serialized) {
|
||||
private Recipient getRecipientFor(String serialized) {
|
||||
Address address;
|
||||
|
||||
if (TextUtils.isEmpty(serialized) || "insert-address-token".equals(serialized)) {
|
||||
@ -1257,7 +1161,7 @@ public class MmsDatabase extends MessagingDatabase {
|
||||
address = Address.fromSerialized(serialized);
|
||||
|
||||
}
|
||||
return RecipientFactory.getRecipientsFor(context, new Address[] {address}, true);
|
||||
return RecipientFactory.getRecipientFor(context, address, true);
|
||||
}
|
||||
|
||||
private List<IdentityKeyMismatch> getMismatchedIdentities(String document) {
|
||||
|
@ -8,8 +8,8 @@ import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.File;
|
||||
@ -34,8 +34,8 @@ public class PlaintextBackupImporter {
|
||||
XmlBackup.XmlBackupItem item;
|
||||
|
||||
while ((item = backup.getNext()) != null) {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, item.getAddress())}, false);
|
||||
long threadId = threads.getThreadIdFor(recipients);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, Address.fromExternal(context, item.getAddress()), false);
|
||||
long threadId = threads.getThreadIdFor(recipient);
|
||||
SQLiteStatement statement = db.createInsertStatement(transaction);
|
||||
|
||||
if (item.getAddress() == null || item.getAddress().equals("null"))
|
||||
|
@ -12,13 +12,10 @@ import android.util.Log;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class RecipientPreferenceDatabase extends Database {
|
||||
|
||||
private static final String TAG = RecipientPreferenceDatabase.class.getSimpleName();
|
||||
@ -26,7 +23,7 @@ public class RecipientPreferenceDatabase extends Database {
|
||||
|
||||
private static final String TABLE_NAME = "recipient_preferences";
|
||||
private static final String ID = "_id";
|
||||
private static final String ADDRESSES = "recipient_ids";
|
||||
private static final String ADDRESS = "recipient_ids";
|
||||
private static final String BLOCK = "block";
|
||||
private static final String NOTIFICATION = "notification";
|
||||
private static final String VIBRATE = "vibrate";
|
||||
@ -57,7 +54,7 @@ public class RecipientPreferenceDatabase extends Database {
|
||||
public static final String CREATE_TABLE =
|
||||
"CREATE TABLE " + TABLE_NAME +
|
||||
" (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
ADDRESSES + " TEXT UNIQUE, " +
|
||||
ADDRESS + " TEXT UNIQUE, " +
|
||||
BLOCK + " INTEGER DEFAULT 0," +
|
||||
NOTIFICATION + " TEXT DEFAULT NULL, " +
|
||||
VIBRATE + " INTEGER DEFAULT " + VibrateState.DEFAULT.getId() + ", " +
|
||||
@ -74,7 +71,7 @@ public class RecipientPreferenceDatabase extends Database {
|
||||
public Cursor getBlocked() {
|
||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||
|
||||
Cursor cursor = database.query(TABLE_NAME, new String[] {ID, ADDRESSES}, BLOCK + " = 1",
|
||||
Cursor cursor = database.query(TABLE_NAME, new String[] {ID, ADDRESS}, BLOCK + " = 1",
|
||||
null, null, null, null, null);
|
||||
cursor.setNotificationUri(context.getContentResolver(), Uri.parse(RECIPIENT_PREFERENCES_URI));
|
||||
|
||||
@ -85,14 +82,13 @@ public class RecipientPreferenceDatabase extends Database {
|
||||
return new BlockedReader(context, cursor);
|
||||
}
|
||||
|
||||
public Optional<RecipientsPreferences> getRecipientsPreferences(@NonNull Address[] addresses) {
|
||||
|
||||
public Optional<RecipientsPreferences> getRecipientsPreferences(@NonNull Address address) {
|
||||
SQLiteDatabase database = databaseHelper.getReadableDatabase();
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
cursor = database.query(TABLE_NAME, null, ADDRESSES + " = ?",
|
||||
new String[] {Address.toSerializedList(Arrays.asList(addresses), ' ')},
|
||||
null, null, null);
|
||||
cursor = database.query(TABLE_NAME, null, ADDRESS + " = ?", new String[] {address.serialize()}, null, null, null);
|
||||
|
||||
if (cursor != null && cursor.moveToNext()) {
|
||||
boolean blocked = cursor.getInt(cursor.getColumnIndexOrThrow(BLOCK)) == 1;
|
||||
@ -128,69 +124,68 @@ public class RecipientPreferenceDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
public void setColor(Recipients recipients, MaterialColor color) {
|
||||
public void setColor(Recipient recipient, MaterialColor color) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(COLOR, color.serialize());
|
||||
updateOrInsert(recipients, values);
|
||||
updateOrInsert(recipient, values);
|
||||
}
|
||||
|
||||
public void setDefaultSubscriptionId(@NonNull Recipients recipients, int defaultSubscriptionId) {
|
||||
public void setDefaultSubscriptionId(@NonNull Recipient recipient, int defaultSubscriptionId) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(DEFAULT_SUBSCRIPTION_ID, defaultSubscriptionId);
|
||||
updateOrInsert(recipients, values);
|
||||
EventBus.getDefault().post(new RecipientPreferenceEvent(recipients));
|
||||
updateOrInsert(recipient, values);
|
||||
EventBus.getDefault().post(new RecipientPreferenceEvent(recipient));
|
||||
}
|
||||
|
||||
public void setBlocked(Recipients recipients, boolean blocked) {
|
||||
public void setBlocked(Recipient recipient, boolean blocked) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(BLOCK, blocked ? 1 : 0);
|
||||
updateOrInsert(recipients, values);
|
||||
updateOrInsert(recipient, values);
|
||||
}
|
||||
|
||||
public void setRingtone(Recipients recipients, @Nullable Uri notification) {
|
||||
public void setRingtone(Recipient recipient, @Nullable Uri notification) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(NOTIFICATION, notification == null ? null : notification.toString());
|
||||
updateOrInsert(recipients, values);
|
||||
updateOrInsert(recipient, values);
|
||||
}
|
||||
|
||||
public void setVibrate(Recipients recipients, @NonNull VibrateState enabled) {
|
||||
public void setVibrate(Recipient recipient, @NonNull VibrateState enabled) {
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(VIBRATE, enabled.getId());
|
||||
updateOrInsert(recipients, values);
|
||||
updateOrInsert(recipient, values);
|
||||
}
|
||||
|
||||
public void setMuted(Recipients recipients, long until) {
|
||||
public void setMuted(Recipient recipient, long until) {
|
||||
Log.w(TAG, "Setting muted until: " + until);
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(MUTE_UNTIL, until);
|
||||
updateOrInsert(recipients, values);
|
||||
updateOrInsert(recipient, values);
|
||||
}
|
||||
|
||||
public void setSeenInviteReminder(Recipients recipients, boolean seen) {
|
||||
public void setSeenInviteReminder(Recipient recipient, boolean seen) {
|
||||
ContentValues values = new ContentValues(1);
|
||||
values.put(SEEN_INVITE_REMINDER, seen ? 1 : 0);
|
||||
updateOrInsert(recipients, values);
|
||||
updateOrInsert(recipient, values);
|
||||
}
|
||||
|
||||
public void setExpireMessages(Recipients recipients, int expiration) {
|
||||
recipients.setExpireMessages(expiration);
|
||||
public void setExpireMessages(Recipient recipient, int expiration) {
|
||||
recipient.setExpireMessages(expiration);
|
||||
|
||||
ContentValues values = new ContentValues(1);
|
||||
values.put(EXPIRE_MESSAGES, expiration);
|
||||
updateOrInsert(recipients, values);
|
||||
updateOrInsert(recipient, values);
|
||||
}
|
||||
|
||||
private void updateOrInsert(Recipients recipients, ContentValues contentValues) {
|
||||
private void updateOrInsert(Recipient recipient, ContentValues contentValues) {
|
||||
SQLiteDatabase database = databaseHelper.getWritableDatabase();
|
||||
|
||||
database.beginTransaction();
|
||||
|
||||
List<Address> addresses = recipients.getAddressesList();
|
||||
String serializedAddresses = Address.toSerializedList(addresses, ' ');
|
||||
int updated = database.update(TABLE_NAME, contentValues, ADDRESSES + " = ?", new String[]{serializedAddresses});
|
||||
int updated = database.update(TABLE_NAME, contentValues, ADDRESS + " = ?",
|
||||
new String[] {recipient.getAddress().serialize()});
|
||||
|
||||
if (updated < 1) {
|
||||
contentValues.put(ADDRESSES, serializedAddresses);
|
||||
contentValues.put(ADDRESS, recipient.getAddress().serialize());
|
||||
database.insert(TABLE_NAME, null, contentValues);
|
||||
}
|
||||
|
||||
@ -271,14 +266,12 @@ public class RecipientPreferenceDatabase extends Database {
|
||||
this.cursor = cursor;
|
||||
}
|
||||
|
||||
public @NonNull Recipients getCurrent() {
|
||||
String serialized = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESSES));
|
||||
List<Address> addressList = Address.fromSerializedList(serialized, ' ');
|
||||
|
||||
return RecipientFactory.getRecipientsFor(context, addressList.toArray(new Address[0]), false);
|
||||
public @NonNull Recipient getCurrent() {
|
||||
String serialized = cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS));
|
||||
return RecipientFactory.getRecipientFor(context, Address.fromSerialized(serialized), false);
|
||||
}
|
||||
|
||||
public @Nullable Recipients getNext() {
|
||||
public @Nullable Recipient getNext() {
|
||||
if (!cursor.moveToNext()) {
|
||||
return null;
|
||||
}
|
||||
@ -289,14 +282,14 @@ public class RecipientPreferenceDatabase extends Database {
|
||||
|
||||
public static class RecipientPreferenceEvent {
|
||||
|
||||
private final Recipients recipients;
|
||||
private final Recipient recipient;
|
||||
|
||||
RecipientPreferenceEvent(Recipients recipients) {
|
||||
this.recipients = recipients;
|
||||
public RecipientPreferenceEvent(Recipient recipients) {
|
||||
this.recipient = recipients;
|
||||
}
|
||||
|
||||
public Recipients getRecipients() {
|
||||
return recipients;
|
||||
public Recipient getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,8 +34,8 @@ import org.thoughtcrime.securesms.database.model.DisplayRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.jobs.TrimThreadJob;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||
@ -457,8 +457,8 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
}
|
||||
|
||||
private @NonNull Pair<Long, Long> insertCallLog(@NonNull Address address, long type, boolean unread) {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {address}, true);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, address, true);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
|
||||
ContentValues values = new ContentValues(6);
|
||||
values.put(ADDRESS, address.serialize());
|
||||
@ -506,14 +506,14 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
if (message.isIdentityVerified()) type |= Types.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT;
|
||||
else if (message.isIdentityDefault()) type |= Types.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT;
|
||||
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {message.getSender()}, true);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, message.getSender(), true);
|
||||
|
||||
Recipients groupRecipients;
|
||||
Recipient groupRecipient;
|
||||
|
||||
if (message.getGroupId() == null) {
|
||||
groupRecipients = null;
|
||||
groupRecipient = null;
|
||||
} else {
|
||||
groupRecipients = RecipientFactory.getRecipientsFor(context, new Address[] {message.getGroupId()}, true);
|
||||
groupRecipient = RecipientFactory.getRecipientFor(context, message.getGroupId(), true);
|
||||
}
|
||||
|
||||
boolean unread = (org.thoughtcrime.securesms.util.Util.isDefaultSmsProvider(context) ||
|
||||
@ -522,8 +522,8 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
|
||||
long threadId;
|
||||
|
||||
if (groupRecipients == null) threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||
else threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipients);
|
||||
if (groupRecipient == null) threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
else threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient);
|
||||
|
||||
ContentValues values = new ContentValues(6);
|
||||
values.put(ADDRESS, message.getSender().serialize());
|
||||
@ -560,7 +560,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
}
|
||||
|
||||
if (message.getSubscriptionId() != -1) {
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(context).setDefaultSubscriptionId(recipients, message.getSubscriptionId());
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(context).setDefaultSubscriptionId(recipient, message.getSubscriptionId());
|
||||
}
|
||||
|
||||
notifyConversationListeners(threadId);
|
||||
@ -589,7 +589,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
if (message.isIdentityVerified()) type |= Types.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT;
|
||||
else if (message.isIdentityDefault()) type |= Types.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT;
|
||||
|
||||
Address address = message.getRecipients().getPrimaryRecipient().getAddress();
|
||||
Address address = message.getRecipient().getAddress();
|
||||
|
||||
ContentValues contentValues = new ContentValues(6);
|
||||
contentValues.put(ADDRESS, address.serialize());
|
||||
@ -783,7 +783,7 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
|
||||
public MessageRecord getCurrent() {
|
||||
return new SmsMessageRecord(context, id, new DisplayRecord.Body(message.getMessageBody(), true),
|
||||
message.getRecipients(), message.getRecipients().getPrimaryRecipient(),
|
||||
message.getRecipient(), message.getRecipient(),
|
||||
1, System.currentTimeMillis(), System.currentTimeMillis(),
|
||||
0, message.isSecureMessage() ? MmsSmsColumns.Types.getOutgoingEncryptedMessageType() : MmsSmsColumns.Types.getOutgoingSmsMessageType(),
|
||||
threadId, 0, new LinkedList<IdentityKeyMismatch>(),
|
||||
@ -828,21 +828,17 @@ public class SmsDatabase extends MessagingDatabase {
|
||||
long expireStarted = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.EXPIRE_STARTED));
|
||||
|
||||
List<IdentityKeyMismatch> mismatches = getMismatches(mismatchDocument);
|
||||
Recipients recipients = getRecipientsFor(address);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, address, true);
|
||||
DisplayRecord.Body body = getBody(cursor);
|
||||
|
||||
return new SmsMessageRecord(context, messageId, body, recipients,
|
||||
recipients.getPrimaryRecipient(),
|
||||
return new SmsMessageRecord(context, messageId, body, recipient,
|
||||
recipient,
|
||||
addressDeviceId,
|
||||
dateSent, dateReceived, receiptCount, type,
|
||||
threadId, status, mismatches, subscriptionId,
|
||||
expiresIn, expireStarted);
|
||||
}
|
||||
|
||||
private Recipients getRecipientsFor(Address address) {
|
||||
return RecipientFactory.getRecipientsFor(context, new Address[] {address}, true);
|
||||
}
|
||||
|
||||
private List<IdentityKeyMismatch> getMismatches(String document) {
|
||||
try {
|
||||
if (!TextUtils.isEmpty(document)) {
|
||||
|
@ -22,16 +22,19 @@ import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
import android.database.sqlite.SQLiteStatement;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public class SmsMigrator {
|
||||
@ -140,21 +143,21 @@ public class SmsMigrator {
|
||||
}
|
||||
}
|
||||
|
||||
private static Recipients getOurRecipients(Context context, String theirRecipients) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(theirRecipients.trim(), " ");
|
||||
List<Address> addressList = new LinkedList<>();
|
||||
private static @Nullable Set<Recipient> getOurRecipients(Context context, String theirRecipients) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(theirRecipients.trim(), " ");
|
||||
Set<Recipient> recipientList = new HashSet<>();
|
||||
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
String theirRecipientId = tokenizer.nextToken();
|
||||
String address = getTheirCanonicalAddress(context, theirRecipientId);
|
||||
|
||||
if (address != null) {
|
||||
addressList.add(Address.fromExternal(context, address));
|
||||
recipientList.add(RecipientFactory.getRecipientFor(context, Address.fromExternal(context, address), true));
|
||||
}
|
||||
}
|
||||
|
||||
if (addressList.isEmpty()) return null;
|
||||
else return RecipientFactory.getRecipientsFor(context, addressList.toArray(new Address[0]), true);
|
||||
if (recipientList.isEmpty()) return null;
|
||||
else return recipientList;
|
||||
}
|
||||
|
||||
private static String encrypt(MasterSecret masterSecret, String body)
|
||||
@ -221,16 +224,30 @@ public class SmsMigrator {
|
||||
cursor = context.getContentResolver().query(threadListUri, null, null, null, "date ASC");
|
||||
|
||||
while (cursor != null && cursor.moveToNext()) {
|
||||
long theirThreadId = cursor.getLong(cursor.getColumnIndexOrThrow("_id"));
|
||||
String theirRecipients = cursor.getString(cursor.getColumnIndexOrThrow("recipient_ids"));
|
||||
Recipients ourRecipients = getOurRecipients(context, theirRecipients);
|
||||
ProgressDescription progress = new ProgressDescription(cursor.getCount(), cursor.getPosition(), 100, 0);
|
||||
long theirThreadId = cursor.getLong(cursor.getColumnIndexOrThrow("_id"));
|
||||
String theirRecipients = cursor.getString(cursor.getColumnIndexOrThrow("recipient_ids"));
|
||||
Set<Recipient> ourRecipients = getOurRecipients(context, theirRecipients);
|
||||
ProgressDescription progress = new ProgressDescription(cursor.getCount(), cursor.getPosition(), 100, 0);
|
||||
|
||||
if (ourRecipients != null) {
|
||||
long ourThreadId = threadDatabase.getThreadIdFor(ourRecipients);
|
||||
migrateConversation(context, masterSecret,
|
||||
listener, progress,
|
||||
theirThreadId, ourThreadId);
|
||||
if (ourRecipients.size() == 1) {
|
||||
long ourThreadId = threadDatabase.getThreadIdFor(ourRecipients.iterator().next());
|
||||
migrateConversation(context, masterSecret, listener, progress, theirThreadId, ourThreadId);
|
||||
} else if (ourRecipients.size() > 1) {
|
||||
ourRecipients.add(RecipientFactory.getRecipientFor(context, Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)), true));
|
||||
|
||||
List<Address> memberAddresses = new LinkedList<>();
|
||||
|
||||
for (Recipient recipient : ourRecipients) {
|
||||
memberAddresses.add(recipient.getAddress());
|
||||
}
|
||||
|
||||
String ourGroupId = DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(memberAddresses, true);
|
||||
Recipient ourGroupRecipient = RecipientFactory.getRecipientFor(context, Address.fromSerialized(ourGroupId), true);
|
||||
long ourThreadId = threadDatabase.getThreadIdFor(ourGroupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
||||
|
||||
migrateConversation(context, masterSecret, listener, progress, theirThreadId, ourThreadId);
|
||||
}
|
||||
}
|
||||
|
||||
progress.incrementPrimaryComplete();
|
||||
|
@ -36,13 +36,12 @@ import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.DelimiterUtil;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.InvalidMessageException;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@ -55,7 +54,7 @@ public class ThreadDatabase extends Database {
|
||||
public static final String ID = "_id";
|
||||
public static final String DATE = "date";
|
||||
public static final String MESSAGE_COUNT = "message_count";
|
||||
public static final String ADDRESSES = "recipient_ids";
|
||||
public static final String ADDRESS = "recipient_ids";
|
||||
public static final String SNIPPET = "snippet";
|
||||
private static final String SNIPPET_CHARSET = "snippet_cs";
|
||||
public static final String READ = "read";
|
||||
@ -71,7 +70,7 @@ public class ThreadDatabase extends Database {
|
||||
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" +
|
||||
ID + " INTEGER PRIMARY KEY, " + DATE + " INTEGER DEFAULT 0, " +
|
||||
MESSAGE_COUNT + " INTEGER DEFAULT 0, " + ADDRESSES + " TEXT, " + SNIPPET + " TEXT, " +
|
||||
MESSAGE_COUNT + " INTEGER DEFAULT 0, " + ADDRESS + " TEXT, " + SNIPPET + " TEXT, " +
|
||||
SNIPPET_CHARSET + " INTEGER DEFAULT 0, " + READ + " INTEGER DEFAULT 1, " +
|
||||
TYPE + " INTEGER DEFAULT 0, " + ERROR + " INTEGER DEFAULT 0, " +
|
||||
SNIPPET_TYPE + " INTEGER DEFAULT 0, " + SNIPPET_URI + " TEXT DEFAULT NULL, " +
|
||||
@ -80,7 +79,7 @@ public class ThreadDatabase extends Database {
|
||||
LAST_SEEN + " INTEGER DEFAULT 0);";
|
||||
|
||||
public static final String[] CREATE_INDEXS = {
|
||||
"CREATE INDEX IF NOT EXISTS thread_recipient_ids_index ON " + TABLE_NAME + " (" + ADDRESSES + ");",
|
||||
"CREATE INDEX IF NOT EXISTS thread_recipient_ids_index ON " + TABLE_NAME + " (" + ADDRESS + ");",
|
||||
"CREATE INDEX IF NOT EXISTS archived_count_index ON " + TABLE_NAME + " (" + ARCHIVED + ", " + MESSAGE_COUNT + ");",
|
||||
};
|
||||
|
||||
@ -88,14 +87,14 @@ public class ThreadDatabase extends Database {
|
||||
super(context, databaseHelper);
|
||||
}
|
||||
|
||||
private long createThreadForRecipients(Address[] addresses, int recipientCount, int distributionType) {
|
||||
private long createThreadForRecipient(Address address, boolean group, int distributionType) {
|
||||
ContentValues contentValues = new ContentValues(4);
|
||||
long date = System.currentTimeMillis();
|
||||
|
||||
contentValues.put(DATE, date - date % 1000);
|
||||
contentValues.put(ADDRESSES, Address.toSerializedList(Arrays.asList(addresses), ' '));
|
||||
contentValues.put(ADDRESS, address.serialize());
|
||||
|
||||
if (recipientCount > 1)
|
||||
if (group)
|
||||
contentValues.put(TYPE, distributionType);
|
||||
|
||||
contentValues.put(MESSAGE_COUNT, 0);
|
||||
@ -272,6 +271,22 @@ public class ThreadDatabase extends Database {
|
||||
notifyConversationListListeners();
|
||||
}
|
||||
|
||||
public int getDistributionType(long threadId) {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
Cursor cursor = db.query(TABLE_NAME, new String[]{TYPE}, ID_WHERE, new String[]{String.valueOf(threadId)}, null, null, null);
|
||||
|
||||
try {
|
||||
if (cursor != null && cursor.moveToNext()) {
|
||||
return cursor.getInt(cursor.getColumnIndexOrThrow(TYPE));
|
||||
}
|
||||
|
||||
return DistributionTypes.DEFAULT;
|
||||
} finally {
|
||||
if (cursor != null) cursor.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public Cursor getFilteredConversationList(List<Address> filter) {
|
||||
if (filter == null || filter.size() == 0)
|
||||
return null;
|
||||
@ -281,11 +296,11 @@ public class ThreadDatabase extends Database {
|
||||
List<Cursor> cursors = new LinkedList<>();
|
||||
|
||||
for (List<Address> addresses : partitionedAddresses) {
|
||||
String selection = ADDRESSES + " = ?";
|
||||
String selection = ADDRESS + " = ?";
|
||||
String[] selectionArgs = new String[addresses.size()];
|
||||
|
||||
for (int i=0;i<addresses.size()-1;i++)
|
||||
selection += (" OR " + ADDRESSES + " = ?");
|
||||
selection += (" OR " + ADDRESS + " = ?");
|
||||
|
||||
int i= 0;
|
||||
for (Address address : addresses) {
|
||||
@ -410,12 +425,11 @@ public class ThreadDatabase extends Database {
|
||||
deleteAllThreads();
|
||||
}
|
||||
|
||||
public long getThreadIdIfExistsFor(Recipients recipients) {
|
||||
List<Address> addresses = Arrays.asList(recipients.getAddresses());
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
String where = ADDRESSES + " = ?";
|
||||
String[] recipientsArg = new String[]{Address.toSerializedList(addresses, ' ')};
|
||||
Cursor cursor = null;
|
||||
public long getThreadIdIfExistsFor(Recipient recipient) {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
String where = ADDRESS + " = ?";
|
||||
String[] recipientsArg = new String[] {recipient.getAddress().serialize()};
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
cursor = db.query(TABLE_NAME, new String[]{ID}, where, recipientsArg, null, null, null);
|
||||
@ -430,15 +444,14 @@ public class ThreadDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
public long getThreadIdFor(Recipients recipients) {
|
||||
return getThreadIdFor(recipients, DistributionTypes.DEFAULT);
|
||||
public long getThreadIdFor(Recipient recipient) {
|
||||
return getThreadIdFor(recipient, DistributionTypes.DEFAULT);
|
||||
}
|
||||
|
||||
public long getThreadIdFor(Recipients recipients, int distributionType) {
|
||||
Address[] addresses = recipients.getAddresses();
|
||||
public long getThreadIdFor(Recipient recipient, int distributionType) {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
String where = ADDRESSES + " = ?";
|
||||
String[] recipientsArg = new String[]{Address.toSerializedList(Arrays.asList(addresses), ' ')};
|
||||
String where = ADDRESS + " = ?";
|
||||
String[] recipientsArg = new String[]{recipient.getAddress().serialize()};
|
||||
Cursor cursor = null;
|
||||
|
||||
try {
|
||||
@ -447,7 +460,7 @@ public class ThreadDatabase extends Database {
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
return cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
||||
} else {
|
||||
return createThreadForRecipients(addresses, recipients.getRecipientsList().size(), distributionType);
|
||||
return createThreadForRecipient(recipient.getAddress(), recipient.isGroupRecipient(), distributionType);
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null)
|
||||
@ -455,7 +468,7 @@ public class ThreadDatabase extends Database {
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable Recipients getRecipientsForThreadId(long threadId) {
|
||||
public @Nullable Recipient getRecipientForThreadId(long threadId) {
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
Cursor cursor = null;
|
||||
|
||||
@ -463,8 +476,8 @@ public class ThreadDatabase extends Database {
|
||||
cursor = db.query(TABLE_NAME, null, ID + " = ?", new String[] {threadId+""}, null, null, null);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
List<Address> addresses = Address.fromSerializedList(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESSES)), ' ');
|
||||
return RecipientFactory.getRecipientsFor(context, addresses.toArray(new Address[0]), false);
|
||||
Address address = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ADDRESS)));
|
||||
return RecipientFactory.getRecipientFor(context, address, false);
|
||||
}
|
||||
} finally {
|
||||
if (cursor != null)
|
||||
@ -561,9 +574,9 @@ public class ThreadDatabase extends Database {
|
||||
}
|
||||
|
||||
public ThreadRecord getCurrent() {
|
||||
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.ID));
|
||||
List<Address> addresses = Address.fromSerializedList(cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.ADDRESSES)), ' ');
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, addresses.toArray(new Address[0]), true);
|
||||
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.ID));
|
||||
Address address = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.ADDRESS)));
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, address, true);
|
||||
|
||||
DisplayRecord.Body body = getPlaintextBody(cursor);
|
||||
long date = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.DATE));
|
||||
@ -578,7 +591,7 @@ public class ThreadDatabase extends Database {
|
||||
long lastSeen = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.LAST_SEEN));
|
||||
Uri snippetUri = getSnippetUri(cursor);
|
||||
|
||||
return new ThreadRecord(context, body, snippetUri, recipients, date, count, read == 1,
|
||||
return new ThreadRecord(context, body, snippetUri, recipient, date, count, read == 1,
|
||||
threadId, receiptCount, status, type, distributionType, archived,
|
||||
expiresIn, lastSeen);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public class ConversationListLoader extends AbstractCursorLoader {
|
||||
if (archivedCount > 0) {
|
||||
MatrixCursor switchToArchiveCursor = new MatrixCursor(new String[] {
|
||||
ThreadDatabase.ID, ThreadDatabase.DATE, ThreadDatabase.MESSAGE_COUNT,
|
||||
ThreadDatabase.ADDRESSES, ThreadDatabase.SNIPPET, ThreadDatabase.READ,
|
||||
ThreadDatabase.ADDRESS, ThreadDatabase.SNIPPET, ThreadDatabase.READ,
|
||||
ThreadDatabase.TYPE, ThreadDatabase.SNIPPET_TYPE, ThreadDatabase.SNIPPET_URI,
|
||||
ThreadDatabase.ARCHIVED, ThreadDatabase.STATUS, ThreadDatabase.RECEIPT_COUNT,
|
||||
ThreadDatabase.EXPIRES_IN, ThreadDatabase.LAST_SEEN}, 1);
|
||||
|
@ -21,7 +21,7 @@ import android.text.SpannableString;
|
||||
|
||||
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
/**
|
||||
* The base class for all message record models. Encapsulates basic data
|
||||
@ -36,7 +36,7 @@ public abstract class DisplayRecord {
|
||||
protected final Context context;
|
||||
protected final long type;
|
||||
|
||||
private final Recipients recipients;
|
||||
private final Recipient recipient;
|
||||
private final long dateSent;
|
||||
private final long dateReceived;
|
||||
private final long threadId;
|
||||
@ -44,12 +44,12 @@ public abstract class DisplayRecord {
|
||||
private final int deliveryStatus;
|
||||
private final int receiptCount;
|
||||
|
||||
public DisplayRecord(Context context, Body body, Recipients recipients, long dateSent,
|
||||
public DisplayRecord(Context context, Body body, Recipient recipient, long dateSent,
|
||||
long dateReceived, long threadId, int deliveryStatus, int receiptCount, long type)
|
||||
{
|
||||
this.context = context.getApplicationContext();
|
||||
this.threadId = threadId;
|
||||
this.recipients = recipients;
|
||||
this.recipient = recipient;
|
||||
this.dateSent = dateSent;
|
||||
this.dateReceived = dateReceived;
|
||||
this.type = type;
|
||||
@ -81,8 +81,8 @@ public abstract class DisplayRecord {
|
||||
|
||||
public abstract SpannableString getDisplayBody();
|
||||
|
||||
public Recipients getRecipients() {
|
||||
return recipients;
|
||||
public Recipient getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
public long getDateSent() {
|
||||
|
@ -27,7 +27,6 @@ import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -45,7 +44,7 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
|
||||
private final Context context;
|
||||
private final int partCount;
|
||||
|
||||
public MediaMmsMessageRecord(Context context, long id, Recipients recipients,
|
||||
public MediaMmsMessageRecord(Context context, long id, Recipient conversationRecipient,
|
||||
Recipient individualRecipient, int recipientDeviceId,
|
||||
long dateSent, long dateReceived, int receiptCount,
|
||||
long threadId, Body body,
|
||||
@ -55,7 +54,7 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
|
||||
List<NetworkFailure> failures, int subscriptionId,
|
||||
long expiresIn, long expireStarted)
|
||||
{
|
||||
super(context, id, body, recipients, individualRecipient, recipientDeviceId, dateSent,
|
||||
super(context, id, body, conversationRecipient, individualRecipient, recipientDeviceId, dateSent,
|
||||
dateReceived, threadId, Status.STATUS_NONE, receiptCount, mailbox, mismatches, failures,
|
||||
subscriptionId, expiresIn, expireStarted, slideDeck);
|
||||
|
||||
|
@ -28,7 +28,6 @@ import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.ExpirationUtil;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
|
||||
@ -55,7 +54,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
private final long expiresIn;
|
||||
private final long expireStarted;
|
||||
|
||||
MessageRecord(Context context, long id, Body body, Recipients recipients,
|
||||
MessageRecord(Context context, long id, Body body, Recipient conversationRecipient,
|
||||
Recipient individualRecipient, int recipientDeviceId,
|
||||
long dateSent, long dateReceived, long threadId,
|
||||
int deliveryStatus, int receiptCount, long type,
|
||||
@ -63,7 +62,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
||||
List<NetworkFailure> networkFailures,
|
||||
int subscriptionId, long expiresIn, long expireStarted)
|
||||
{
|
||||
super(context, body, recipients, dateSent, dateReceived, threadId, deliveryStatus, receiptCount,
|
||||
super(context, body, conversationRecipient, dateSent, dateReceived, threadId, deliveryStatus, receiptCount,
|
||||
type);
|
||||
this.id = id;
|
||||
this.individualRecipient = individualRecipient;
|
||||
|
@ -9,7 +9,6 @@ import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -17,14 +16,14 @@ public abstract class MmsMessageRecord extends MessageRecord {
|
||||
|
||||
private final @NonNull SlideDeck slideDeck;
|
||||
|
||||
MmsMessageRecord(Context context, long id, Body body, Recipients recipients,
|
||||
MmsMessageRecord(Context context, long id, Body body, Recipient conversationRecipient,
|
||||
Recipient individualRecipient, int recipientDeviceId, long dateSent,
|
||||
long dateReceived, long threadId, int deliveryStatus, int receiptCount,
|
||||
long type, List<IdentityKeyMismatch> mismatches,
|
||||
List<NetworkFailure> networkFailures, int subscriptionId, long expiresIn,
|
||||
long expireStarted, @NonNull SlideDeck slideDeck)
|
||||
{
|
||||
super(context, id, body, recipients, individualRecipient, recipientDeviceId, dateSent, dateReceived, threadId, deliveryStatus, receiptCount, type, mismatches, networkFailures, subscriptionId, expiresIn, expireStarted);
|
||||
super(context, id, body, conversationRecipient, individualRecipient, recipientDeviceId, dateSent, dateReceived, threadId, deliveryStatus, receiptCount, type, mismatches, networkFailures, subscriptionId, expiresIn, expireStarted);
|
||||
this.slideDeck = slideDeck;
|
||||
}
|
||||
|
||||
|
@ -20,13 +20,12 @@ import android.content.Context;
|
||||
import android.text.SpannableString;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase.Status;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase.Status;
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
@ -46,14 +45,14 @@ public class NotificationMmsMessageRecord extends MmsMessageRecord {
|
||||
private final int status;
|
||||
private final byte[] transactionId;
|
||||
|
||||
public NotificationMmsMessageRecord(Context context, long id, Recipients recipients,
|
||||
public NotificationMmsMessageRecord(Context context, long id, Recipient conversationRecipient,
|
||||
Recipient individualRecipient, int recipientDeviceId,
|
||||
long dateSent, long dateReceived, int receiptCount,
|
||||
long threadId, byte[] contentLocation, long messageSize,
|
||||
long expiry, int status, byte[] transactionId, long mailbox,
|
||||
int subscriptionId, SlideDeck slideDeck)
|
||||
{
|
||||
super(context, id, new Body("", true), recipients, individualRecipient, recipientDeviceId,
|
||||
super(context, id, new Body("", true), conversationRecipient, individualRecipient, recipientDeviceId,
|
||||
dateSent, dateReceived, threadId, Status.STATUS_NONE, receiptCount, mailbox,
|
||||
new LinkedList<IdentityKeyMismatch>(), new LinkedList<NetworkFailure>(), subscriptionId,
|
||||
0, 0, slideDeck);
|
||||
|
@ -26,7 +26,6 @@ import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||
import org.thoughtcrime.securesms.database.documents.NetworkFailure;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -41,7 +40,7 @@ import java.util.List;
|
||||
public class SmsMessageRecord extends MessageRecord {
|
||||
|
||||
public SmsMessageRecord(Context context, long id,
|
||||
Body body, Recipients recipients,
|
||||
Body body, Recipient recipient,
|
||||
Recipient individualRecipient,
|
||||
int recipientDeviceId,
|
||||
long dateSent, long dateReceived,
|
||||
@ -50,7 +49,7 @@ public class SmsMessageRecord extends MessageRecord {
|
||||
int status, List<IdentityKeyMismatch> mismatches,
|
||||
int subscriptionId, long expiresIn, long expireStarted)
|
||||
{
|
||||
super(context, id, body, recipients, individualRecipient, recipientDeviceId,
|
||||
super(context, id, body, recipient, individualRecipient, recipientDeviceId,
|
||||
dateSent, dateReceived, threadId, status, receiptCount, type,
|
||||
mismatches, new LinkedList<NetworkFailure>(), subscriptionId,
|
||||
expiresIn, expireStarted);
|
||||
|
@ -28,7 +28,7 @@ import android.text.style.StyleSpan;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsColumns;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.ExpirationUtil;
|
||||
|
||||
/**
|
||||
@ -49,11 +49,11 @@ public class ThreadRecord extends DisplayRecord {
|
||||
private final long lastSeen;
|
||||
|
||||
public ThreadRecord(@NonNull Context context, @NonNull Body body, @Nullable Uri snippetUri,
|
||||
@NonNull Recipients recipients, long date, long count, boolean read,
|
||||
@NonNull Recipient recipient, long date, long count, boolean read,
|
||||
long threadId, int receiptCount, int status, long snippetType,
|
||||
int distributionType, boolean archived, long expiresIn, long lastSeen)
|
||||
{
|
||||
super(context, body, recipients, date, date, threadId, status, receiptCount, snippetType);
|
||||
super(context, body, recipient, date, date, threadId, status, receiptCount, snippetType);
|
||||
this.context = context.getApplicationContext();
|
||||
this.snippetUri = snippetUri;
|
||||
this.count = count;
|
||||
@ -98,13 +98,13 @@ public class ThreadRecord extends DisplayRecord {
|
||||
} else if (SmsDatabase.Types.isMissedCall(type)) {
|
||||
return emphasisAdded(context.getString(org.thoughtcrime.securesms.R.string.ThreadRecord_missed_call));
|
||||
} else if (SmsDatabase.Types.isJoinedType(type)) {
|
||||
return emphasisAdded(context.getString(R.string.ThreadRecord_s_is_on_signal, getRecipients().getPrimaryRecipient().toShortString()));
|
||||
return emphasisAdded(context.getString(R.string.ThreadRecord_s_is_on_signal, getRecipient().toShortString()));
|
||||
} else if (SmsDatabase.Types.isExpirationTimerUpdate(type)) {
|
||||
String time = ExpirationUtil.getExpirationDisplayValue(context, (int) (getExpiresIn() / 1000));
|
||||
return emphasisAdded(context.getString(R.string.ThreadRecord_disappearing_message_time_updated_to_s, time));
|
||||
} else if (SmsDatabase.Types.isIdentityUpdate(type)) {
|
||||
if (getRecipients().isGroupRecipient()) return emphasisAdded(context.getString(R.string.ThreadRecord_safety_number_changed));
|
||||
else return emphasisAdded(context.getString(R.string.ThreadRecord_your_safety_number_with_s_has_changed, getRecipients().getPrimaryRecipient().toShortString()));
|
||||
if (getRecipient().isGroupRecipient()) return emphasisAdded(context.getString(R.string.ThreadRecord_safety_number_changed));
|
||||
else return emphasisAdded(context.getString(R.string.ThreadRecord_your_safety_number_with_s_has_changed, getRecipient().toShortString()));
|
||||
} else if (SmsDatabase.Types.isIdentityVerified(type)) {
|
||||
return emphasisAdded(context.getString(R.string.ThreadRecord_you_marked_verified));
|
||||
} else if (SmsDatabase.Types.isIdentityDefault(type)) {
|
||||
|
@ -15,19 +15,21 @@ import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||
import org.thoughtcrime.securesms.providers.SingleUseBlobProvider;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.MediaUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
@ -40,23 +42,93 @@ public class GroupManager {
|
||||
@NonNull MasterSecret masterSecret,
|
||||
@NonNull Set<Recipient> members,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name)
|
||||
throws InvalidNumberException
|
||||
@Nullable String name,
|
||||
boolean mms)
|
||||
{
|
||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
final byte[] groupId = groupDatabase.allocateGroupId();
|
||||
final Set<Address> memberAddresses = getMemberAddresses(context, members);
|
||||
final String groupId = GroupUtil.getEncodedId(groupDatabase.allocateGroupId(), mms);
|
||||
final Set<Address> memberAddresses = getMemberAddresses(members);
|
||||
|
||||
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
||||
groupDatabase.create(groupId, name, new LinkedList<>(memberAddresses), null, null);
|
||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||
return sendGroupUpdate(context, masterSecret, groupId, memberAddresses, name, avatarBytes);
|
||||
|
||||
if (!mms) {
|
||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||
return sendGroupUpdate(context, masterSecret, groupId, memberAddresses, name, avatarBytes);
|
||||
} else {
|
||||
Recipient groupRecipient = RecipientFactory.getRecipientFor(context, Address.fromSerialized(groupId), true);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION);
|
||||
return new GroupActionResult(groupRecipient, threadId);
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<Address> getMemberAddresses(Context context, Collection<Recipient> recipients)
|
||||
public static GroupActionResult updateGroup(@NonNull Context context,
|
||||
@NonNull MasterSecret masterSecret,
|
||||
@NonNull String groupId,
|
||||
@NonNull Set<Recipient> members,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name)
|
||||
throws InvalidNumberException
|
||||
{
|
||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
final Set<Address> memberAddresses = getMemberAddresses(members);
|
||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||
|
||||
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
||||
groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
|
||||
groupDatabase.updateTitle(groupId, name);
|
||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||
|
||||
if (!GroupUtil.isMmsGroup(groupId)) {
|
||||
return sendGroupUpdate(context, masterSecret, groupId, memberAddresses, name, avatarBytes);
|
||||
} else {
|
||||
Recipient groupRecipient = RecipientFactory.getRecipientFor(context, Address.fromSerialized(groupId), true);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient);
|
||||
return new GroupActionResult(groupRecipient, threadId);
|
||||
}
|
||||
}
|
||||
|
||||
private static GroupActionResult sendGroupUpdate(@NonNull Context context,
|
||||
@NonNull MasterSecret masterSecret,
|
||||
@NonNull String groupId,
|
||||
@NonNull Set<Address> members,
|
||||
@Nullable String groupName,
|
||||
@Nullable byte[] avatar)
|
||||
{
|
||||
try {
|
||||
Attachment avatarAttachment = null;
|
||||
Address groupAddress = Address.fromSerialized(groupId);
|
||||
Recipient groupRecipient = RecipientFactory.getRecipientFor(context, groupAddress, false);
|
||||
|
||||
List<String> numbers = new LinkedList<>();
|
||||
|
||||
for (Address member : members) {
|
||||
numbers.add(member.serialize());
|
||||
}
|
||||
|
||||
GroupContext.Builder groupContextBuilder = GroupContext.newBuilder()
|
||||
.setId(ByteString.copyFrom(GroupUtil.getDecodedId(groupId)))
|
||||
.setType(GroupContext.Type.UPDATE)
|
||||
.addAllMembers(numbers);
|
||||
if (groupName != null) groupContextBuilder.setName(groupName);
|
||||
GroupContext groupContext = groupContextBuilder.build();
|
||||
|
||||
if (avatar != null) {
|
||||
Uri avatarUri = SingleUseBlobProvider.getInstance().createUri(avatar);
|
||||
avatarAttachment = new UriAttachment(avatarUri, MediaUtil.IMAGE_PNG, AttachmentDatabase.TRANSFER_PROGRESS_DONE, avatar.length, null, false);
|
||||
}
|
||||
|
||||
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(groupRecipient, groupContext, avatarAttachment, System.currentTimeMillis(), 0);
|
||||
long threadId = MessageSender.send(context, masterSecret, outgoingMessage, -1, false, null);
|
||||
|
||||
return new GroupActionResult(groupRecipient, threadId);
|
||||
} catch (IOException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<Address> getMemberAddresses(Collection<Recipient> recipients) {
|
||||
final Set<Address> results = new HashSet<>();
|
||||
for (Recipient recipient : recipients) {
|
||||
results.add(recipient.getAddress());
|
||||
@ -65,71 +137,16 @@ public class GroupManager {
|
||||
return results;
|
||||
}
|
||||
|
||||
public static GroupActionResult updateGroup(@NonNull Context context,
|
||||
@NonNull MasterSecret masterSecret,
|
||||
@NonNull byte[] groupId,
|
||||
@NonNull Set<Recipient> members,
|
||||
@Nullable Bitmap avatar,
|
||||
@Nullable String name)
|
||||
throws InvalidNumberException
|
||||
{
|
||||
final GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
final Set<Address> memberAddresses = getMemberAddresses(context, members);
|
||||
final byte[] avatarBytes = BitmapUtil.toByteArray(avatar);
|
||||
|
||||
memberAddresses.add(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
|
||||
groupDatabase.updateMembers(groupId, new LinkedList<>(memberAddresses));
|
||||
groupDatabase.updateTitle(groupId, name);
|
||||
groupDatabase.updateAvatar(groupId, avatarBytes);
|
||||
|
||||
return sendGroupUpdate(context, masterSecret, groupId, memberAddresses, name, avatarBytes);
|
||||
}
|
||||
|
||||
private static GroupActionResult sendGroupUpdate(@NonNull Context context,
|
||||
@NonNull MasterSecret masterSecret,
|
||||
@NonNull byte[] groupId,
|
||||
@NonNull Set<Address> members,
|
||||
@Nullable String groupName,
|
||||
@Nullable byte[] avatar)
|
||||
{
|
||||
Attachment avatarAttachment = null;
|
||||
Address groupAddress = Address.fromSerialized(GroupUtil.getEncodedId(groupId));
|
||||
Recipients groupRecipient = RecipientFactory.getRecipientsFor(context, new Address[]{groupAddress}, false);
|
||||
|
||||
List<String> numbers = new LinkedList<>();
|
||||
|
||||
for (Address member : members) {
|
||||
numbers.add(member.serialize());
|
||||
}
|
||||
|
||||
GroupContext.Builder groupContextBuilder = GroupContext.newBuilder()
|
||||
.setId(ByteString.copyFrom(groupId))
|
||||
.setType(GroupContext.Type.UPDATE)
|
||||
.addAllMembers(numbers);
|
||||
if (groupName != null) groupContextBuilder.setName(groupName);
|
||||
GroupContext groupContext = groupContextBuilder.build();
|
||||
|
||||
if (avatar != null) {
|
||||
Uri avatarUri = SingleUseBlobProvider.getInstance().createUri(avatar);
|
||||
avatarAttachment = new UriAttachment(avatarUri, MediaUtil.IMAGE_PNG, AttachmentDatabase.TRANSFER_PROGRESS_DONE, avatar.length, null, false);
|
||||
}
|
||||
|
||||
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(groupRecipient, groupContext, avatarAttachment, System.currentTimeMillis(), 0);
|
||||
long threadId = MessageSender.send(context, masterSecret, outgoingMessage, -1, false, null);
|
||||
|
||||
return new GroupActionResult(groupRecipient, threadId);
|
||||
}
|
||||
|
||||
public static class GroupActionResult {
|
||||
private Recipients groupRecipient;
|
||||
private long threadId;
|
||||
private Recipient groupRecipient;
|
||||
private long threadId;
|
||||
|
||||
public GroupActionResult(Recipients groupRecipient, long threadId) {
|
||||
public GroupActionResult(Recipient groupRecipient, long threadId) {
|
||||
this.groupRecipient = groupRecipient;
|
||||
this.threadId = threadId;
|
||||
}
|
||||
|
||||
public Recipients getGroupRecipient() {
|
||||
public Recipient getGroupRecipient() {
|
||||
return groupRecipient;
|
||||
}
|
||||
|
||||
|
@ -21,8 +21,8 @@ import org.thoughtcrime.securesms.jobs.PushGroupUpdateJob;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.sms.IncomingGroupMessage;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
@ -60,7 +60,7 @@ public class GroupMessageProcessor {
|
||||
|
||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||
SignalServiceGroup group = message.getGroupInfo().get();
|
||||
byte[] id = group.getGroupId();
|
||||
String id = GroupUtil.getEncodedId(group.getGroupId(), false);
|
||||
GroupRecord record = database.getGroup(id);
|
||||
|
||||
if (record != null && group.getType() == Type.UPDATE) {
|
||||
@ -84,7 +84,7 @@ public class GroupMessageProcessor {
|
||||
boolean outgoing)
|
||||
{
|
||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||
byte[] id = group.getGroupId();
|
||||
String id = GroupUtil.getEncodedId(group.getGroupId(), false);
|
||||
GroupContext.Builder builder = createGroupContext(group);
|
||||
builder.setType(GroupContext.Type.UPDATE);
|
||||
|
||||
@ -113,7 +113,7 @@ public class GroupMessageProcessor {
|
||||
{
|
||||
|
||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||
byte[] id = group.getGroupId();
|
||||
String id = GroupUtil.getEncodedId(group.getGroupId(), false);
|
||||
|
||||
Set<Address> recordMembers = new HashSet<>(groupRecord.getMembers());
|
||||
Set<Address> messageMembers = new HashSet<>();
|
||||
@ -185,7 +185,7 @@ public class GroupMessageProcessor {
|
||||
boolean outgoing)
|
||||
{
|
||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||
byte[] id = group.getGroupId();
|
||||
String id = GroupUtil.getEncodedId(group.getGroupId(), false);
|
||||
List<Address> members = record.getMembers();
|
||||
|
||||
GroupContext.Builder builder = createGroupContext(group);
|
||||
@ -217,10 +217,10 @@ public class GroupMessageProcessor {
|
||||
try {
|
||||
if (outgoing) {
|
||||
MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
|
||||
Address addres = Address.fromExternal(context, GroupUtil.getEncodedId(group.getGroupId()));
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {addres}, false);
|
||||
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(recipients, storage, null, envelope.getTimestamp(), 0);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||
Address addres = Address.fromExternal(context, GroupUtil.getEncodedId(group.getGroupId(), false));
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, addres, false);
|
||||
OutgoingGroupMediaMessage outgoingMessage = new OutgoingGroupMediaMessage(recipient, storage, null, envelope.getTimestamp(), 0);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
long messageId = mmsDatabase.insertMessageOutbox(masterSecret, outgoingMessage, threadId, false, null);
|
||||
|
||||
mmsDatabase.markAsSent(messageId, true);
|
||||
|
@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.mms.AttachmentStreamUriLoader.AttachmentModel;
|
||||
import org.thoughtcrime.securesms.util.BitmapDecodingException;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.Hex;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
||||
@ -54,8 +55,9 @@ public class AvatarDownloadJob extends MasterSecretJob implements InjectableType
|
||||
|
||||
@Override
|
||||
public void onRun(MasterSecret masterSecret) throws IOException {
|
||||
String encodeId = GroupUtil.getEncodedId(groupId, false);
|
||||
GroupDatabase database = DatabaseFactory.getGroupDatabase(context);
|
||||
GroupDatabase.GroupRecord record = database.getGroup(groupId);
|
||||
GroupDatabase.GroupRecord record = database.getGroup(encodeId);
|
||||
File attachment = null;
|
||||
|
||||
try {
|
||||
@ -82,7 +84,7 @@ public class AvatarDownloadJob extends MasterSecretJob implements InjectableType
|
||||
InputStream inputStream = receiver.retrieveAttachment(pointer, attachment, MAX_AVATAR_SIZE);
|
||||
Bitmap avatar = BitmapUtil.createScaledBitmap(context, new AttachmentModel(attachment, key), 500, 500);
|
||||
|
||||
database.updateAvatar(groupId, avatar);
|
||||
database.updateAvatar(encodeId, avatar);
|
||||
inputStream.close();
|
||||
}
|
||||
} catch (BitmapDecodingException | NonSuccessfulResponseCodeException | InvalidMessageException e) {
|
||||
|
@ -8,10 +8,9 @@ import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.crypto.SecurityEvent;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.util.DirectoryHelper;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
||||
import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException;
|
||||
@ -20,7 +19,7 @@ import java.io.IOException;
|
||||
|
||||
public class DirectoryRefreshJob extends ContextJob {
|
||||
|
||||
@Nullable private transient Recipients recipients;
|
||||
@Nullable private transient Recipient recipient;
|
||||
@Nullable private transient MasterSecret masterSecret;
|
||||
|
||||
public DirectoryRefreshJob(@NonNull Context context) {
|
||||
@ -29,14 +28,14 @@ public class DirectoryRefreshJob extends ContextJob {
|
||||
|
||||
public DirectoryRefreshJob(@NonNull Context context,
|
||||
@Nullable MasterSecret masterSecret,
|
||||
@Nullable Recipients recipients)
|
||||
@Nullable Recipient recipient)
|
||||
{
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withGroupId(DirectoryRefreshJob.class.getSimpleName())
|
||||
.withRequirement(new NetworkRequirement(context))
|
||||
.create());
|
||||
|
||||
this.recipients = recipients;
|
||||
this.recipient = recipient;
|
||||
this.masterSecret = masterSecret;
|
||||
}
|
||||
|
||||
@ -51,10 +50,10 @@ public class DirectoryRefreshJob extends ContextJob {
|
||||
|
||||
try {
|
||||
wakeLock.acquire();
|
||||
if (recipients == null) {
|
||||
if (recipient == null) {
|
||||
DirectoryHelper.refreshDirectory(context, KeyCachingService.getMasterSecret(context));
|
||||
} else {
|
||||
DirectoryHelper.refreshDirectoryFor(context, masterSecret, recipients);
|
||||
DirectoryHelper.refreshDirectoryFor(context, masterSecret, recipient);
|
||||
}
|
||||
SecurityEvent.broadcastSecurityUpdateEvent(context);
|
||||
} finally {
|
||||
|
@ -14,6 +14,7 @@ import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.attachments.UriAttachment;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
||||
@ -28,6 +29,7 @@ import org.thoughtcrime.securesms.mms.PartParser;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.providers.SingleUseBlobProvider;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
||||
@ -39,8 +41,10 @@ import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class MmsDownloadJob extends MasterSecretJob {
|
||||
@ -88,6 +92,10 @@ public class MmsDownloadJob extends MasterSecretJob {
|
||||
throw new MmsException("Notification content location was null.");
|
||||
}
|
||||
|
||||
if (!TextSecurePreferences.isPushRegistered(context)) {
|
||||
throw new MmsException("Not registered");
|
||||
}
|
||||
|
||||
database.markDownloadState(messageId, MmsDatabase.Status.DOWNLOAD_CONNECTING);
|
||||
|
||||
String contentLocation = notification.get().getContentLocation();
|
||||
@ -161,28 +169,33 @@ public class MmsDownloadJob extends MasterSecretJob {
|
||||
{
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
SingleUseBlobProvider provider = SingleUseBlobProvider.getInstance();
|
||||
String from = null;
|
||||
List<String> to = new LinkedList<>();
|
||||
List<String> cc = new LinkedList<>();
|
||||
Optional<Address> group = Optional.absent();
|
||||
Set<Address> members = new HashSet<>();
|
||||
String body = null;
|
||||
List<Attachment> attachments = new LinkedList<>();
|
||||
|
||||
Address from;
|
||||
|
||||
if (retrieved.getFrom() != null) {
|
||||
from = Util.toIsoString(retrieved.getFrom().getTextString());
|
||||
from = Address.fromExternal(context, Util.toIsoString(retrieved.getFrom().getTextString()));
|
||||
} else {
|
||||
from = Address.UNKNOWN;
|
||||
}
|
||||
|
||||
if (retrieved.getTo() != null) {
|
||||
for (EncodedStringValue toValue : retrieved.getTo()) {
|
||||
to.add(Util.toIsoString(toValue.getTextString()));
|
||||
members.add(Address.fromExternal(context, Util.toIsoString(toValue.getTextString())));
|
||||
}
|
||||
}
|
||||
|
||||
if (retrieved.getCc() != null) {
|
||||
for (EncodedStringValue ccValue : retrieved.getCc()) {
|
||||
cc.add(Util.toIsoString(ccValue.getTextString()));
|
||||
members.add(Address.fromExternal(context, Util.toIsoString(ccValue.getTextString())));
|
||||
}
|
||||
}
|
||||
|
||||
members.add(Address.fromExternal(context, TextSecurePreferences.getLocalNumber(context)));
|
||||
|
||||
if (retrieved.getBody() != null) {
|
||||
body = PartParser.getMessageText(retrieved.getBody());
|
||||
PduBody media = PartParser.getSupportedMediaParts(retrieved.getBody());
|
||||
@ -203,9 +216,11 @@ public class MmsDownloadJob extends MasterSecretJob {
|
||||
}
|
||||
}
|
||||
|
||||
if (members.size() > 1) {
|
||||
group = Optional.of(Address.fromSerialized(DatabaseFactory.getGroupDatabase(context).getOrCreateGroupForMembers(new LinkedList<>(members), true)));
|
||||
}
|
||||
|
||||
|
||||
IncomingMediaMessage message = new IncomingMediaMessage(context, from, to, cc, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false);
|
||||
IncomingMediaMessage message = new IncomingMediaMessage(from, group, body, retrieved.getDate() * 1000L, attachments, subscriptionId, 0, false);
|
||||
Optional<InsertResult> insertResult = database.insertMessageInbox(new MasterSecretUnion(masterSecret),
|
||||
message, contentLocation, threadId);
|
||||
|
||||
|
@ -13,8 +13,8 @@ import org.thoughtcrime.securesms.ApplicationContext;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
|
||||
@ -86,7 +86,7 @@ public class MmsReceiveJob extends ContextJob {
|
||||
|
||||
private boolean isBlocked(GenericPdu pdu) {
|
||||
if (pdu.getFrom() != null && pdu.getFrom().getTextString() != null) {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, Util.toIsoString(pdu.getFrom().getTextString()))}, false);
|
||||
Recipient recipients = RecipientFactory.getRecipientFor(context, Address.fromExternal(context, Util.toIsoString(pdu.getFrom().getTextString())), false);
|
||||
return recipients.isBlocked();
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.mms.CompatMmsConnection;
|
||||
import org.thoughtcrime.securesms.mms.MediaConstraints;
|
||||
@ -33,11 +34,12 @@ import org.thoughtcrime.securesms.mms.MmsSendResult;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
|
||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||
import org.thoughtcrime.securesms.util.Hex;
|
||||
import org.thoughtcrime.securesms.util.NumberUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
||||
@ -171,16 +173,28 @@ public class MmsSendJob extends SendJob {
|
||||
{
|
||||
SendReq req = new SendReq();
|
||||
String lineNumber = Utils.getMyPhoneNumber(context);
|
||||
Address[] numbers = message.getRecipients().getAddresses();
|
||||
Address destination = message.getRecipient().getAddress();
|
||||
MediaConstraints mediaConstraints = MediaConstraints.getMmsMediaConstraints(message.getSubscriptionId());
|
||||
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
|
||||
|
||||
if (!TextUtils.isEmpty(lineNumber)) {
|
||||
req.setFrom(new EncodedStringValue(lineNumber));
|
||||
} else {
|
||||
req.setFrom(new EncodedStringValue(TextSecurePreferences.getLocalNumber(context)));
|
||||
}
|
||||
|
||||
for (Address recipient : numbers) {
|
||||
req.addTo(new EncodedStringValue(recipient.serialize()));
|
||||
if (destination.isMmsGroup()) {
|
||||
List<Recipient> members = DatabaseFactory.getGroupDatabase(context).getGroupMembers(destination.toGroupString(), false);
|
||||
|
||||
for (Recipient member : members) {
|
||||
if (message.getDistributionType() == ThreadDatabase.DistributionTypes.BROADCAST) {
|
||||
req.addBcc(new EncodedStringValue(member.getAddress().serialize()));
|
||||
} else {
|
||||
req.addTo(new EncodedStringValue(member.getAddress().serialize()));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
req.addTo(new EncodedStringValue(destination.serialize()));
|
||||
}
|
||||
|
||||
req.setDate(System.currentTimeMillis() / 1000);
|
||||
@ -266,11 +280,11 @@ public class MmsSendJob extends SendJob {
|
||||
}
|
||||
|
||||
private void notifyMediaMessageDeliveryFailed(Context context, long messageId) {
|
||||
long threadId = DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId);
|
||||
Recipients recipients = DatabaseFactory.getThreadDatabase(context).getRecipientsForThreadId(threadId);
|
||||
long threadId = DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId);
|
||||
Recipient recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
|
||||
|
||||
if (recipients != null) {
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, recipients, threadId);
|
||||
if (recipient != null) {
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, recipient, threadId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.BlockedRe
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
@ -50,11 +50,11 @@ public class MultiDeviceBlockedUpdateJob extends MasterSecretJob implements Inje
|
||||
BlockedReader reader = database.readerForBlocked(database.getBlocked());
|
||||
List<String> blocked = new LinkedList<>();
|
||||
|
||||
Recipients recipients;
|
||||
Recipient recipient;
|
||||
|
||||
while ((recipients = reader.getNext()) != null) {
|
||||
if (recipients.isSingleRecipient() && !recipients.isGroupRecipient()) {
|
||||
blocked.add(recipients.getPrimaryRecipient().getAddress().serialize());
|
||||
while ((recipient = reader.getNext()) != null) {
|
||||
if (!recipient.isGroupRecipient()) {
|
||||
blocked.add(recipient.getAddress().serialize());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,8 +34,8 @@ import org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.service.WebRtcCallService;
|
||||
import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage;
|
||||
@ -80,7 +80,6 @@ import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptM
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
|
||||
import org.whispersystems.signalservice.api.messages.multidevice.VerifiedMessage;
|
||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -162,7 +161,7 @@ public class PushDecryptJob extends ContextJob {
|
||||
else if (message.getAttachments().isPresent()) handleMediaMessage(masterSecret, envelope, message, smsMessageId);
|
||||
else handleTextMessage(masterSecret, envelope, message, smsMessageId);
|
||||
|
||||
if (message.getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(message.getGroupInfo().get().getGroupId())) {
|
||||
if (message.getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId(), false))) {
|
||||
handleUnknownGroupMessage(envelope, message.getGroupInfo().get());
|
||||
}
|
||||
} else if (content.getSyncMessage().isPresent()) {
|
||||
@ -322,15 +321,15 @@ public class PushDecryptJob extends ContextJob {
|
||||
@NonNull Optional<Long> smsMessageId)
|
||||
{
|
||||
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
Recipients recipients = getSyncMessageDestination(message);
|
||||
OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipients, "", -1);
|
||||
Recipient recipient = getSyncMessageDestination(message);
|
||||
OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipient, "", -1);
|
||||
OutgoingEndSessionMessage outgoingEndSessionMessage = new OutgoingEndSessionMessage(outgoingTextMessage);
|
||||
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
|
||||
if (recipients.isSingleRecipient() && !recipients.isGroupRecipient()) {
|
||||
if (!recipient.isGroupRecipient()) {
|
||||
SessionStore sessionStore = new TextSecureSessionStore(context);
|
||||
sessionStore.deleteAllSessions(recipients.getPrimaryRecipient().getAddress().toPhoneString());
|
||||
sessionStore.deleteAllSessions(recipient.getAddress().toPhoneString());
|
||||
|
||||
SecurityEvent.broadcastSecurityUpdateEvent(context);
|
||||
|
||||
@ -373,11 +372,9 @@ public class PushDecryptJob extends ContextJob {
|
||||
throws MmsException
|
||||
{
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
||||
Recipients recipients = getMessageDestination(envelope, message);
|
||||
Recipient recipient = getMessageDestination(envelope, message);
|
||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret,
|
||||
Address.fromExternal(context, envelope.getSource()),
|
||||
Address.fromSerialized(localNumber),
|
||||
message.getTimestamp(), -1,
|
||||
message.getExpiresInSeconds() * 1000, true,
|
||||
Optional.fromNullable(envelope.getRelay()),
|
||||
@ -388,7 +385,7 @@ public class PushDecryptJob extends ContextJob {
|
||||
|
||||
database.insertSecureDecryptedMessageInbox(masterSecret, mediaMessage, -1);
|
||||
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(context).setExpireMessages(recipients, message.getExpiresInSeconds());
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(context).setExpireMessages(recipient, message.getExpiresInSeconds());
|
||||
|
||||
if (smsMessageId.isPresent()) {
|
||||
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
|
||||
@ -423,7 +420,7 @@ public class PushDecryptJob extends ContextJob {
|
||||
threadId = handleSynchronizeSentTextMessage(masterSecret, message, smsMessageId);
|
||||
}
|
||||
|
||||
if (message.getMessage().getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(message.getMessage().getGroupInfo().get().getGroupId())) {
|
||||
if (message.getMessage().getGroupInfo().isPresent() && groupDatabase.isUnknownGroup(GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get().getGroupId(), false))) {
|
||||
handleUnknownGroupMessage(envelope, message.getMessage().getGroupInfo().get());
|
||||
}
|
||||
|
||||
@ -490,11 +487,9 @@ public class PushDecryptJob extends ContextJob {
|
||||
throws MmsException
|
||||
{
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
String localNumber = TextSecurePreferences.getLocalNumber(context);
|
||||
Recipients recipients = getMessageDestination(envelope, message);
|
||||
Recipient recipient = getMessageDestination(envelope, message);
|
||||
IncomingMediaMessage mediaMessage = new IncomingMediaMessage(masterSecret,
|
||||
Address.fromExternal(context, envelope.getSource()),
|
||||
Address.fromSerialized(localNumber),
|
||||
message.getTimestamp(), -1,
|
||||
message.getExpiresInSeconds() * 1000, false,
|
||||
Optional.fromNullable(envelope.getRelay()),
|
||||
@ -502,7 +497,7 @@ public class PushDecryptJob extends ContextJob {
|
||||
message.getGroupInfo(),
|
||||
message.getAttachments());
|
||||
|
||||
if (message.getExpiresInSeconds() != recipients.getExpireMessages()) {
|
||||
if (message.getExpiresInSeconds() != recipient.getExpireMessages()) {
|
||||
handleExpirationUpdate(masterSecret, envelope, message, Optional.<Long>absent());
|
||||
}
|
||||
|
||||
@ -537,18 +532,18 @@ public class PushDecryptJob extends ContextJob {
|
||||
throws MmsException
|
||||
{
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
Recipients recipients = getSyncMessageDestination(message);
|
||||
Recipient recipient = getSyncMessageDestination(message);
|
||||
|
||||
OutgoingExpirationUpdateMessage expirationUpdateMessage = new OutgoingExpirationUpdateMessage(recipients,
|
||||
OutgoingExpirationUpdateMessage expirationUpdateMessage = new OutgoingExpirationUpdateMessage(recipient,
|
||||
message.getTimestamp(),
|
||||
message.getMessage().getExpiresInSeconds() * 1000);
|
||||
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
long messageId = database.insertMessageOutbox(masterSecret, expirationUpdateMessage, threadId, false, null);
|
||||
|
||||
database.markAsSent(messageId, true);
|
||||
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(context).setExpireMessages(recipients, message.getMessage().getExpiresInSeconds());
|
||||
DatabaseFactory.getRecipientPreferenceDatabase(context).setExpireMessages(recipient, message.getMessage().getExpiresInSeconds());
|
||||
|
||||
if (smsMessageId.isPresent()) {
|
||||
DatabaseFactory.getSmsDatabase(context).deleteMessage(smsMessageId.get());
|
||||
@ -563,7 +558,7 @@ public class PushDecryptJob extends ContextJob {
|
||||
throws MmsException
|
||||
{
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
Recipients recipients = getSyncMessageDestination(message);
|
||||
Recipient recipients = getSyncMessageDestination(message);
|
||||
OutgoingMediaMessage mediaMessage = new OutgoingMediaMessage(recipients, message.getMessage().getBody().orNull(),
|
||||
PointerAttachment.forPointers(masterSecret, message.getMessage().getAttachments()),
|
||||
message.getTimestamp(), -1,
|
||||
@ -611,9 +606,9 @@ public class PushDecryptJob extends ContextJob {
|
||||
{
|
||||
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
String body = message.getBody().isPresent() ? message.getBody().get() : "";
|
||||
Recipients recipients = getMessageDestination(envelope, message);
|
||||
Recipient recipient = getMessageDestination(envelope, message);
|
||||
|
||||
if (message.getExpiresInSeconds() != recipients.getExpireMessages()) {
|
||||
if (message.getExpiresInSeconds() != recipient.getExpireMessages()) {
|
||||
handleExpirationUpdate(masterSecret, envelope, message, Optional.<Long>absent());
|
||||
}
|
||||
|
||||
@ -648,16 +643,16 @@ public class PushDecryptJob extends ContextJob {
|
||||
throws MmsException
|
||||
{
|
||||
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
Recipients recipients = getSyncMessageDestination(message);
|
||||
Recipient recipient = getSyncMessageDestination(message);
|
||||
String body = message.getMessage().getBody().or("");
|
||||
long expiresInMillis = message.getMessage().getExpiresInSeconds() * 1000;
|
||||
OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipients, body, expiresInMillis, -1);
|
||||
OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipient, body, expiresInMillis, -1);
|
||||
|
||||
if (recipients.getExpireMessages() != message.getMessage().getExpiresInSeconds()) {
|
||||
if (recipient.getExpireMessages() != message.getMessage().getExpiresInSeconds()) {
|
||||
handleSynchronizeSentExpirationUpdate(masterSecret, message, Optional.<Long>absent());
|
||||
}
|
||||
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||
long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
long messageId = database.insertMessageOutbox(masterSecret, threadId, outgoingTextMessage, false, message.getTimestamp(), null);
|
||||
|
||||
database.markAsSent(messageId, true);
|
||||
@ -810,19 +805,19 @@ public class PushDecryptJob extends ContextJob {
|
||||
return database.insertMessageInbox(textMessage);
|
||||
}
|
||||
|
||||
private Recipients getSyncMessageDestination(SentTranscriptMessage message) {
|
||||
private Recipient getSyncMessageDestination(SentTranscriptMessage message) {
|
||||
if (message.getMessage().getGroupInfo().isPresent()) {
|
||||
return RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get().getGroupId()))}, false);
|
||||
return RecipientFactory.getRecipientFor(context, Address.fromExternal(context, GroupUtil.getEncodedId(message.getMessage().getGroupInfo().get().getGroupId(), false)), false);
|
||||
} else {
|
||||
return RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, message.getDestination().get())}, false);
|
||||
return RecipientFactory.getRecipientFor(context, Address.fromExternal(context, message.getDestination().get()), false);
|
||||
}
|
||||
}
|
||||
|
||||
private Recipients getMessageDestination(SignalServiceEnvelope envelope, SignalServiceDataMessage message) {
|
||||
private Recipient getMessageDestination(SignalServiceEnvelope envelope, SignalServiceDataMessage message) {
|
||||
if (message.getGroupInfo().isPresent()) {
|
||||
return RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId()))}, false);
|
||||
return RecipientFactory.getRecipientFor(context, Address.fromExternal(context, GroupUtil.getEncodedId(message.getGroupInfo().get().getGroupId(), false)), false);
|
||||
} else {
|
||||
return RecipientFactory.getRecipientsFor(context, new Address[] {Address.fromExternal(context, envelope.getSource())}, false);
|
||||
return RecipientFactory.getRecipientFor(context, Address.fromExternal(context, envelope.getSource()), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,6 @@ import org.thoughtcrime.securesms.mms.OutgoingGroupMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFormattingException;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
@ -138,8 +137,8 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
EncapsulatedExceptions, UndeliverableMessageException
|
||||
{
|
||||
SignalServiceMessageSender messageSender = messageSenderFactory.create();
|
||||
byte[] groupId = GroupUtil.getDecodedId(message.getRecipients().getPrimaryRecipient().getAddress().toGroupString());
|
||||
Recipients recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false);
|
||||
String groupId = message.getRecipient().getAddress().toGroupString();
|
||||
List<Recipient> recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false);
|
||||
MediaConstraints mediaConstraints = MediaConstraints.getPushMediaConstraints();
|
||||
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
|
||||
List<SignalServiceAttachment> attachmentStreams = getAttachmentsFor(masterSecret, scaledAttachments);
|
||||
@ -154,12 +153,12 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
GroupContext groupContext = groupMessage.getGroupContext();
|
||||
SignalServiceAttachment avatar = attachmentStreams.isEmpty() ? null : attachmentStreams.get(0);
|
||||
SignalServiceGroup.Type type = groupMessage.isGroupQuit() ? SignalServiceGroup.Type.QUIT : SignalServiceGroup.Type.UPDATE;
|
||||
SignalServiceGroup group = new SignalServiceGroup(type, groupId, groupContext.getName(), groupContext.getMembersList(), avatar);
|
||||
SignalServiceGroup group = new SignalServiceGroup(type, GroupUtil.getDecodedId(groupId), groupContext.getName(), groupContext.getMembersList(), avatar);
|
||||
SignalServiceDataMessage groupDataMessage = new SignalServiceDataMessage(message.getSentTimeMillis(), group, null, null);
|
||||
|
||||
messageSender.sendMessage(addresses, groupDataMessage);
|
||||
} else {
|
||||
SignalServiceGroup group = new SignalServiceGroup(groupId);
|
||||
SignalServiceGroup group = new SignalServiceGroup(GroupUtil.getDecodedId(groupId));
|
||||
SignalServiceDataMessage groupMessage = new SignalServiceDataMessage(message.getSentTimeMillis(), group,
|
||||
attachmentStreams, message.getBody(), false,
|
||||
(int)(message.getExpiresIn() / 1000),
|
||||
@ -175,10 +174,10 @@ public class PushGroupSendJob extends PushSendJob implements InjectableType {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
private List<SignalServiceAddress> getPushAddresses(Recipients recipients) {
|
||||
private List<SignalServiceAddress> getPushAddresses(List<Recipient> recipients) {
|
||||
List<SignalServiceAddress> addresses = new LinkedList<>();
|
||||
|
||||
for (Recipient recipient : recipients.getRecipientsList()) {
|
||||
for (Recipient recipient : recipients) {
|
||||
addresses.add(getPushAddress(recipient.getAddress()));
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@ import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||
import org.thoughtcrime.securesms.database.GroupDatabase.GroupRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.dependencies.SignalCommunicationModule.SignalMessageSenderFactory;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
||||
@ -59,7 +60,7 @@ public class PushGroupUpdateJob extends ContextJob implements InjectableType {
|
||||
public void onRun() throws IOException, UntrustedIdentityException {
|
||||
SignalServiceMessageSender messageSender = messageSenderFactory.create();
|
||||
GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context);
|
||||
GroupRecord record = groupDatabase.getGroup(groupId);
|
||||
GroupRecord record = groupDatabase.getGroup(GroupUtil.getEncodedId(groupId, false));
|
||||
SignalServiceAttachment avatar = null;
|
||||
|
||||
if (record == null) {
|
||||
|
@ -102,14 +102,14 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
||||
throws RetryLaterException, InsecureFallbackApprovalException, UntrustedIdentityException,
|
||||
UndeliverableMessageException
|
||||
{
|
||||
if (message.getRecipients() == null || message.getRecipients().getPrimaryRecipient() == null) {
|
||||
if (message.getRecipient() == null) {
|
||||
throw new UndeliverableMessageException("No destination address.");
|
||||
}
|
||||
|
||||
SignalServiceMessageSender messageSender = messageSenderFactory.create();
|
||||
|
||||
try {
|
||||
SignalServiceAddress address = getPushAddress(message.getRecipients().getPrimaryRecipient().getAddress());
|
||||
SignalServiceAddress address = getPushAddress(message.getRecipient().getAddress());
|
||||
MediaConstraints mediaConstraints = MediaConstraints.getPushMediaConstraints();
|
||||
List<Attachment> scaledAttachments = scaleAttachments(masterSecret, mediaConstraints, message.getAttachments());
|
||||
List<SignalServiceAttachment> attachmentStreams = getAttachmentsFor(masterSecret, scaledAttachments);
|
||||
|
@ -9,8 +9,8 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
|
||||
import org.thoughtcrime.securesms.database.NotInDirectoryException;
|
||||
import org.thoughtcrime.securesms.database.TextSecureDirectory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.whispersystems.jobqueue.JobManager;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
@ -35,8 +35,8 @@ public abstract class PushReceivedJob extends ContextJob {
|
||||
|
||||
directory.setNumber(contactTokenDetails, true);
|
||||
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {source}, false);
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(context, KeyCachingService.getMasterSecret(context), recipients));
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, source, false);
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(context, KeyCachingService.getMasterSecret(context), recipient));
|
||||
}
|
||||
|
||||
if (envelope.isReceipt()) {
|
||||
@ -49,7 +49,7 @@ public abstract class PushReceivedJob extends ContextJob {
|
||||
}
|
||||
|
||||
private void handleMessage(SignalServiceEnvelope envelope, Address source, boolean sendExplicitReceipt) {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {source}, false);
|
||||
Recipient recipients = RecipientFactory.getRecipientFor(context, source, false);
|
||||
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
|
||||
|
||||
if (!recipients.isBlocked()) {
|
||||
|
@ -15,7 +15,7 @@ import org.thoughtcrime.securesms.events.PartProgressEvent;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
import org.whispersystems.jobqueue.requirements.NetworkRequirement;
|
||||
@ -95,11 +95,11 @@ public abstract class PushSendJob extends SendJob {
|
||||
}
|
||||
|
||||
protected void notifyMediaMessageDeliveryFailed(Context context, long messageId) {
|
||||
long threadId = DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId);
|
||||
Recipients recipients = DatabaseFactory.getThreadDatabase(context).getRecipientsForThreadId(threadId);
|
||||
long threadId = DatabaseFactory.getMmsDatabase(context).getThreadIdForMessage(messageId);
|
||||
Recipient recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
|
||||
|
||||
if (threadId != -1 && recipients != null) {
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, recipients, threadId);
|
||||
if (threadId != -1 && recipient != null) {
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, recipient, threadId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||
import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException;
|
||||
import org.thoughtcrime.securesms.transport.RetryLaterException;
|
||||
@ -66,7 +66,7 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
||||
} catch (InsecureFallbackApprovalException e) {
|
||||
Log.w(TAG, e);
|
||||
database.markAsPendingInsecureSmsFallback(record.getId());
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipients(), record.getThreadId());
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
|
||||
ApplicationContext.getInstance(context).getJobManager().add(new DirectoryRefreshJob(context));
|
||||
} catch (UntrustedIdentityException e) {
|
||||
Log.w(TAG, e);
|
||||
@ -87,11 +87,11 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
||||
public void onCanceled() {
|
||||
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageId);
|
||||
|
||||
long threadId = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageId);
|
||||
Recipients recipients = DatabaseFactory.getThreadDatabase(context).getRecipientsForThreadId(threadId);
|
||||
long threadId = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageId);
|
||||
Recipient recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
|
||||
|
||||
if (threadId != -1 && recipients != null) {
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, recipients, threadId);
|
||||
if (threadId != -1 && recipient != null) {
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, recipient, threadId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,10 +9,8 @@ import android.util.Log;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.service.MessageRetrievalService;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.util.IdentityUtil;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
import org.whispersystems.libsignal.IdentityKey;
|
||||
@ -24,6 +22,7 @@ import org.whispersystems.signalservice.api.push.SignalServiceProfile;
|
||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ -33,14 +32,14 @@ public class RetrieveProfileJob extends ContextJob implements InjectableType {
|
||||
|
||||
@Inject transient SignalServiceMessageReceiver receiver;
|
||||
|
||||
private final Recipients recipients;
|
||||
private final Recipient recipient;
|
||||
|
||||
public RetrieveProfileJob(Context context, Recipients recipients) {
|
||||
public RetrieveProfileJob(Context context, Recipient recipient) {
|
||||
super(context, JobParameters.newBuilder()
|
||||
.withRetryCount(3)
|
||||
.create());
|
||||
|
||||
this.recipients = recipients;
|
||||
this.recipient = recipient;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -49,10 +48,8 @@ public class RetrieveProfileJob extends ContextJob implements InjectableType {
|
||||
@Override
|
||||
public void onRun() throws IOException, InvalidKeyException {
|
||||
try {
|
||||
for (Recipient recipient : recipients) {
|
||||
if (recipient.isGroupRecipient()) handleGroupRecipient(recipient);
|
||||
else handleIndividualRecipient(recipient);
|
||||
}
|
||||
if (recipient.isGroupRecipient()) handleGroupRecipient(recipient);
|
||||
else handleIndividualRecipient(recipient);
|
||||
} catch (InvalidNumberException e) {
|
||||
Log.w(TAG, e);
|
||||
}
|
||||
@ -93,8 +90,7 @@ public class RetrieveProfileJob extends ContextJob implements InjectableType {
|
||||
private void handleGroupRecipient(Recipient group)
|
||||
throws IOException, InvalidKeyException, InvalidNumberException
|
||||
{
|
||||
byte[] groupId = GroupUtil.getDecodedId(group.getAddress().toGroupString());
|
||||
Recipients recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(groupId, false);
|
||||
List<Recipient> recipients = DatabaseFactory.getGroupDatabase(context).getGroupMembers(group.getAddress().toGroupString(), false);
|
||||
|
||||
for (Recipient recipient : recipients) {
|
||||
handleIndividualRecipient(recipient);
|
||||
|
@ -9,13 +9,12 @@ import android.util.Log;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.InsertResult;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.sms.IncomingTextMessage;
|
||||
import org.whispersystems.jobqueue.JobParameters;
|
||||
@ -86,8 +85,8 @@ public class SmsReceiveJob extends ContextJob {
|
||||
|
||||
private boolean isBlocked(IncomingTextMessage message) {
|
||||
if (message.getSender() != null) {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, new Address[] {message.getSender()}, false);
|
||||
return recipients.isBlocked();
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, message.getSender(), false);
|
||||
return recipient.isBlocked();
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -13,13 +13,12 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.EncryptingSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.NetworkOrServiceRequirement;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.ServiceRequirement;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.service.SmsDeliveryListener;
|
||||
import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
||||
import org.thoughtcrime.securesms.util.NumberUtil;
|
||||
@ -54,7 +53,7 @@ public class SmsSendJob extends SendJob {
|
||||
} catch (UndeliverableMessageException ude) {
|
||||
Log.w(TAG, ude);
|
||||
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(record.getId());
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipients(), record.getThreadId());
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,11 +65,11 @@ public class SmsSendJob extends SendJob {
|
||||
@Override
|
||||
public void onCanceled() {
|
||||
Log.w(TAG, "onCanceled()");
|
||||
long threadId = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageId);
|
||||
Recipients recipients = DatabaseFactory.getThreadDatabase(context).getRecipientsForThreadId(threadId);
|
||||
long threadId = DatabaseFactory.getSmsDatabase(context).getThreadIdForMessage(messageId);
|
||||
Recipient recipient = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
|
||||
|
||||
DatabaseFactory.getSmsDatabase(context).markAsSentFailed(messageId);
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, recipients, threadId);
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, recipient, threadId);
|
||||
}
|
||||
|
||||
private void deliver(SmsMessageRecord message)
|
||||
|
@ -86,7 +86,7 @@ public class SmsSentJob extends MasterSecretJob {
|
||||
break;
|
||||
default:
|
||||
database.markAsSentFailed(messageId);
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipients(), record.getThreadId());
|
||||
MessageNotifier.notifyMessageDeliveryFailed(context, record.getRecipient(), record.getThreadId());
|
||||
}
|
||||
} catch (NoSuchMessageException e) {
|
||||
Log.w(TAG, e);
|
||||
|
@ -1,12 +1,9 @@
|
||||
package org.thoughtcrime.securesms.mms;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.attachments.PointerAttachment;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecretUnion;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.MmsAddresses;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||
@ -18,46 +15,39 @@ import java.util.List;
|
||||
public class IncomingMediaMessage {
|
||||
|
||||
private final Address from;
|
||||
private final String body;
|
||||
private final Address groupId;
|
||||
private final String body;
|
||||
private final boolean push;
|
||||
private final long sentTimeMillis;
|
||||
private final int subscriptionId;
|
||||
private final long expiresIn;
|
||||
private final boolean expirationUpdate;
|
||||
|
||||
private final List<Address> to = new LinkedList<>();
|
||||
private final List<Address> cc = new LinkedList<>();
|
||||
private final List<Attachment> attachments = new LinkedList<>();
|
||||
|
||||
public IncomingMediaMessage(Context context, String from, List<String> to, List<String> cc,
|
||||
String body, long sentTimeMillis,
|
||||
List<Attachment> attachments, int subscriptionId,
|
||||
long expiresIn, boolean expirationUpdate)
|
||||
public IncomingMediaMessage(Address from,
|
||||
Optional<Address> groupId,
|
||||
String body,
|
||||
long sentTimeMillis,
|
||||
List<Attachment> attachments,
|
||||
int subscriptionId,
|
||||
long expiresIn,
|
||||
boolean expirationUpdate)
|
||||
{
|
||||
this.from = Address.fromExternal(context, from);
|
||||
this.from = from;
|
||||
this.groupId = groupId.orNull();
|
||||
this.sentTimeMillis = sentTimeMillis;
|
||||
this.body = body;
|
||||
this.groupId = null;
|
||||
this.push = false;
|
||||
this.subscriptionId = subscriptionId;
|
||||
this.expiresIn = expiresIn;
|
||||
this.expirationUpdate = expirationUpdate;
|
||||
|
||||
for (String destination : to) {
|
||||
this.to.add(Address.fromExternal(context, destination));
|
||||
}
|
||||
|
||||
for (String destination : cc) {
|
||||
this.cc.add(Address.fromExternal(context, destination));
|
||||
}
|
||||
|
||||
this.attachments.addAll(attachments);
|
||||
}
|
||||
|
||||
public IncomingMediaMessage(MasterSecretUnion masterSecret,
|
||||
Address from,
|
||||
Address to,
|
||||
long sentTimeMillis,
|
||||
int subscriptionId,
|
||||
long expiresIn,
|
||||
@ -75,10 +65,9 @@ public class IncomingMediaMessage {
|
||||
this.expiresIn = expiresIn;
|
||||
this.expirationUpdate = expirationUpdate;
|
||||
|
||||
if (group.isPresent()) this.groupId = Address.fromSerialized(GroupUtil.getEncodedId(group.get().getGroupId()));
|
||||
if (group.isPresent()) this.groupId = Address.fromSerialized(GroupUtil.getEncodedId(group.get().getGroupId(), false));
|
||||
else this.groupId = null;
|
||||
|
||||
this.to.add(to);
|
||||
this.attachments.addAll(PointerAttachment.forPointers(masterSecret, attachments));
|
||||
}
|
||||
|
||||
@ -90,14 +79,14 @@ public class IncomingMediaMessage {
|
||||
return body;
|
||||
}
|
||||
|
||||
public MmsAddresses getAddresses() {
|
||||
return new MmsAddresses(from, to, cc, new LinkedList<Address>());
|
||||
}
|
||||
|
||||
public List<Attachment> getAttachments() {
|
||||
return attachments;
|
||||
}
|
||||
|
||||
public Address getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
public Address getGroupId() {
|
||||
return groupId;
|
||||
}
|
||||
@ -119,6 +108,6 @@ public class IncomingMediaMessage {
|
||||
}
|
||||
|
||||
public boolean isGroupMessage() {
|
||||
return groupId != null || to.size() > 1 || cc.size() > 0;
|
||||
return groupId != null;
|
||||
}
|
||||
}
|
||||
|
@ -2,14 +2,14 @@ package org.thoughtcrime.securesms.mms;
|
||||
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
public class OutgoingExpirationUpdateMessage extends OutgoingSecureMediaMessage {
|
||||
|
||||
public OutgoingExpirationUpdateMessage(Recipients recipients, long sentTimeMillis, long expiresIn) {
|
||||
super(recipients, "", new LinkedList<Attachment>(), sentTimeMillis,
|
||||
public OutgoingExpirationUpdateMessage(Recipient recipient, long sentTimeMillis, long expiresIn) {
|
||||
super(recipient, "", new LinkedList<Attachment>(), sentTimeMillis,
|
||||
ThreadDatabase.DistributionTypes.CONVERSATION, expiresIn);
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ import android.support.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.Base64;
|
||||
import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext;
|
||||
|
||||
@ -17,26 +17,26 @@ public class OutgoingGroupMediaMessage extends OutgoingSecureMediaMessage {
|
||||
|
||||
private final GroupContext group;
|
||||
|
||||
public OutgoingGroupMediaMessage(@NonNull Recipients recipients,
|
||||
public OutgoingGroupMediaMessage(@NonNull Recipient recipient,
|
||||
@NonNull String encodedGroupContext,
|
||||
@NonNull List<Attachment> avatar,
|
||||
long sentTimeMillis,
|
||||
long expiresIn)
|
||||
throws IOException
|
||||
{
|
||||
super(recipients, encodedGroupContext, avatar, sentTimeMillis,
|
||||
super(recipient, encodedGroupContext, avatar, sentTimeMillis,
|
||||
ThreadDatabase.DistributionTypes.CONVERSATION, expiresIn);
|
||||
|
||||
this.group = GroupContext.parseFrom(Base64.decode(encodedGroupContext));
|
||||
}
|
||||
|
||||
public OutgoingGroupMediaMessage(@NonNull Recipients recipients,
|
||||
public OutgoingGroupMediaMessage(@NonNull Recipient recipient,
|
||||
@NonNull GroupContext group,
|
||||
@Nullable final Attachment avatar,
|
||||
long sentTimeMillis,
|
||||
long expireIn)
|
||||
{
|
||||
super(recipients, Base64.encodeBytes(group.toByteArray()),
|
||||
super(recipient, Base64.encodeBytes(group.toByteArray()),
|
||||
new LinkedList<Attachment>() {{if (avatar != null) add(avatar);}},
|
||||
System.currentTimeMillis(),
|
||||
ThreadDatabase.DistributionTypes.CONVERSATION, expireIn);
|
||||
|
@ -3,13 +3,13 @@ package org.thoughtcrime.securesms.mms;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class OutgoingMediaMessage {
|
||||
|
||||
private final Recipients recipients;
|
||||
private final Recipient recipient;
|
||||
protected final String body;
|
||||
protected final List<Attachment> attachments;
|
||||
private final long sentTimeMillis;
|
||||
@ -17,12 +17,12 @@ public class OutgoingMediaMessage {
|
||||
private final int subscriptionId;
|
||||
private final long expiresIn;
|
||||
|
||||
public OutgoingMediaMessage(Recipients recipients, String message,
|
||||
public OutgoingMediaMessage(Recipient recipient, String message,
|
||||
List<Attachment> attachments, long sentTimeMillis,
|
||||
int subscriptionId, long expiresIn,
|
||||
int distributionType)
|
||||
{
|
||||
this.recipients = recipients;
|
||||
this.recipient = recipient;
|
||||
this.body = message;
|
||||
this.sentTimeMillis = sentTimeMillis;
|
||||
this.distributionType = distributionType;
|
||||
@ -31,9 +31,9 @@ public class OutgoingMediaMessage {
|
||||
this.expiresIn = expiresIn;
|
||||
}
|
||||
|
||||
public OutgoingMediaMessage(Recipients recipients, SlideDeck slideDeck, String message, long sentTimeMillis, int subscriptionId, long expiresIn, int distributionType)
|
||||
public OutgoingMediaMessage(Recipient recipient, SlideDeck slideDeck, String message, long sentTimeMillis, int subscriptionId, long expiresIn, int distributionType)
|
||||
{
|
||||
this(recipients,
|
||||
this(recipient,
|
||||
buildMessage(slideDeck, message),
|
||||
slideDeck.asAttachments(),
|
||||
sentTimeMillis, subscriptionId,
|
||||
@ -41,7 +41,7 @@ public class OutgoingMediaMessage {
|
||||
}
|
||||
|
||||
public OutgoingMediaMessage(OutgoingMediaMessage that) {
|
||||
this.recipients = that.getRecipients();
|
||||
this.recipient = that.getRecipient();
|
||||
this.body = that.body;
|
||||
this.distributionType = that.distributionType;
|
||||
this.attachments = that.attachments;
|
||||
@ -50,8 +50,8 @@ public class OutgoingMediaMessage {
|
||||
this.expiresIn = that.expiresIn;
|
||||
}
|
||||
|
||||
public Recipients getRecipients() {
|
||||
return recipients;
|
||||
public Recipient getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
|
@ -1,19 +1,19 @@
|
||||
package org.thoughtcrime.securesms.mms;
|
||||
|
||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class OutgoingSecureMediaMessage extends OutgoingMediaMessage {
|
||||
|
||||
public OutgoingSecureMediaMessage(Recipients recipients, String body,
|
||||
public OutgoingSecureMediaMessage(Recipient recipient, String body,
|
||||
List<Attachment> attachments,
|
||||
long sentTimeMillis,
|
||||
int distributionType,
|
||||
long expiresIn)
|
||||
{
|
||||
super(recipients, body, attachments, sentTimeMillis, -1, expiresIn, distributionType);
|
||||
super(recipient, body, attachments, sentTimeMillis, -1, expiresIn, distributionType);
|
||||
}
|
||||
|
||||
public OutgoingSecureMediaMessage(OutgoingMediaMessage base) {
|
||||
|
@ -31,8 +31,8 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||
import org.whispersystems.libsignal.logging.Log;
|
||||
@ -48,7 +48,7 @@ public class AndroidAutoReplyReceiver extends MasterSecretBroadcastReceiver {
|
||||
|
||||
public static final String TAG = AndroidAutoReplyReceiver.class.getSimpleName();
|
||||
public static final String REPLY_ACTION = "org.thoughtcrime.securesms.notifications.ANDROID_AUTO_REPLY";
|
||||
public static final String ADDRESSES_EXTRA = "car_addresses";
|
||||
public static final String ADDRESS_EXTRA = "car_address";
|
||||
public static final String VOICE_REPLY_KEY = "car_voice_reply_key";
|
||||
public static final String THREAD_ID_EXTRA = "car_reply_thread_id";
|
||||
|
||||
@ -62,10 +62,10 @@ public class AndroidAutoReplyReceiver extends MasterSecretBroadcastReceiver {
|
||||
|
||||
if (remoteInput == null) return;
|
||||
|
||||
final Address[] addresses = Address.fromParcelable(intent.getParcelableArrayExtra(ADDRESSES_EXTRA));
|
||||
final Address address = intent.getParcelableExtra(ADDRESS_EXTRA);
|
||||
final long threadId = intent.getLongExtra(THREAD_ID_EXTRA, -1);
|
||||
final CharSequence responseText = getMessageText(intent);
|
||||
final Recipients recipients = RecipientFactory.getRecipientsFor(context, addresses, false);
|
||||
final Recipient recipient = RecipientFactory.getRecipientFor(context, address, false);
|
||||
|
||||
if (responseText != null) {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@ -74,17 +74,17 @@ public class AndroidAutoReplyReceiver extends MasterSecretBroadcastReceiver {
|
||||
|
||||
long replyThreadId;
|
||||
|
||||
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(addresses);
|
||||
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(address);
|
||||
int subscriptionId = preferences.isPresent() ? preferences.get().getDefaultSubscriptionId().or(-1) : -1;
|
||||
long expiresIn = preferences.isPresent() ? preferences.get().getExpireMessages() * 1000 : 0;
|
||||
|
||||
if (recipients.isGroupRecipient()) {
|
||||
if (recipient.isGroupRecipient()) {
|
||||
Log.w("AndroidAutoReplyReceiver", "GroupRecipient, Sending media message");
|
||||
OutgoingMediaMessage reply = new OutgoingMediaMessage(recipients, responseText.toString(), new LinkedList<Attachment>(), System.currentTimeMillis(), subscriptionId, expiresIn, 0);
|
||||
OutgoingMediaMessage reply = new OutgoingMediaMessage(recipient, responseText.toString(), new LinkedList<Attachment>(), System.currentTimeMillis(), subscriptionId, expiresIn, 0);
|
||||
replyThreadId = MessageSender.send(context, masterSecret, reply, threadId, false, null);
|
||||
} else {
|
||||
Log.w("AndroidAutoReplyReceiver", "Sending regular message ");
|
||||
OutgoingTextMessage reply = new OutgoingTextMessage(recipients, responseText.toString(), expiresIn, subscriptionId);
|
||||
OutgoingTextMessage reply = new OutgoingTextMessage(recipient, responseText.toString(), expiresIn, subscriptionId);
|
||||
replyThreadId = MessageSender.send(context, masterSecret, reply, threadId, false, null);
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,6 @@ import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
import org.thoughtcrime.securesms.service.MessageRetrievalService;
|
||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||
@ -102,12 +101,12 @@ public class MessageNotifier {
|
||||
lastDesktopActivityTimestamp = timestamp;
|
||||
}
|
||||
|
||||
public static void notifyMessageDeliveryFailed(Context context, Recipients recipients, long threadId) {
|
||||
public static void notifyMessageDeliveryFailed(Context context, Recipient recipient, long threadId) {
|
||||
if (visibleThread == threadId) {
|
||||
sendInThreadNotification(context, recipients);
|
||||
sendInThreadNotification(context, recipient);
|
||||
} else {
|
||||
Intent intent = new Intent(context, ConversationActivity.class);
|
||||
intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, recipients.getAddresses());
|
||||
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.getAddress());
|
||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
|
||||
intent.setData((Uri.parse("custom://" + System.currentTimeMillis())));
|
||||
|
||||
@ -213,8 +212,8 @@ public class MessageNotifier {
|
||||
boolean isVisible = visibleThread == threadId;
|
||||
|
||||
ThreadDatabase threads = DatabaseFactory.getThreadDatabase(context);
|
||||
Recipients recipients = DatabaseFactory.getThreadDatabase(context)
|
||||
.getRecipientsForThreadId(threadId);
|
||||
Recipient recipients = DatabaseFactory.getThreadDatabase(context)
|
||||
.getRecipientForThreadId(threadId);
|
||||
|
||||
if (isVisible) {
|
||||
List<MarkedMessageInfo> messageIds = threads.setRead(threadId, false);
|
||||
@ -228,7 +227,7 @@ public class MessageNotifier {
|
||||
}
|
||||
|
||||
if (isVisible) {
|
||||
sendInThreadNotification(context, threads.getRecipientsForThreadId(threadId));
|
||||
sendInThreadNotification(context, threads.getRecipientForThreadId(threadId));
|
||||
} else {
|
||||
updateNotification(context, masterSecret, signal, 0);
|
||||
}
|
||||
@ -299,13 +298,13 @@ public class MessageNotifier {
|
||||
|
||||
SingleRecipientNotificationBuilder builder = new SingleRecipientNotificationBuilder(context, masterSecret, TextSecurePreferences.getNotificationPrivacy(context));
|
||||
List<NotificationItem> notifications = notificationState.getNotifications();
|
||||
Recipients recipients = notifications.get(0).getRecipients();
|
||||
Recipient recipient = notifications.get(0).getRecipient();
|
||||
int notificationId = (int) (SUMMARY_NOTIFICATION_ID + (bundled ? notifications.get(0).getThreadId() : 0));
|
||||
|
||||
|
||||
builder.setThread(notifications.get(0).getRecipients());
|
||||
builder.setThread(notifications.get(0).getRecipient());
|
||||
builder.setMessageCount(notificationState.getMessageCount());
|
||||
builder.setPrimaryMessageBody(recipients, notifications.get(0).getIndividualRecipient(),
|
||||
builder.setPrimaryMessageBody(recipient, notifications.get(0).getIndividualRecipient(),
|
||||
notifications.get(0).getText(), notifications.get(0).getSlideDeck());
|
||||
builder.setContentIntent(notifications.get(0).getPendingIntent(context));
|
||||
builder.setGroup(NOTIFICATION_GROUP);
|
||||
@ -316,17 +315,17 @@ public class MessageNotifier {
|
||||
|
||||
builder.addActions(masterSecret,
|
||||
notificationState.getMarkAsReadIntent(context, notificationId),
|
||||
notificationState.getQuickReplyIntent(context, notifications.get(0).getRecipients()),
|
||||
notificationState.getRemoteReplyIntent(context, notifications.get(0).getRecipients()));
|
||||
notificationState.getQuickReplyIntent(context, notifications.get(0).getRecipient()),
|
||||
notificationState.getRemoteReplyIntent(context, notifications.get(0).getRecipient()));
|
||||
|
||||
builder.addAndroidAutoAction(notificationState.getAndroidAutoReplyIntent(context, notifications.get(0).getRecipients()),
|
||||
builder.addAndroidAutoAction(notificationState.getAndroidAutoReplyIntent(context, notifications.get(0).getRecipient()),
|
||||
notificationState.getAndroidAutoHeardIntent(context, notificationId), notifications.get(0).getTimestamp());
|
||||
|
||||
ListIterator<NotificationItem> iterator = notifications.listIterator(notifications.size());
|
||||
|
||||
while(iterator.hasPrevious()) {
|
||||
NotificationItem item = iterator.previous();
|
||||
builder.addMessageBody(item.getRecipients(), item.getIndividualRecipient(), item.getText());
|
||||
builder.addMessageBody(item.getRecipient(), item.getIndividualRecipient(), item.getText());
|
||||
}
|
||||
|
||||
if (signal) {
|
||||
@ -375,14 +374,14 @@ public class MessageNotifier {
|
||||
NotificationManagerCompat.from(context).notify(SUMMARY_NOTIFICATION_ID, builder.build());
|
||||
}
|
||||
|
||||
private static void sendInThreadNotification(Context context, Recipients recipients) {
|
||||
private static void sendInThreadNotification(Context context, Recipient recipient) {
|
||||
if (!TextSecurePreferences.isInThreadNotifications(context) ||
|
||||
ServiceUtil.getAudioManager(context).getRingerMode() != AudioManager.RINGER_MODE_NORMAL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Uri uri = recipients != null ? recipients.getRingtone() : null;
|
||||
Uri uri = recipient != null ? recipient.getRingtone() : null;
|
||||
|
||||
if (uri == null) {
|
||||
String ringtone = TextSecurePreferences.getNotificationRingtone(context);
|
||||
@ -435,19 +434,19 @@ public class MessageNotifier {
|
||||
else reader = DatabaseFactory.getMmsSmsDatabase(context).readerFor(cursor, masterSecret);
|
||||
|
||||
while ((record = reader.getNext()) != null) {
|
||||
long id = record.getId();
|
||||
boolean mms = record.isMms() || record.isMmsNotification();
|
||||
Recipient recipient = record.getIndividualRecipient();
|
||||
Recipients recipients = record.getRecipients();
|
||||
long threadId = record.getThreadId();
|
||||
CharSequence body = record.getDisplayBody();
|
||||
Recipients threadRecipients = null;
|
||||
SlideDeck slideDeck = null;
|
||||
long timestamp = record.getTimestamp();
|
||||
long id = record.getId();
|
||||
boolean mms = record.isMms() || record.isMmsNotification();
|
||||
Recipient recipient = record.getIndividualRecipient();
|
||||
Recipient conversationRecipient = record.getRecipient();
|
||||
long threadId = record.getThreadId();
|
||||
CharSequence body = record.getDisplayBody();
|
||||
Recipient threadRecipients = null;
|
||||
SlideDeck slideDeck = null;
|
||||
long timestamp = record.getTimestamp();
|
||||
|
||||
|
||||
if (threadId != -1) {
|
||||
threadRecipients = DatabaseFactory.getThreadDatabase(context).getRecipientsForThreadId(threadId);
|
||||
threadRecipients = DatabaseFactory.getThreadDatabase(context).getRecipientForThreadId(threadId);
|
||||
}
|
||||
|
||||
if (SmsDatabase.Types.isDecryptInProgressType(record.getType()) || !record.getBody().isPlaintext()) {
|
||||
@ -463,7 +462,7 @@ public class MessageNotifier {
|
||||
}
|
||||
|
||||
if (threadRecipients == null || !threadRecipients.isMuted()) {
|
||||
notificationState.addNotification(new NotificationItem(id, mms, recipient, recipients, threadRecipients, threadId, body, timestamp, slideDeck));
|
||||
notificationState.addNotification(new NotificationItem(id, mms, recipient, conversationRecipient, threadRecipients, threadId, body, timestamp, slideDeck));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,15 +11,14 @@ import android.support.v4.app.TaskStackBuilder;
|
||||
import org.thoughtcrime.securesms.ConversationActivity;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
public class NotificationItem {
|
||||
|
||||
private final long id;
|
||||
private final boolean mms;
|
||||
private final @NonNull Recipients recipients;
|
||||
private final @NonNull Recipient conversationRecipient;
|
||||
private final @NonNull Recipient individualRecipient;
|
||||
private final @Nullable Recipients threadRecipients;
|
||||
private final @Nullable Recipient threadRecipient;
|
||||
private final long threadId;
|
||||
private final @Nullable CharSequence text;
|
||||
private final long timestamp;
|
||||
@ -27,24 +26,24 @@ public class NotificationItem {
|
||||
|
||||
public NotificationItem(long id, boolean mms,
|
||||
@NonNull Recipient individualRecipient,
|
||||
@NonNull Recipients recipients,
|
||||
@Nullable Recipients threadRecipients,
|
||||
@NonNull Recipient conversationRecipient,
|
||||
@Nullable Recipient threadRecipient,
|
||||
long threadId, @Nullable CharSequence text, long timestamp,
|
||||
@Nullable SlideDeck slideDeck)
|
||||
{
|
||||
this.id = id;
|
||||
this.mms = mms;
|
||||
this.individualRecipient = individualRecipient;
|
||||
this.recipients = recipients;
|
||||
this.threadRecipients = threadRecipients;
|
||||
this.text = text;
|
||||
this.threadId = threadId;
|
||||
this.timestamp = timestamp;
|
||||
this.slideDeck = slideDeck;
|
||||
this.id = id;
|
||||
this.mms = mms;
|
||||
this.individualRecipient = individualRecipient;
|
||||
this.conversationRecipient = conversationRecipient;
|
||||
this.threadRecipient = threadRecipient;
|
||||
this.text = text;
|
||||
this.threadId = threadId;
|
||||
this.timestamp = timestamp;
|
||||
this.slideDeck = slideDeck;
|
||||
}
|
||||
|
||||
public @NonNull Recipients getRecipients() {
|
||||
return threadRecipients == null ? recipients : threadRecipients;
|
||||
public @NonNull Recipient getRecipient() {
|
||||
return threadRecipient == null ? conversationRecipient : threadRecipient;
|
||||
}
|
||||
|
||||
public @NonNull Recipient getIndividualRecipient() {
|
||||
@ -69,8 +68,8 @@ public class NotificationItem {
|
||||
|
||||
public PendingIntent getPendingIntent(Context context) {
|
||||
Intent intent = new Intent(context, ConversationActivity.class);
|
||||
Recipients notifyRecipients = threadRecipients != null ? threadRecipients : recipients;
|
||||
if (notifyRecipients != null) intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, notifyRecipients.getAddresses());
|
||||
Recipient notifyRecipients = threadRecipient != null ? threadRecipient : conversationRecipient;
|
||||
if (notifyRecipients != null) intent.putExtra(ConversationActivity.ADDRESS_EXTRA, notifyRecipients.getAddress());
|
||||
|
||||
intent.putExtra("thread_id", threadId);
|
||||
intent.setData((Uri.parse("custom://"+System.currentTimeMillis())));
|
||||
|
@ -11,7 +11,7 @@ import android.util.Log;
|
||||
import org.thoughtcrime.securesms.ConversationActivity;
|
||||
import org.thoughtcrime.securesms.ConversationPopupActivity;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.VibrateState;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
@ -45,10 +45,10 @@ public class NotificationState {
|
||||
|
||||
public @Nullable Uri getRingtone() {
|
||||
if (!notifications.isEmpty()) {
|
||||
Recipients recipients = notifications.getFirst().getRecipients();
|
||||
Recipient recipient = notifications.getFirst().getRecipient();
|
||||
|
||||
if (recipients != null) {
|
||||
return recipients.getRingtone();
|
||||
if (recipient != null) {
|
||||
return recipient.getRingtone();
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,10 +57,10 @@ public class NotificationState {
|
||||
|
||||
public VibrateState getVibrate() {
|
||||
if (!notifications.isEmpty()) {
|
||||
Recipients recipients = notifications.getFirst().getRecipients();
|
||||
Recipient recipient = notifications.getFirst().getRecipient();
|
||||
|
||||
if (recipients != null) {
|
||||
return recipients.getVibrate();
|
||||
if (recipient != null) {
|
||||
return recipient.getVibrate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,26 +115,26 @@ public class NotificationState {
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
public PendingIntent getRemoteReplyIntent(Context context, Recipients recipients) {
|
||||
public PendingIntent getRemoteReplyIntent(Context context, Recipient recipient) {
|
||||
if (threads.size() != 1) throw new AssertionError("We only support replies to single thread notifications!");
|
||||
|
||||
Intent intent = new Intent(RemoteReplyReceiver.REPLY_ACTION);
|
||||
intent.setClass(context, RemoteReplyReceiver.class);
|
||||
intent.setData((Uri.parse("custom://"+System.currentTimeMillis())));
|
||||
intent.putExtra(RemoteReplyReceiver.ADDRESSES_EXTRA, recipients.getAddresses());
|
||||
intent.putExtra(RemoteReplyReceiver.ADDRESS_EXTRA, recipient.getAddress());
|
||||
intent.setPackage(context.getPackageName());
|
||||
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
public PendingIntent getAndroidAutoReplyIntent(Context context, Recipients recipients) {
|
||||
public PendingIntent getAndroidAutoReplyIntent(Context context, Recipient recipient) {
|
||||
if (threads.size() != 1) throw new AssertionError("We only support replies to single thread notifications!");
|
||||
|
||||
Intent intent = new Intent(AndroidAutoReplyReceiver.REPLY_ACTION);
|
||||
intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
|
||||
intent.setClass(context, AndroidAutoReplyReceiver.class);
|
||||
intent.setData((Uri.parse("custom://"+System.currentTimeMillis())));
|
||||
intent.putExtra(AndroidAutoReplyReceiver.ADDRESSES_EXTRA, recipients.getAddresses());
|
||||
intent.putExtra(AndroidAutoReplyReceiver.ADDRESS_EXTRA, recipient.getAddress());
|
||||
intent.putExtra(AndroidAutoReplyReceiver.THREAD_ID_EXTRA, (long)threads.toArray()[0]);
|
||||
intent.setPackage(context.getPackageName());
|
||||
|
||||
@ -160,11 +160,11 @@ public class NotificationState {
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||
}
|
||||
|
||||
public PendingIntent getQuickReplyIntent(Context context, Recipients recipients) {
|
||||
public PendingIntent getQuickReplyIntent(Context context, Recipient recipient) {
|
||||
if (threads.size() != 1) throw new AssertionError("We only support replies to single thread notifications! " + threads.size());
|
||||
|
||||
Intent intent = new Intent(context, ConversationPopupActivity.class);
|
||||
intent.putExtra(ConversationActivity.ADDRESSES_EXTRA, recipients.getAddresses());
|
||||
intent.putExtra(ConversationActivity.ADDRESS_EXTRA, recipient.getAddress());
|
||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, (long)threads.toArray()[0]);
|
||||
intent.setData((Uri.parse("custom://"+System.currentTimeMillis())));
|
||||
|
||||
|
@ -31,8 +31,8 @@ import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessagingDatabase.MarkedMessageInfo;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
@ -45,9 +45,9 @@ import java.util.List;
|
||||
*/
|
||||
public class RemoteReplyReceiver extends MasterSecretBroadcastReceiver {
|
||||
|
||||
public static final String TAG = RemoteReplyReceiver.class.getSimpleName();
|
||||
public static final String REPLY_ACTION = "org.thoughtcrime.securesms.notifications.WEAR_REPLY";
|
||||
public static final String ADDRESSES_EXTRA = "addresses";
|
||||
public static final String TAG = RemoteReplyReceiver.class.getSimpleName();
|
||||
public static final String REPLY_ACTION = "org.thoughtcrime.securesms.notifications.WEAR_REPLY";
|
||||
public static final String ADDRESS_EXTRA = "address";
|
||||
|
||||
@Override
|
||||
protected void onReceive(final Context context, Intent intent,
|
||||
@ -59,7 +59,7 @@ public class RemoteReplyReceiver extends MasterSecretBroadcastReceiver {
|
||||
|
||||
if (remoteInput == null) return;
|
||||
|
||||
final Address[] addresses = Address.fromParcelable(intent.getParcelableArrayExtra(ADDRESSES_EXTRA));
|
||||
final Address address = intent.getParcelableExtra(ADDRESS_EXTRA);
|
||||
final CharSequence responseText = remoteInput.getCharSequence(MessageNotifier.EXTRA_REMOTE_REPLY);
|
||||
|
||||
if (masterSecret != null && responseText != null) {
|
||||
@ -68,16 +68,16 @@ public class RemoteReplyReceiver extends MasterSecretBroadcastReceiver {
|
||||
protected Void doInBackground(Void... params) {
|
||||
long threadId;
|
||||
|
||||
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(addresses);
|
||||
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(address);
|
||||
int subscriptionId = preferences.isPresent() ? preferences.get().getDefaultSubscriptionId().or(-1) : -1;
|
||||
long expiresIn = preferences.isPresent() ? preferences.get().getExpireMessages() * 1000 : 0;
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(context, address, false);
|
||||
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(context, addresses, false);
|
||||
if (recipients.isGroupRecipient()) {
|
||||
OutgoingMediaMessage reply = new OutgoingMediaMessage(recipients, responseText.toString(), new LinkedList<Attachment>(), System.currentTimeMillis(), subscriptionId, expiresIn, 0);
|
||||
if (recipient.isGroupRecipient()) {
|
||||
OutgoingMediaMessage reply = new OutgoingMediaMessage(recipient, responseText.toString(), new LinkedList<Attachment>(), System.currentTimeMillis(), subscriptionId, expiresIn, 0);
|
||||
threadId = MessageSender.send(context, masterSecret, reply, -1, false, null);
|
||||
} else {
|
||||
OutgoingTextMessage reply = new OutgoingTextMessage(recipients, responseText.toString(), expiresIn, subscriptionId);
|
||||
OutgoingTextMessage reply = new OutgoingTextMessage(recipient, responseText.toString(), expiresIn, subscriptionId);
|
||||
threadId = MessageSender.send(context, masterSecret, reply, -1, false, null);
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,6 @@ import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.preferences.NotificationPrivacyPreference;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
@ -57,16 +56,16 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
||||
setCategory(NotificationCompat.CATEGORY_MESSAGE);
|
||||
}
|
||||
|
||||
public void setThread(@NonNull Recipients recipients) {
|
||||
public void setThread(@NonNull Recipient recipient) {
|
||||
if (privacy.isDisplayContact()) {
|
||||
setContentTitle(recipients.toShortString());
|
||||
setContentTitle(recipient.toShortString());
|
||||
|
||||
if (recipients.isSingleRecipient() && recipients.getPrimaryRecipient().getContactUri() != null) {
|
||||
addPerson(recipients.getPrimaryRecipient().getContactUri().toString());
|
||||
if (recipient.getContactUri() != null) {
|
||||
addPerson(recipient.getContactUri().toString());
|
||||
}
|
||||
|
||||
setLargeIcon(recipients.getContactPhoto()
|
||||
.asDrawable(context, recipients.getColor()
|
||||
setLargeIcon(recipient.getContactPhoto()
|
||||
.asDrawable(context, recipient.getColor()
|
||||
.toConversationColor(context)));
|
||||
} else {
|
||||
setContentTitle(context.getString(R.string.SingleRecipientNotificationBuilder_signal));
|
||||
@ -80,14 +79,14 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
||||
setNumber(messageCount);
|
||||
}
|
||||
|
||||
public void setPrimaryMessageBody(@NonNull Recipients threadRecipients,
|
||||
public void setPrimaryMessageBody(@NonNull Recipient threadRecipients,
|
||||
@NonNull Recipient individualRecipient,
|
||||
@NonNull CharSequence message,
|
||||
@Nullable SlideDeck slideDeck)
|
||||
{
|
||||
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
|
||||
|
||||
if (privacy.isDisplayContact() && (threadRecipients.isGroupRecipient() || !threadRecipients.isSingleRecipient())) {
|
||||
if (privacy.isDisplayContact() && threadRecipients.isGroupRecipient()) {
|
||||
stringBuilder.append(Util.getBoldedString(individualRecipient.toShortString() + ": "));
|
||||
}
|
||||
|
||||
@ -162,13 +161,13 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
|
||||
}
|
||||
}
|
||||
|
||||
public void addMessageBody(@NonNull Recipients threadRecipients,
|
||||
public void addMessageBody(@NonNull Recipient threadRecipient,
|
||||
@NonNull Recipient individualRecipient,
|
||||
@Nullable CharSequence messageBody)
|
||||
{
|
||||
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
|
||||
|
||||
if (privacy.isDisplayContact() && (threadRecipients.isGroupRecipient() || !threadRecipients.isSingleRecipient())) {
|
||||
if (privacy.isDisplayContact() && threadRecipient.isGroupRecipient()) {
|
||||
stringBuilder.append(Util.getBoldedString(individualRecipient.toShortString() + ": "));
|
||||
}
|
||||
|
||||
|
@ -7,14 +7,15 @@ import android.widget.TextView;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.components.AvatarImageView;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class BlockedContactListItem extends RelativeLayout implements Recipients.RecipientsModifiedListener {
|
||||
public class BlockedContactListItem extends RelativeLayout implements RecipientModifiedListener {
|
||||
|
||||
private AvatarImageView contactPhotoImage;
|
||||
private TextView nameView;
|
||||
private Recipients recipients;
|
||||
private Recipient recipient;
|
||||
|
||||
public BlockedContactListItem(Context context) {
|
||||
super(context);
|
||||
@ -35,15 +36,15 @@ public class BlockedContactListItem extends RelativeLayout implements Recipients
|
||||
this.nameView = (TextView) findViewById(R.id.name);
|
||||
}
|
||||
|
||||
public void set(Recipients recipients) {
|
||||
this.recipients = recipients;
|
||||
public void set(Recipient recipients) {
|
||||
this.recipient = recipients;
|
||||
|
||||
onModified(recipients);
|
||||
recipients.addListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModified(final Recipients recipients) {
|
||||
public void onModified(final Recipient recipients) {
|
||||
final AvatarImageView contactPhotoImage = this.contactPhotoImage;
|
||||
final TextView nameView = this.nameView;
|
||||
|
||||
@ -56,7 +57,7 @@ public class BlockedContactListItem extends RelativeLayout implements Recipients
|
||||
});
|
||||
}
|
||||
|
||||
public Recipients getRecipients() {
|
||||
return recipients;
|
||||
public Recipient getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +1,14 @@
|
||||
package org.thoughtcrime.securesms.providers;
|
||||
|
||||
import android.content.ContentUris;
|
||||
import android.content.Context;
|
||||
import android.content.UriMatcher;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.DecryptingPartInputStream;
|
||||
import org.thoughtcrime.securesms.crypto.EncryptingPartOutputStream;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -26,31 +26,41 @@ import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhotoFactory;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.VibrateState;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientProvider.RecipientDetails;
|
||||
import org.thoughtcrime.securesms.util.FutureTaskListener;
|
||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class Recipient {
|
||||
public class Recipient implements RecipientModifiedListener {
|
||||
|
||||
private final static String TAG = Recipient.class.getSimpleName();
|
||||
|
||||
private final Set<RecipientModifiedListener> listeners = Collections.newSetFromMap(new WeakHashMap<RecipientModifiedListener, Boolean>());
|
||||
|
||||
private final @NonNull Address address;
|
||||
private final @NonNull List<Recipient> participants = new LinkedList<>();
|
||||
|
||||
private @Nullable String name;
|
||||
private @Nullable String customLabel;
|
||||
private boolean stale;
|
||||
private boolean resolving;
|
||||
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;
|
||||
|
||||
@Nullable private MaterialColor color;
|
||||
|
||||
@ -64,11 +74,16 @@ public class Recipient {
|
||||
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.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;
|
||||
}
|
||||
|
||||
future.addListener(new FutureTaskListener<RecipientDetails>() {
|
||||
@ -76,12 +91,22 @@ public class Recipient {
|
||||
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.resolving = false;
|
||||
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.participants.addAll(result.participants);
|
||||
Recipient.this.resolving = false;
|
||||
|
||||
if (!listeners.isEmpty()) {
|
||||
for (Recipient recipient : participants) recipient.addListener(Recipient.this);
|
||||
}
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
@ -95,14 +120,20 @@ public class Recipient {
|
||||
});
|
||||
}
|
||||
|
||||
Recipient(Address address, RecipientDetails details) {
|
||||
this.address = address;
|
||||
this.contactUri = details.contactUri;
|
||||
this.name = details.name;
|
||||
this.contactPhoto = details.avatar;
|
||||
this.color = details.color;
|
||||
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.participants.addAll(details.participants);
|
||||
this.resolving = false;
|
||||
this.customLabel = details.customLabel;
|
||||
}
|
||||
|
||||
public synchronized @Nullable Uri getContactUri() {
|
||||
@ -110,13 +141,24 @@ public class Recipient {
|
||||
}
|
||||
|
||||
public synchronized @Nullable String getName() {
|
||||
if (this.name == null && isMmsGroupRecipient()) {
|
||||
List<String> names = new LinkedList<>();
|
||||
|
||||
for (Recipient recipient : participants) {
|
||||
names.add(recipient.toShortString());
|
||||
}
|
||||
|
||||
return Util.join(names, ", ");
|
||||
}
|
||||
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public synchronized @NonNull MaterialColor getColor() {
|
||||
if (color != null) return color;
|
||||
else if (name != null) return ContactColors.generateFor(name);
|
||||
else return ContactColors.UNKNOWN_COLOR;
|
||||
if (isGroupRecipient()) return MaterialColor.GROUP;
|
||||
else if (color != null) return color;
|
||||
else if (name != null) return ContactColors.generateFor(name);
|
||||
else return ContactColors.UNKNOWN_COLOR;
|
||||
}
|
||||
|
||||
public void setColor(@NonNull MaterialColor color) {
|
||||
@ -139,22 +181,101 @@ public class Recipient {
|
||||
return address.isGroup();
|
||||
}
|
||||
|
||||
public boolean isMmsGroupRecipient() {
|
||||
return address.isMmsGroup();
|
||||
}
|
||||
|
||||
public boolean isPushGroupRecipient() {
|
||||
return address.isGroup() && !address.isMmsGroup();
|
||||
}
|
||||
|
||||
public List<Recipient> getParticipants() {
|
||||
return participants;
|
||||
}
|
||||
|
||||
public synchronized void addListener(RecipientModifiedListener listener) {
|
||||
if (listeners.isEmpty()) {
|
||||
for (Recipient recipient : participants) recipient.addListener(this);
|
||||
}
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public synchronized void removeListener(RecipientModifiedListener listener) {
|
||||
listeners.remove(listener);
|
||||
|
||||
if (listeners.isEmpty()) {
|
||||
for (Recipient recipient : participants) recipient.removeListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized String toShortString() {
|
||||
return (name == null ? address.serialize() : name);
|
||||
return (getName() == null ? address.serialize() : getName());
|
||||
}
|
||||
|
||||
public synchronized @NonNull ContactPhoto getContactPhoto() {
|
||||
return contactPhoto;
|
||||
}
|
||||
|
||||
public synchronized @Nullable Uri getRingtone() {
|
||||
return ringtone;
|
||||
}
|
||||
|
||||
public void setRingtone(Uri ringtone) {
|
||||
synchronized (this) {
|
||||
this.ringtone = ringtone;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized boolean isMuted() {
|
||||
return System.currentTimeMillis() <= mutedUntil;
|
||||
}
|
||||
|
||||
public void setMuted(long mutedUntil) {
|
||||
synchronized (this) {
|
||||
this.mutedUntil = mutedUntil;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized boolean isBlocked() {
|
||||
return blocked;
|
||||
}
|
||||
|
||||
public void setBlocked(boolean blocked) {
|
||||
synchronized (this) {
|
||||
this.blocked = blocked;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized VibrateState getVibrate() {
|
||||
return vibrate;
|
||||
}
|
||||
|
||||
public void setVibrate(VibrateState vibrate) {
|
||||
synchronized (this) {
|
||||
this.vibrate = vibrate;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized int getExpireMessages() {
|
||||
return expireMessages;
|
||||
}
|
||||
|
||||
public void setExpireMessages(int expireMessages) {
|
||||
synchronized (this) {
|
||||
this.expireMessages = expireMessages;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
@ -182,8 +303,9 @@ public class Recipient {
|
||||
listener.onModified(this);
|
||||
}
|
||||
|
||||
public interface RecipientModifiedListener {
|
||||
public void onModified(Recipient recipient);
|
||||
@Override
|
||||
public void onModified(Recipient recipient) {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
boolean isStale() {
|
||||
|
@ -22,37 +22,12 @@ import android.support.annotation.NonNull;
|
||||
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class RecipientFactory {
|
||||
|
||||
public static final String RECIPIENT_CLEAR_ACTION = "org.thoughtcrime.securesms.database.RecipientFactory.CLEAR";
|
||||
|
||||
private static final RecipientProvider provider = new RecipientProvider();
|
||||
|
||||
public static @NonNull Recipients getRecipientsFor(Context context, Collection<Recipient> recipients, boolean asynchronous) {
|
||||
Address[] addresses= new Address[recipients.size()];
|
||||
int i = 0;
|
||||
|
||||
for (Recipient recipient : recipients) {
|
||||
addresses[i++] = recipient.getAddress();
|
||||
}
|
||||
|
||||
return provider.getRecipients(context, addresses, asynchronous);
|
||||
}
|
||||
|
||||
public static Recipients getRecipientsFor(Context context, Recipient recipient, boolean asynchronous) {
|
||||
Address[] addresses = new Address[1];
|
||||
addresses[0] = recipient.getAddress();
|
||||
|
||||
return provider.getRecipients(context, addresses, asynchronous);
|
||||
}
|
||||
|
||||
public static @NonNull Recipients getRecipientsFor(@NonNull Context context, @NonNull Address[] addresses, boolean asynchronous) {
|
||||
if (addresses == null || addresses.length == 0) throw new AssertionError(addresses);
|
||||
return provider.getRecipients(context, addresses, asynchronous);
|
||||
}
|
||||
|
||||
public static @NonNull Recipient getRecipientFor(@NonNull Context context, @NonNull Address address, boolean asynchronous) {
|
||||
if (address == null) throw new AssertionError(address);
|
||||
return provider.getRecipient(context, address, asynchronous);
|
||||
|
@ -0,0 +1,6 @@
|
||||
package org.thoughtcrime.securesms.recipients;
|
||||
|
||||
|
||||
public interface RecipientModifiedListener {
|
||||
public void onModified(Recipient recipient);
|
||||
}
|
@ -28,21 +28,18 @@ import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
|
||||
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;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
|
||||
import org.thoughtcrime.securesms.util.GroupUtil;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.VibrateState;
|
||||
import org.thoughtcrime.securesms.util.LRUCache;
|
||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.whispersystems.libsignal.util.guava.Optional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -55,7 +52,6 @@ class RecipientProvider {
|
||||
private static final String TAG = RecipientProvider.class.getSimpleName();
|
||||
|
||||
private static final RecipientCache recipientCache = new RecipientCache();
|
||||
private static final RecipientsCache recipientsCache = new RecipientsCache();
|
||||
private static final ExecutorService asyncRecipientResolver = Util.newSingleThreadedLifoExecutor();
|
||||
|
||||
private static final String[] CALLER_ID_PROJECTION = new String[] {
|
||||
@ -69,7 +65,7 @@ class RecipientProvider {
|
||||
private static final Map<String, RecipientDetails> STATIC_DETAILS = new HashMap<String, RecipientDetails>() {{
|
||||
put("262966", new RecipientDetails("Amazon", null, null,
|
||||
ContactPhotoFactory.getResourceContactPhoto(R.drawable.ic_amazon),
|
||||
ContactColors.UNKNOWN_COLOR));
|
||||
null, null));
|
||||
}};
|
||||
|
||||
@NonNull Recipient getRecipient(Context context, Address address, boolean asynchronous) {
|
||||
@ -81,35 +77,15 @@ class RecipientProvider {
|
||||
if (asynchronous) {
|
||||
cachedRecipient = new Recipient(address, cachedRecipient, getRecipientDetailsAsync(context, address));
|
||||
} else {
|
||||
cachedRecipient = new Recipient(address, getRecipientDetailsSync(context, address));
|
||||
cachedRecipient = new Recipient(address, getRecipientDetailsSync(context, address, false));
|
||||
}
|
||||
|
||||
recipientCache.set(address, cachedRecipient);
|
||||
return cachedRecipient;
|
||||
}
|
||||
|
||||
@NonNull Recipients getRecipients(Context context, Address[] recipientAddresses, boolean asynchronous) {
|
||||
Recipients cachedRecipients = recipientsCache.get(new RecipientAddresses(recipientAddresses));
|
||||
if (cachedRecipients != null && !cachedRecipients.isStale() && (asynchronous || !cachedRecipients.isResolving())) {
|
||||
return cachedRecipients;
|
||||
}
|
||||
|
||||
List<Recipient> recipientList = new LinkedList<>();
|
||||
|
||||
for (Address address : recipientAddresses) {
|
||||
recipientList.add(getRecipient(context, address, asynchronous));
|
||||
}
|
||||
|
||||
if (asynchronous) cachedRecipients = new Recipients(recipientList, cachedRecipients, getRecipientsPreferencesAsync(context, recipientAddresses));
|
||||
else cachedRecipients = new Recipients(recipientList, getRecipientsPreferencesSync(context, recipientAddresses));
|
||||
|
||||
recipientsCache.set(new RecipientAddresses(recipientAddresses), cachedRecipients);
|
||||
return cachedRecipients;
|
||||
}
|
||||
|
||||
void clearCache() {
|
||||
recipientCache.reset();
|
||||
recipientsCache.reset();
|
||||
}
|
||||
|
||||
private @NonNull ListenableFutureTask<RecipientDetails> getRecipientDetailsAsync(final Context context, final @NonNull Address address)
|
||||
@ -117,7 +93,7 @@ class RecipientProvider {
|
||||
Callable<RecipientDetails> task = new Callable<RecipientDetails>() {
|
||||
@Override
|
||||
public RecipientDetails call() throws Exception {
|
||||
return getRecipientDetailsSync(context, address);
|
||||
return getRecipientDetailsSync(context, address, true);
|
||||
}
|
||||
};
|
||||
|
||||
@ -126,14 +102,13 @@ class RecipientProvider {
|
||||
return future;
|
||||
}
|
||||
|
||||
private @NonNull RecipientDetails getRecipientDetailsSync(Context context, @NonNull Address address) {
|
||||
if (address.isGroup()) return getGroupRecipientDetails(context, address);
|
||||
private @NonNull RecipientDetails getRecipientDetailsSync(Context context, @NonNull Address address, boolean nestedAsynchronous) {
|
||||
if (address.isGroup()) return getGroupRecipientDetails(context, address, nestedAsynchronous);
|
||||
else return getIndividualRecipientDetails(context, address);
|
||||
}
|
||||
|
||||
private @NonNull RecipientDetails getIndividualRecipientDetails(Context context, @NonNull Address address) {
|
||||
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(new Address[]{address});
|
||||
MaterialColor color = preferences.isPresent() ? preferences.get().getColor() : null;
|
||||
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientsPreferences(address);
|
||||
|
||||
if (address.isPhone() && !TextUtils.isEmpty(address.toPhoneString())) {
|
||||
Uri uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(address.toPhoneString()));
|
||||
@ -149,7 +124,7 @@ class RecipientProvider {
|
||||
Uri.withAppendedPath(Contacts.CONTENT_URI, cursor.getLong(2) + ""),
|
||||
name);
|
||||
|
||||
return new RecipientDetails(cursor.getString(0), cursor.getString(4), contactUri, contactPhoto, color);
|
||||
return new RecipientDetails(cursor.getString(0), cursor.getString(4), contactUri, contactPhoto, preferences.orNull(), null);
|
||||
} else {
|
||||
Log.w(TAG, "resultNumber is null");
|
||||
}
|
||||
@ -161,84 +136,61 @@ class RecipientProvider {
|
||||
}
|
||||
|
||||
if (STATIC_DETAILS.containsKey(address.serialize())) return STATIC_DETAILS.get(address.serialize());
|
||||
else return new RecipientDetails(null, null, null, ContactPhotoFactory.getDefaultContactPhoto(null), color);
|
||||
else return new RecipientDetails(null, null, null, ContactPhotoFactory.getDefaultContactPhoto(null), preferences.orNull(), null);
|
||||
}
|
||||
|
||||
private @NonNull RecipientDetails getGroupRecipientDetails(Context context, Address groupId) {
|
||||
try {
|
||||
GroupDatabase.GroupRecord record = DatabaseFactory.getGroupDatabase(context)
|
||||
.getGroup(GroupUtil.getDecodedId(groupId.toGroupString()));
|
||||
private @NonNull RecipientDetails getGroupRecipientDetails(Context context, Address groupId, boolean asynchronous) {
|
||||
GroupDatabase.GroupRecord record = DatabaseFactory.getGroupDatabase(context).getGroup(groupId.toGroupString());
|
||||
|
||||
if (record != null) {
|
||||
ContactPhoto contactPhoto = ContactPhotoFactory.getGroupContactPhoto(record.getAvatar());
|
||||
String title = record.getTitle();
|
||||
if (record != null) {
|
||||
ContactPhoto contactPhoto = ContactPhotoFactory.getGroupContactPhoto(record.getAvatar());
|
||||
String title = record.getTitle();
|
||||
List<Address> memberAddresses = record.getMembers();
|
||||
List<Recipient> members = new LinkedList<>();
|
||||
|
||||
if (title == null) {
|
||||
title = context.getString(R.string.RecipientProvider_unnamed_group);;
|
||||
}
|
||||
|
||||
return new RecipientDetails(title, null, null, contactPhoto, null);
|
||||
for (Address memberAddress : memberAddresses) {
|
||||
members.add(getRecipient(context, memberAddress, asynchronous));
|
||||
}
|
||||
|
||||
return new RecipientDetails(context.getString(R.string.RecipientProvider_unnamed_group), null, null, ContactPhotoFactory.getDefaultGroupPhoto(), null);
|
||||
} catch (IOException e) {
|
||||
Log.w("RecipientProvider", e);
|
||||
return new RecipientDetails(context.getString(R.string.RecipientProvider_unnamed_group), null, null, ContactPhotoFactory.getDefaultGroupPhoto(), null);
|
||||
if (!groupId.isMmsGroup() && title == null) {
|
||||
title = context.getString(R.string.RecipientProvider_unnamed_group);;
|
||||
}
|
||||
|
||||
return new RecipientDetails(title, null, null, contactPhoto, null, members);
|
||||
}
|
||||
|
||||
return new RecipientDetails(context.getString(R.string.RecipientProvider_unnamed_group), null, null, ContactPhotoFactory.getDefaultGroupPhoto(), null, null);
|
||||
}
|
||||
|
||||
private @Nullable RecipientsPreferences getRecipientsPreferencesSync(Context context, Address[] addresses) {
|
||||
return DatabaseFactory.getRecipientPreferenceDatabase(context)
|
||||
.getRecipientsPreferences(addresses)
|
||||
.orNull();
|
||||
}
|
||||
|
||||
private ListenableFutureTask<RecipientsPreferences> getRecipientsPreferencesAsync(final Context context, final Address[] addresses) {
|
||||
ListenableFutureTask<RecipientsPreferences> task = new ListenableFutureTask<>(new Callable<RecipientsPreferences>() {
|
||||
@Override
|
||||
public RecipientsPreferences call() throws Exception {
|
||||
return getRecipientsPreferencesSync(context, addresses);
|
||||
}
|
||||
});
|
||||
|
||||
asyncRecipientResolver.execute(task);
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
public 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;
|
||||
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;
|
||||
|
||||
public RecipientDetails(@Nullable String name, @Nullable String customLabel,
|
||||
@Nullable Uri contactUri, @NonNull ContactPhoto avatar,
|
||||
@Nullable MaterialColor color)
|
||||
@Nullable RecipientsPreferences preferences,
|
||||
@Nullable List<Recipient> participants)
|
||||
{
|
||||
this.name = name;
|
||||
this.customLabel = customLabel;
|
||||
this.avatar = avatar;
|
||||
this.contactUri = contactUri;
|
||||
this.color = color;
|
||||
}
|
||||
}
|
||||
|
||||
private static class RecipientAddresses {
|
||||
private final Address[] addresses;
|
||||
|
||||
private RecipientAddresses(Address[] addresses) {
|
||||
this.addresses = addresses;
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (other == null || !(other instanceof RecipientAddresses)) return false;
|
||||
return Arrays.equals(this.addresses, ((RecipientAddresses) other).addresses);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(addresses);
|
||||
this.name = name;
|
||||
this.customLabel = customLabel;
|
||||
this.avatar = avatar;
|
||||
this.contactUri = contactUri;
|
||||
this.color = preferences != null ? preferences.getColor() : null;
|
||||
this.ringtone = preferences != null ? preferences.getRingtone() : null;
|
||||
this.mutedUntil = preferences != null ? preferences.getMuteUntil() : 0;
|
||||
this.vibrateState = preferences != null ? preferences.getVibrateState() : null;
|
||||
this.blocked = preferences != null && preferences.isBlocked();
|
||||
this.expireMessages = preferences != null ? preferences.getExpireMessages() : 0;
|
||||
this.participants = participants == null ? new LinkedList<Recipient>() : participants;
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,26 +214,4 @@ class RecipientProvider {
|
||||
|
||||
}
|
||||
|
||||
private static class RecipientsCache {
|
||||
|
||||
private final Map<RecipientAddresses,Recipients> cache = new LRUCache<>(1000);
|
||||
|
||||
public synchronized Recipients get(RecipientAddresses addresses) {
|
||||
return cache.get(addresses);
|
||||
}
|
||||
|
||||
public synchronized void set(RecipientAddresses addresses, Recipients recipients) {
|
||||
cache.put(addresses, recipients);
|
||||
}
|
||||
|
||||
public synchronized void reset() {
|
||||
for (Recipients recipients : cache.values()) {
|
||||
recipients.setStale();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -1,321 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2015 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
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package org.thoughtcrime.securesms.recipients;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.color.MaterialColor;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactColors;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
|
||||
import org.thoughtcrime.securesms.contacts.avatars.ContactPhotoFactory;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.VibrateState;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient.RecipientModifiedListener;
|
||||
import org.thoughtcrime.securesms.util.FutureTaskListener;
|
||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.WeakHashMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class Recipients implements Iterable<Recipient>, RecipientModifiedListener {
|
||||
|
||||
private static final String TAG = Recipients.class.getSimpleName();
|
||||
|
||||
private final Set<RecipientsModifiedListener> listeners = Collections.newSetFromMap(new WeakHashMap<RecipientsModifiedListener, Boolean>());
|
||||
private final List<Recipient> recipients;
|
||||
|
||||
private Uri ringtone = null;
|
||||
private long mutedUntil = 0;
|
||||
private boolean blocked = false;
|
||||
private VibrateState vibrate = VibrateState.DEFAULT;
|
||||
private int expireMessages = 0;
|
||||
private boolean stale = false;
|
||||
|
||||
Recipients() {
|
||||
this(new LinkedList<Recipient>(), null);
|
||||
}
|
||||
|
||||
Recipients(List<Recipient> recipients, @Nullable RecipientsPreferences preferences) {
|
||||
this.recipients = recipients;
|
||||
|
||||
if (preferences != null) {
|
||||
ringtone = preferences.getRingtone();
|
||||
mutedUntil = preferences.getMuteUntil();
|
||||
vibrate = preferences.getVibrateState();
|
||||
blocked = preferences.isBlocked();
|
||||
expireMessages = preferences.getExpireMessages();
|
||||
}
|
||||
}
|
||||
|
||||
Recipients(@NonNull List<Recipient> recipients,
|
||||
@Nullable Recipients stale,
|
||||
@NonNull ListenableFutureTask<RecipientsPreferences> preferences)
|
||||
{
|
||||
this.recipients = recipients;
|
||||
|
||||
if (stale != null) {
|
||||
ringtone = stale.ringtone;
|
||||
mutedUntil = stale.mutedUntil;
|
||||
vibrate = stale.vibrate;
|
||||
blocked = stale.blocked;
|
||||
expireMessages = stale.expireMessages;
|
||||
}
|
||||
|
||||
preferences.addListener(new FutureTaskListener<RecipientsPreferences>() {
|
||||
@Override
|
||||
public void onSuccess(RecipientsPreferences result) {
|
||||
if (result != null) {
|
||||
|
||||
Set<RecipientsModifiedListener> localListeners;
|
||||
|
||||
synchronized (Recipients.this) {
|
||||
ringtone = result.getRingtone();
|
||||
mutedUntil = result.getMuteUntil();
|
||||
vibrate = result.getVibrateState();
|
||||
blocked = result.isBlocked();
|
||||
expireMessages = result.getExpireMessages();
|
||||
|
||||
localListeners = new HashSet<>(listeners);
|
||||
}
|
||||
|
||||
for (RecipientsModifiedListener listener : localListeners) {
|
||||
listener.onModified(Recipients.this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(ExecutionException error) {
|
||||
Log.w(TAG, error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized @Nullable Uri getRingtone() {
|
||||
return ringtone;
|
||||
}
|
||||
|
||||
public void setRingtone(Uri ringtone) {
|
||||
synchronized (this) {
|
||||
this.ringtone = ringtone;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized boolean isMuted() {
|
||||
return System.currentTimeMillis() <= mutedUntil;
|
||||
}
|
||||
|
||||
public void setMuted(long mutedUntil) {
|
||||
synchronized (this) {
|
||||
this.mutedUntil = mutedUntil;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized boolean isBlocked() {
|
||||
return blocked;
|
||||
}
|
||||
|
||||
public void setBlocked(boolean blocked) {
|
||||
synchronized (this) {
|
||||
this.blocked = blocked;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized VibrateState getVibrate() {
|
||||
return vibrate;
|
||||
}
|
||||
|
||||
public void setVibrate(VibrateState vibrate) {
|
||||
synchronized (this) {
|
||||
this.vibrate = vibrate;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public @NonNull ContactPhoto getContactPhoto() {
|
||||
if (recipients.size() == 1) return recipients.get(0).getContactPhoto();
|
||||
else return ContactPhotoFactory.getDefaultGroupPhoto();
|
||||
}
|
||||
|
||||
public synchronized @NonNull MaterialColor getColor() {
|
||||
if (!isSingleRecipient() || isGroupRecipient()) return MaterialColor.GROUP;
|
||||
else if (isEmpty()) return ContactColors.UNKNOWN_COLOR;
|
||||
else return recipients.get(0).getColor();
|
||||
}
|
||||
|
||||
public synchronized void setColor(@NonNull MaterialColor color) {
|
||||
if (!isSingleRecipient() || isGroupRecipient()) throw new AssertionError("Groups don't have colors!");
|
||||
else if (!isEmpty()) recipients.get(0).setColor(color);
|
||||
}
|
||||
|
||||
public synchronized int getExpireMessages() {
|
||||
return expireMessages;
|
||||
}
|
||||
|
||||
public void setExpireMessages(int expireMessages) {
|
||||
synchronized (this) {
|
||||
this.expireMessages = expireMessages;
|
||||
}
|
||||
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
public synchronized void addListener(RecipientsModifiedListener listener) {
|
||||
if (listeners.isEmpty()) {
|
||||
for (Recipient recipient : recipients) {
|
||||
recipient.addListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public synchronized void removeListener(RecipientsModifiedListener listener) {
|
||||
listeners.remove(listener);
|
||||
|
||||
if (listeners.isEmpty()) {
|
||||
for (Recipient recipient : recipients) {
|
||||
recipient.removeListener(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isEmailRecipient() {
|
||||
for (Recipient recipient : recipients) {
|
||||
if (recipient.getAddress().isEmail()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isGroupRecipient() {
|
||||
return isSingleRecipient() && recipients.get(0).getAddress().isGroup();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.recipients.isEmpty();
|
||||
}
|
||||
|
||||
public boolean isSingleRecipient() {
|
||||
return this.recipients.size() == 1;
|
||||
}
|
||||
|
||||
public @Nullable Recipient getPrimaryRecipient() {
|
||||
if (!isEmpty())
|
||||
return this.recipients.get(0);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<Recipient> getRecipientsList() {
|
||||
return this.recipients;
|
||||
}
|
||||
|
||||
public Address[] getAddresses() {
|
||||
Address[] addresses = new Address[recipients.size()];
|
||||
for (int i=0;i<recipients.size();i++) {
|
||||
addresses[i] = recipients.get(i).getAddress();
|
||||
}
|
||||
|
||||
Arrays.sort(addresses);
|
||||
|
||||
return addresses;
|
||||
}
|
||||
|
||||
public List<Address> getAddressesList() {
|
||||
List<Address> results = new LinkedList<>();
|
||||
Collections.addAll(results, getAddresses());
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public String toShortString() {
|
||||
String fromString = "";
|
||||
|
||||
for (int i=0;i<recipients.size();i++) {
|
||||
fromString += recipients.get(i).toShortString();
|
||||
|
||||
if (i != recipients.size() -1 )
|
||||
fromString += ", ";
|
||||
}
|
||||
|
||||
return fromString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Recipient> iterator() {
|
||||
return recipients.iterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onModified(Recipient recipient) {
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
private void notifyListeners() {
|
||||
Set<RecipientsModifiedListener> localListeners;
|
||||
|
||||
synchronized (this) {
|
||||
localListeners = new HashSet<>(listeners);
|
||||
}
|
||||
|
||||
for (RecipientsModifiedListener listener : localListeners) {
|
||||
listener.onModified(this);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isStale() {
|
||||
return stale;
|
||||
}
|
||||
|
||||
void setStale() {
|
||||
this.stale = true;
|
||||
}
|
||||
|
||||
boolean isResolving() {
|
||||
for (Recipient recipient : recipients) {
|
||||
if (recipient.isResolving()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public interface RecipientsModifiedListener {
|
||||
public void onModified(Recipients recipient);
|
||||
}
|
||||
|
||||
}
|
@ -20,8 +20,8 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.BitmapUtil;
|
||||
|
||||
import java.util.LinkedList;
|
||||
@ -49,17 +49,17 @@ public class DirectShareService extends ChooserTargetService {
|
||||
ThreadRecord record;
|
||||
|
||||
while ((record = reader.getNext()) != null && results.size() < 10) {
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(this, record.getRecipients().getAddresses(), false);
|
||||
String name = recipients.toShortString();
|
||||
Drawable drawable = recipients.getContactPhoto().asDrawable(this, recipients.getColor().toConversationColor(this));
|
||||
Bitmap avatar = BitmapUtil.createFromDrawable(drawable, 500, 500);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(this, record.getRecipient().getAddress(), false);
|
||||
String name = recipient.toShortString();
|
||||
Drawable drawable = recipient.getContactPhoto().asDrawable(this, recipient.getColor().toConversationColor(this));
|
||||
Bitmap avatar = BitmapUtil.createFromDrawable(drawable, 500, 500);
|
||||
|
||||
Parcel parcel = Parcel.obtain();
|
||||
parcel.writeTypedArray(recipients.getAddresses(), 0);
|
||||
parcel.writeParcelable(recipient.getAddress(), 0);
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putLong(ShareActivity.EXTRA_THREAD_ID, record.getThreadId());
|
||||
bundle.putByteArray(ShareActivity.EXTRA_ADDRESSES_MARSHALLED, parcel.marshall());
|
||||
bundle.putByteArray(ShareActivity.EXTRA_ADDRESS_MARSHALLED, parcel.marshall());
|
||||
bundle.putInt(ShareActivity.EXTRA_DISTRIBUTION_TYPE, record.getDistributionType());
|
||||
bundle.setClassLoader(getClassLoader());
|
||||
|
||||
|
@ -12,11 +12,8 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.Address;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.sms.MessageSender;
|
||||
import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
|
||||
import org.thoughtcrime.securesms.util.Rfc5724Uri;
|
||||
@ -49,31 +46,20 @@ public class QuickResponseService extends MasterSecretIntentService {
|
||||
try {
|
||||
Rfc5724Uri uri = new Rfc5724Uri(intent.getDataString());
|
||||
String content = intent.getStringExtra(Intent.EXTRA_TEXT);
|
||||
String numbers = uri.getPath();
|
||||
String number = uri.getPath();
|
||||
|
||||
if (numbers.contains("%")){
|
||||
numbers = URLDecoder.decode(numbers);
|
||||
if (number.contains("%")){
|
||||
number = URLDecoder.decode(number);
|
||||
}
|
||||
|
||||
String[] numbersArray = numbers.split(",");
|
||||
Address[] addresses = new Address[numbersArray.length];
|
||||
|
||||
for (int i=0;i<numbersArray.length;i++) {
|
||||
addresses[i] = Address.fromExternal(this, numbersArray[i]);
|
||||
}
|
||||
|
||||
Recipients recipients = RecipientFactory.getRecipientsFor(this, addresses, false);
|
||||
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(this).getRecipientsPreferences(recipients.getAddresses());
|
||||
Address address = Address.fromExternal(this, number);
|
||||
Recipient recipient = RecipientFactory.getRecipientFor(this, address, false);
|
||||
Optional<RecipientsPreferences> preferences = DatabaseFactory.getRecipientPreferenceDatabase(this).getRecipientsPreferences(recipient.getAddress());
|
||||
int subscriptionId = preferences.isPresent() ? preferences.get().getDefaultSubscriptionId().or(-1) : -1;
|
||||
long expiresIn = preferences.isPresent() ? preferences.get().getExpireMessages() * 1000 : 0;
|
||||
|
||||
if (!TextUtils.isEmpty(content)) {
|
||||
if (recipients.isSingleRecipient()) {
|
||||
MessageSender.send(this, masterSecret, new OutgoingTextMessage(recipients, content, expiresIn, subscriptionId), -1, false, null);
|
||||
} else {
|
||||
MessageSender.send(this, masterSecret, new OutgoingMediaMessage(recipients, new SlideDeck(), content, System.currentTimeMillis(),
|
||||
subscriptionId, expiresIn, ThreadDatabase.DistributionTypes.DEFAULT), -1, false, null);
|
||||
}
|
||||
MessageSender.send(this, masterSecret, new OutgoingTextMessage(recipient, content, expiresIn, subscriptionId), -1, false, null);
|
||||
}
|
||||
} catch (URISyntaxException e) {
|
||||
Toast.makeText(this, R.string.QuickResponseService_problem_sending_message, Toast.LENGTH_LONG).show();
|
||||
|
@ -75,7 +75,7 @@ public class IncomingTextMessage implements Parcelable {
|
||||
this.expiresInMillis = expiresInMillis;
|
||||
|
||||
if (group.isPresent()) {
|
||||
this.groupId = Address.fromSerialized(GroupUtil.getEncodedId(group.get().getGroupId()));
|
||||
this.groupId = Address.fromSerialized(GroupUtil.getEncodedId(group.get().getGroupId(), false));
|
||||
} else {
|
||||
this.groupId = null;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ import org.thoughtcrime.securesms.jobs.SmsSendJob;
|
||||
import org.thoughtcrime.securesms.mms.MmsException;
|
||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||
import org.thoughtcrime.securesms.push.AccountManagerFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
@ -63,13 +63,13 @@ public class MessageSender {
|
||||
final SmsDatabase.InsertListener insertListener)
|
||||
{
|
||||
EncryptingSmsDatabase database = DatabaseFactory.getEncryptingSmsDatabase(context);
|
||||
Recipients recipients = message.getRecipients();
|
||||
Recipient recipient = message.getRecipient();
|
||||
boolean keyExchange = message.isKeyExchange();
|
||||
|
||||
long allocatedThreadId;
|
||||
|
||||
if (threadId == -1) {
|
||||
allocatedThreadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||
allocatedThreadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient);
|
||||
} else {
|
||||
allocatedThreadId = threadId;
|
||||
}
|
||||
@ -77,7 +77,7 @@ public class MessageSender {
|
||||
long messageId = database.insertMessageOutbox(new MasterSecretUnion(masterSecret), allocatedThreadId,
|
||||
message, forceSms, System.currentTimeMillis(), insertListener);
|
||||
|
||||
sendTextMessage(context, recipients, forceSms, keyExchange, messageId, message.getExpiresIn());
|
||||
sendTextMessage(context, recipient, forceSms, keyExchange, messageId, message.getExpiresIn());
|
||||
|
||||
return allocatedThreadId;
|
||||
}
|
||||
@ -96,15 +96,15 @@ public class MessageSender {
|
||||
long allocatedThreadId;
|
||||
|
||||
if (threadId == -1) {
|
||||
allocatedThreadId = threadDatabase.getThreadIdFor(message.getRecipients(), message.getDistributionType());
|
||||
allocatedThreadId = threadDatabase.getThreadIdFor(message.getRecipient(), message.getDistributionType());
|
||||
} else {
|
||||
allocatedThreadId = threadId;
|
||||
}
|
||||
|
||||
Recipients recipients = message.getRecipients();
|
||||
long messageId = database.insertMessageOutbox(new MasterSecretUnion(masterSecret), message, allocatedThreadId, forceSms, insertListener);
|
||||
Recipient recipient = message.getRecipient();
|
||||
long messageId = database.insertMessageOutbox(new MasterSecretUnion(masterSecret), message, allocatedThreadId, forceSms, insertListener);
|
||||
|
||||
sendMediaMessage(context, masterSecret, recipients, forceSms, messageId, message.getExpiresIn());
|
||||
sendMediaMessage(context, masterSecret, recipient, forceSms, messageId, message.getExpiresIn());
|
||||
|
||||
return allocatedThreadId;
|
||||
} catch (MmsException e) {
|
||||
@ -113,11 +113,9 @@ public class MessageSender {
|
||||
}
|
||||
}
|
||||
|
||||
public static void resendGroupMessage(Context context, MasterSecret masterSecret, MessageRecord messageRecord, Address filterAddress) {
|
||||
public static void resendGroupMessage(Context context, MessageRecord messageRecord, Address filterAddress) {
|
||||
if (!messageRecord.isMms()) throw new AssertionError("Not Group");
|
||||
|
||||
Recipients recipients = DatabaseFactory.getMmsAddressDatabase(context).getRecipientsForId(messageRecord.getId());
|
||||
sendGroupPush(context, recipients, messageRecord.getId(), filterAddress);
|
||||
sendGroupPush(context, messageRecord.getRecipient(), messageRecord.getId(), filterAddress);
|
||||
}
|
||||
|
||||
public static void resend(Context context, MasterSecret masterSecret, MessageRecord messageRecord) {
|
||||
@ -126,13 +124,12 @@ public class MessageSender {
|
||||
boolean forceSms = messageRecord.isForcedSms();
|
||||
boolean keyExchange = messageRecord.isKeyExchange();
|
||||
long expiresIn = messageRecord.getExpiresIn();
|
||||
Recipient recipient = messageRecord.getRecipient();
|
||||
|
||||
if (messageRecord.isMms()) {
|
||||
Recipients recipients = DatabaseFactory.getMmsAddressDatabase(context).getRecipientsForId(messageId);
|
||||
sendMediaMessage(context, masterSecret, recipients, forceSms, messageId, expiresIn);
|
||||
sendMediaMessage(context, masterSecret, recipient, forceSms, messageId, expiresIn);
|
||||
} else {
|
||||
Recipients recipients = messageRecord.getRecipients();
|
||||
sendTextMessage(context, recipients, forceSms, keyExchange, messageId, expiresIn);
|
||||
sendTextMessage(context, recipient, forceSms, keyExchange, messageId, expiresIn);
|
||||
}
|
||||
} catch (MmsException e) {
|
||||
Log.w(TAG, e);
|
||||
@ -140,31 +137,31 @@ public class MessageSender {
|
||||
}
|
||||
|
||||
private static void sendMediaMessage(Context context, MasterSecret masterSecret,
|
||||
Recipients recipients, boolean forceSms,
|
||||
Recipient recipient, boolean forceSms,
|
||||
long messageId, long expiresIn)
|
||||
throws MmsException
|
||||
{
|
||||
if (!forceSms && isSelfSend(context, recipients)) {
|
||||
if (!forceSms && isSelfSend(context, recipient)) {
|
||||
sendMediaSelf(context, masterSecret, messageId, expiresIn);
|
||||
} else if (isGroupPushSend(recipients)) {
|
||||
sendGroupPush(context, recipients, messageId, null);
|
||||
} else if (!forceSms && isPushMediaSend(context, recipients)) {
|
||||
sendMediaPush(context, recipients, messageId);
|
||||
} else if (isGroupPushSend(recipient)) {
|
||||
sendGroupPush(context, recipient, messageId, null);
|
||||
} else if (!forceSms && isPushMediaSend(context, recipient)) {
|
||||
sendMediaPush(context, recipient, messageId);
|
||||
} else {
|
||||
sendMms(context, messageId);
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendTextMessage(Context context, Recipients recipients,
|
||||
private static void sendTextMessage(Context context, Recipient recipient,
|
||||
boolean forceSms, boolean keyExchange,
|
||||
long messageId, long expiresIn)
|
||||
{
|
||||
if (!forceSms && isSelfSend(context, recipients)) {
|
||||
if (!forceSms && isSelfSend(context, recipient)) {
|
||||
sendTextSelf(context, messageId, expiresIn);
|
||||
} else if (!forceSms && isPushTextSend(context, recipients, keyExchange)) {
|
||||
sendTextPush(context, recipients, messageId);
|
||||
} else if (!forceSms && isPushTextSend(context, recipient, keyExchange)) {
|
||||
sendTextPush(context, recipient, messageId);
|
||||
} else {
|
||||
sendSms(context, recipients, messageId);
|
||||
sendSms(context, recipient, messageId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,24 +197,24 @@ public class MessageSender {
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendTextPush(Context context, Recipients recipients, long messageId) {
|
||||
private static void sendTextPush(Context context, Recipient recipient, long messageId) {
|
||||
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
|
||||
jobManager.add(new PushTextSendJob(context, messageId, recipients.getPrimaryRecipient().getAddress()));
|
||||
jobManager.add(new PushTextSendJob(context, messageId, recipient.getAddress()));
|
||||
}
|
||||
|
||||
private static void sendMediaPush(Context context, Recipients recipients, long messageId) {
|
||||
private static void sendMediaPush(Context context, Recipient recipient, long messageId) {
|
||||
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
|
||||
jobManager.add(new PushMediaSendJob(context, messageId, recipients.getPrimaryRecipient().getAddress()));
|
||||
jobManager.add(new PushMediaSendJob(context, messageId, recipient.getAddress()));
|
||||
}
|
||||
|
||||
private static void sendGroupPush(Context context, Recipients recipients, long messageId, Address filterAddress) {
|
||||
private static void sendGroupPush(Context context, Recipient recipient, long messageId, Address filterAddress) {
|
||||
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
|
||||
jobManager.add(new PushGroupSendJob(context, messageId, recipients.getPrimaryRecipient().getAddress(), filterAddress));
|
||||
jobManager.add(new PushGroupSendJob(context, messageId, recipient.getAddress(), filterAddress));
|
||||
}
|
||||
|
||||
private static void sendSms(Context context, Recipients recipients, long messageId) {
|
||||
private static void sendSms(Context context, Recipient recipient, long messageId) {
|
||||
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
|
||||
jobManager.add(new SmsSendJob(context, messageId, recipients.getPrimaryRecipient().getName()));
|
||||
jobManager.add(new SmsSendJob(context, messageId, recipient.getName()));
|
||||
}
|
||||
|
||||
private static void sendMms(Context context, long messageId) {
|
||||
@ -225,7 +222,7 @@ public class MessageSender {
|
||||
jobManager.add(new MmsSendJob(context, messageId));
|
||||
}
|
||||
|
||||
private static boolean isPushTextSend(Context context, Recipients recipients, boolean keyExchange) {
|
||||
private static boolean isPushTextSend(Context context, Recipient recipient, boolean keyExchange) {
|
||||
if (!TextSecurePreferences.isPushRegistered(context)) {
|
||||
return false;
|
||||
}
|
||||
@ -234,39 +231,36 @@ public class MessageSender {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isPushDestination(context, recipients.getPrimaryRecipient().getAddress());
|
||||
return isPushDestination(context, recipient.getAddress());
|
||||
}
|
||||
|
||||
private static boolean isPushMediaSend(Context context, Recipients recipients) {
|
||||
private static boolean isPushMediaSend(Context context, Recipient recipient) {
|
||||
if (!TextSecurePreferences.isPushRegistered(context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (recipients.getRecipientsList().size() > 1) {
|
||||
if (recipient.isGroupRecipient()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isPushDestination(context, recipients.getPrimaryRecipient().getAddress());
|
||||
return isPushDestination(context, recipient.getAddress());
|
||||
}
|
||||
|
||||
private static boolean isGroupPushSend(Recipients recipients) {
|
||||
return recipients.getPrimaryRecipient().getAddress().isGroup();
|
||||
private static boolean isGroupPushSend(Recipient recipient) {
|
||||
return recipient.getAddress().isGroup() &&
|
||||
!recipient.getAddress().isMmsGroup();
|
||||
}
|
||||
|
||||
private static boolean isSelfSend(Context context, Recipients recipients) {
|
||||
private static boolean isSelfSend(Context context, Recipient recipient) {
|
||||
if (!TextSecurePreferences.isPushRegistered(context)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!recipients.isSingleRecipient()) {
|
||||
if (recipient.isGroupRecipient()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (recipients.isGroupRecipient()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Util.isOwnNumber(context, recipients.getPrimaryRecipient().getAddress());
|
||||
return Util.isOwnNumber(context, recipient.getAddress());
|
||||
}
|
||||
|
||||
private static boolean isPushDestination(Context context, Address destination) {
|
||||
|
@ -1,11 +1,11 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
public class OutgoingEncryptedMessage extends OutgoingTextMessage {
|
||||
|
||||
public OutgoingEncryptedMessage(Recipients recipients, String body, long expiresIn) {
|
||||
super(recipients, body, expiresIn, -1);
|
||||
public OutgoingEncryptedMessage(Recipient recipient, String body, long expiresIn) {
|
||||
super(recipient, body, expiresIn, -1);
|
||||
}
|
||||
|
||||
private OutgoingEncryptedMessage(OutgoingEncryptedMessage base, String body) {
|
||||
|
@ -1,16 +1,16 @@
|
||||
package org.thoughtcrime.securesms.sms;
|
||||
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
public class OutgoingIdentityDefaultMessage extends OutgoingTextMessage {
|
||||
|
||||
public OutgoingIdentityDefaultMessage(Recipients recipients) {
|
||||
this(recipients, "");
|
||||
public OutgoingIdentityDefaultMessage(Recipient recipient) {
|
||||
this(recipient, "");
|
||||
}
|
||||
|
||||
private OutgoingIdentityDefaultMessage(Recipients recipients, String body) {
|
||||
super(recipients, body, -1);
|
||||
private OutgoingIdentityDefaultMessage(Recipient recipient, String body) {
|
||||
super(recipient, body, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -19,6 +19,6 @@ public class OutgoingIdentityDefaultMessage extends OutgoingTextMessage {
|
||||
}
|
||||
|
||||
public OutgoingTextMessage withBody(String body) {
|
||||
return new OutgoingIdentityDefaultMessage(getRecipients());
|
||||
return new OutgoingIdentityDefaultMessage(getRecipient());
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user