First cut at group messaging refactor.
This commit is contained in:
parent
83e260436b
commit
dd0aecc811
29 changed files with 365 additions and 262 deletions
BIN
res/drawable-hdpi/group_distribute.png
Normal file
BIN
res/drawable-hdpi/group_distribute.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 KiB |
BIN
res/drawable-mdpi/group_distribute.png
Normal file
BIN
res/drawable-mdpi/group_distribute.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.3 KiB |
BIN
res/drawable-xhdpi/group_distribute.png
Normal file
BIN
res/drawable-xhdpi/group_distribute.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
|
@ -6,4 +6,17 @@
|
|||
android:icon="@drawable/ic_groups_holo_dark"
|
||||
android:showAsAction="ifRoom" />
|
||||
|
||||
<item android:title="@string/conversation_group_options__delivery"
|
||||
android:id="@+id/menu_group_delivery"
|
||||
android:icon="@drawable/group_distribute"
|
||||
android:showAsAction="ifRoom" >
|
||||
|
||||
<menu >
|
||||
<group android:id="@+id/distribution_group"
|
||||
android:checkableBehavior="single">
|
||||
<item android:id="@+id/menu_distribution_conversation" android:title="@string/conversation_group_options__conversation" android:checked="true" />
|
||||
<item android:id="@+id/menu_distribution_broadcast" android:title="@string/conversation_group_options__broadcast" />
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
</menu>
|
||||
|
|
|
@ -505,6 +505,9 @@
|
|||
|
||||
<!-- Misc. piggybacking -->
|
||||
<string name="PlayStoreListing">TextSecure is a security enhanced text messaging application that serves as a full replacement for the default text messaging application. Messages to other TextSecure users are encrypted over the air, and all text messages are stored in an encrypted database on the device. If your phone is lost or stolen, your messages will be safe, and communication with other TextSecure users can\'t be monitored over the air.</string>
|
||||
<string name="conversation_group_options__delivery">Delivery</string>
|
||||
<string name="conversation_group_options__conversation">Conversation</string>
|
||||
<string name="conversation_group_options__broadcast">Broadcast</string>
|
||||
|
||||
<!-- EOF -->
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
|||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.DraftDatabase;
|
||||
import org.thoughtcrime.securesms.database.DraftDatabase.Draft;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.mms.AttachmentManager;
|
||||
import org.thoughtcrime.securesms.mms.AttachmentTypeSelectorAdapter;
|
||||
import org.thoughtcrime.securesms.mms.MediaTooLargeException;
|
||||
|
@ -93,14 +94,15 @@ import ws.com.google.android.mms.MmsException;
|
|||
*/
|
||||
public class ConversationActivity extends PassphraseRequiredSherlockFragmentActivity
|
||||
implements ConversationFragment.ConversationFragmentListener
|
||||
{
|
||||
{
|
||||
|
||||
public static final String RECIPIENTS_EXTRA = "recipients";
|
||||
public static final String THREAD_ID_EXTRA = "thread_id";
|
||||
public static final String MASTER_SECRET_EXTRA = "master_secret";
|
||||
public static final String DRAFT_TEXT_EXTRA = "draft_text";
|
||||
public static final String DRAFT_IMAGE_EXTRA = "draft_image";
|
||||
public static final String DRAFT_AUDIO_EXTRA = "draft_audio";
|
||||
public static final String RECIPIENTS_EXTRA = "recipients";
|
||||
public static final String THREAD_ID_EXTRA = "thread_id";
|
||||
public static final String MASTER_SECRET_EXTRA = "master_secret";
|
||||
public static final String DRAFT_TEXT_EXTRA = "draft_text";
|
||||
public static final String DRAFT_IMAGE_EXTRA = "draft_image";
|
||||
public static final String DRAFT_AUDIO_EXTRA = "draft_audio";
|
||||
public static final String DISTRIBUTION_TYPE_EXTRA = "distribution_type";
|
||||
|
||||
private static final int PICK_CONTACT = 1;
|
||||
private static final int PICK_IMAGE = 2;
|
||||
|
@ -120,6 +122,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
|||
|
||||
private Recipients recipients;
|
||||
private long threadId;
|
||||
private int distributionType;
|
||||
private boolean isEncryptedConversation;
|
||||
private boolean isMmsEnabled = true;
|
||||
|
||||
|
@ -182,7 +185,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
|||
|
||||
switch (reqCode) {
|
||||
case PICK_CONTACT:
|
||||
Recipients recipients = (Recipients)data.getParcelableExtra("recipients");
|
||||
Recipients recipients = data.getParcelableExtra("recipients");
|
||||
|
||||
if (recipients != null)
|
||||
recipientsPanel.addRecipients(recipients);
|
||||
|
@ -220,6 +223,13 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
|||
inflater.inflate(R.menu.conversation_callable, menu);
|
||||
} else if (isGroupConversation()) {
|
||||
inflater.inflate(R.menu.conversation_group_options, menu);
|
||||
|
||||
if (distributionType == ThreadDatabase.DistributionTypes.BROADCAST)
|
||||
{
|
||||
menu.findItem(R.id.menu_distribution_broadcast).setChecked(true);
|
||||
} else {
|
||||
menu.findItem(R.id.menu_distribution_conversation).setChecked(true);
|
||||
}
|
||||
}
|
||||
|
||||
inflater.inflate(R.menu.conversation, menu);
|
||||
|
@ -231,15 +241,17 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
|||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
super.onOptionsItemSelected(item);
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_call: handleDial(getRecipients().getPrimaryRecipient()); return true;
|
||||
case R.id.menu_delete_thread: handleDeleteThread(); return true;
|
||||
case R.id.menu_add_attachment: handleAddAttachment(); return true;
|
||||
case R.id.menu_start_secure_session: handleStartSecureSession(); return true;
|
||||
case R.id.menu_abort_session: handleAbortSecureSession(); return true;
|
||||
case R.id.menu_verify_recipient: handleVerifyRecipient(); return true;
|
||||
case R.id.menu_verify_session: handleVerifySession(); return true;
|
||||
case R.id.menu_group_recipients: handleDisplayGroupRecipients(); return true;
|
||||
case android.R.id.home: handleReturnToConversationList(); return true;
|
||||
case R.id.menu_call: handleDial(getRecipients().getPrimaryRecipient()); return true;
|
||||
case R.id.menu_delete_thread: handleDeleteThread(); return true;
|
||||
case R.id.menu_add_attachment: handleAddAttachment(); return true;
|
||||
case R.id.menu_start_secure_session: handleStartSecureSession(); return true;
|
||||
case R.id.menu_abort_session: handleAbortSecureSession(); return true;
|
||||
case R.id.menu_verify_recipient: handleVerifyRecipient(); return true;
|
||||
case R.id.menu_verify_session: handleVerifySession(); return true;
|
||||
case R.id.menu_group_recipients: handleDisplayGroupRecipients(); return true;
|
||||
case R.id.menu_distribution_broadcast: handleDistributionBroadcastEnabled(item); return true;
|
||||
case R.id.menu_distribution_conversation: handleDistributionConversationEnabled(item); return true;
|
||||
case android.R.id.home: handleReturnToConversationList(); return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -327,6 +339,38 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
|||
builder.show();
|
||||
}
|
||||
|
||||
private void handleDistributionBroadcastEnabled(MenuItem item) {
|
||||
distributionType = ThreadDatabase.DistributionTypes.BROADCAST;
|
||||
item.setChecked(true);
|
||||
|
||||
if (threadId != -1) {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
|
||||
.setDistributionType(threadId, ThreadDatabase.DistributionTypes.BROADCAST);
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDistributionConversationEnabled(MenuItem item) {
|
||||
distributionType = ThreadDatabase.DistributionTypes.CONVERSATION;
|
||||
item.setChecked(true);
|
||||
|
||||
if (threadId != -1) {
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
@Override
|
||||
protected Void doInBackground(Void... params) {
|
||||
DatabaseFactory.getThreadDatabase(ConversationActivity.this)
|
||||
.setDistributionType(threadId, ThreadDatabase.DistributionTypes.CONVERSATION);
|
||||
return null;
|
||||
}
|
||||
}.execute();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDial(Recipient recipient) {
|
||||
if (recipient == null) return;
|
||||
|
||||
|
@ -494,12 +538,14 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
|||
|
||||
private void initializeResources() {
|
||||
recipientsPanel = (RecipientsPanel)findViewById(R.id.recipients);
|
||||
recipients = getIntent().getParcelableExtra("recipients");
|
||||
threadId = getIntent().getLongExtra("thread_id", -1);
|
||||
recipients = getIntent().getParcelableExtra(RECIPIENTS_EXTRA);
|
||||
threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
|
||||
distributionType = getIntent().getIntExtra(DISTRIBUTION_TYPE_EXTRA,
|
||||
ThreadDatabase.DistributionTypes.DEFAULT);
|
||||
addContactButton = (ImageButton)findViewById(R.id.contacts_button);
|
||||
sendButton = (ImageButton)findViewById(R.id.send_button);
|
||||
composeText = (EditText)findViewById(R.id.embedded_text_editor);
|
||||
masterSecret = (MasterSecret)getIntent().getParcelableExtra("master_secret");
|
||||
masterSecret = getIntent().getParcelableExtra(MASTER_SECRET_EXTRA);
|
||||
charactersLeft = (TextView)findViewById(R.id.space_left);
|
||||
|
||||
attachmentAdapter = new AttachmentTypeSelectorAdapter(this);
|
||||
|
@ -749,10 +795,11 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
|||
if (attachmentManager.isAttachmentPresent()) {
|
||||
allocatedThreadId = MessageSender.sendMms(ConversationActivity.this, masterSecret, recipients,
|
||||
threadId, attachmentManager.getSlideDeck(), body,
|
||||
forcePlaintext);
|
||||
} else if (recipients.isEmailRecipient()) {
|
||||
distributionType, forcePlaintext);
|
||||
} else if (recipients.isEmailRecipient() || !recipients.isSingleRecipient()) {
|
||||
allocatedThreadId = MessageSender.sendMms(ConversationActivity.this, masterSecret, recipients,
|
||||
threadId, new SlideDeck(), body, forcePlaintext);
|
||||
threadId, new SlideDeck(), body, distributionType,
|
||||
forcePlaintext);
|
||||
} else {
|
||||
OutgoingTextMessage message;
|
||||
|
||||
|
@ -790,7 +837,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
|||
Intent intent = new Intent(ConversationActivity.this, ContactSelectionActivity.class);
|
||||
startActivityForResult(intent, PICK_CONTACT);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class AttachmentTypeListener implements DialogInterface.OnClickListener {
|
||||
@Override
|
||||
|
@ -823,7 +870,7 @@ public class ConversationActivity extends PassphraseRequiredSherlockFragmentActi
|
|||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private class OnTextChangedListener implements TextWatcher {
|
||||
@Override
|
||||
|
|
|
@ -123,7 +123,7 @@ public class ConversationFragment extends SherlockListFragment
|
|||
}
|
||||
|
||||
private void handleDisplayDetails(MessageRecord message) {
|
||||
String sender = message.getRecipients().getPrimaryRecipient().getNumber();
|
||||
String sender = message.getIndividualRecipient().getNumber();
|
||||
String transport = message.isMms() ? "mms" : "sms";
|
||||
long dateReceived = message.getDateReceived();
|
||||
long dateSent = message.getDateSent();
|
||||
|
@ -175,8 +175,7 @@ public class ConversationFragment extends SherlockListFragment
|
|||
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
|
||||
return new ConversationLoader(getActivity(), threadId,
|
||||
(recipients != null && !recipients.isSingleRecipient()));
|
||||
return new ConversationLoader(getActivity(), threadId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -193,19 +193,19 @@ public class ConversationItem extends LinearLayout {
|
|||
}
|
||||
|
||||
private void setGroupMessageStatus(MessageRecord messageRecord) {
|
||||
GroupData groupData = messageRecord.getGroupData();
|
||||
|
||||
if (groupData != null) {
|
||||
String status = String.format("Sent (%d/%d)", groupData.groupSentCount, groupData.groupSize);
|
||||
|
||||
if (groupData.groupSendFailedCount != 0)
|
||||
status = status + String.format(", Failed (%d/%d)", groupData.groupSendFailedCount, groupData.groupSize);
|
||||
|
||||
this.groupStatusText.setText(status);
|
||||
this.groupStatusText.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
// GroupData groupData = messageRecord.getGroupData();
|
||||
//
|
||||
// if (groupData != null) {
|
||||
// String status = String.format("Sent (%d/%d)", groupData.groupSentCount, groupData.groupSize);
|
||||
//
|
||||
// if (groupData.groupSendFailedCount != 0)
|
||||
// status = status + String.format(", Failed (%d/%d)", groupData.groupSendFailedCount, groupData.groupSize);
|
||||
//
|
||||
// this.groupStatusText.setText(status);
|
||||
// this.groupStatusText.setVisibility(View.VISIBLE);
|
||||
// } else {
|
||||
this.groupStatusText.setVisibility(View.GONE);
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
private void setNotificationMmsAttributes(NotificationMmsMessageRecord messageRecord) {
|
||||
|
@ -298,7 +298,7 @@ public class ConversationItem extends LinearLayout {
|
|||
|
||||
private void handleKeyExchangeClicked() {
|
||||
Intent intent = new Intent(context, ReceiveKeyActivity.class);
|
||||
intent.putExtra("recipient", messageRecord.getRecipients().getPrimaryRecipient());
|
||||
intent.putExtra("recipient", messageRecord.getIndividualRecipient());
|
||||
intent.putExtra("body", messageRecord.getBody());
|
||||
intent.putExtra("thread_id", messageRecord.getThreadId());
|
||||
intent.putExtra("master_secret", masterSecret);
|
||||
|
|
|
@ -10,6 +10,7 @@ import android.view.WindowManager;
|
|||
|
||||
import org.thoughtcrime.securesms.ApplicationExportManager.ApplicationExportListener;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||
|
@ -67,27 +68,30 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment
|
|||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
super.onOptionsItemSelected(item);
|
||||
|
||||
int defaultType = ThreadDatabase.DistributionTypes.DEFAULT;
|
||||
|
||||
switch (item.getItemId()) {
|
||||
case R.id.menu_new_message: createConversation(-1, null); return true;
|
||||
case R.id.menu_settings: handleDisplaySettings(); return true;
|
||||
case R.id.menu_export: handleExportDatabase(); return true;
|
||||
case R.id.menu_import: handleImportDatabase(); return true;
|
||||
case R.id.menu_clear_passphrase: handleClearPassphrase(); return true;
|
||||
case R.id.menu_new_message: createConversation(-1, null, defaultType); return true;
|
||||
case R.id.menu_settings: handleDisplaySettings(); return true;
|
||||
case R.id.menu_export: handleExportDatabase(); return true;
|
||||
case R.id.menu_import: handleImportDatabase(); return true;
|
||||
case R.id.menu_clear_passphrase: handleClearPassphrase(); return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateConversation(long threadId, Recipients recipients) {
|
||||
createConversation(threadId, recipients);
|
||||
public void onCreateConversation(long threadId, Recipients recipients, int distributionType) {
|
||||
createConversation(threadId, recipients, distributionType);
|
||||
}
|
||||
|
||||
private void createConversation(long threadId, Recipients recipients) {
|
||||
private void createConversation(long threadId, Recipients recipients, int distributionType) {
|
||||
Intent intent = new Intent(this, ConversationActivity.class);
|
||||
intent.putExtra(ConversationActivity.RECIPIENTS_EXTRA, recipients);
|
||||
intent.putExtra(ConversationActivity.THREAD_ID_EXTRA, threadId);
|
||||
intent.putExtra(ConversationActivity.MASTER_SECRET_EXTRA, masterSecret);
|
||||
intent.putExtra(ConversationActivity.DISTRIBUTION_TYPE_EXTRA, distributionType);
|
||||
|
||||
startActivity(intent);
|
||||
}
|
||||
|
|
|
@ -96,7 +96,8 @@ public class ConversationListFragment extends SherlockListFragment
|
|||
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
if (v instanceof ConversationListItem) {
|
||||
ConversationListItem headerView = (ConversationListItem) v;
|
||||
handleCreateConversation(headerView.getThreadId(), headerView.getRecipients());
|
||||
handleCreateConversation(headerView.getThreadId(), headerView.getRecipients(),
|
||||
headerView.getDistributionType());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -197,8 +198,8 @@ public class ConversationListFragment extends SherlockListFragment
|
|||
((ConversationListAdapter)this.getListAdapter()).selectAllThreads();
|
||||
}
|
||||
|
||||
private void handleCreateConversation(long threadId, Recipients recipients) {
|
||||
listener.onCreateConversation(threadId, recipients);
|
||||
private void handleCreateConversation(long threadId, Recipients recipients, int distributionType) {
|
||||
listener.onCreateConversation(threadId, recipients, distributionType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -217,7 +218,7 @@ public class ConversationListFragment extends SherlockListFragment
|
|||
}
|
||||
|
||||
public interface ConversationSelectedListener {
|
||||
public void onCreateConversation(long threadId, Recipients recipients);
|
||||
public void onCreateConversation(long threadId, Recipients recipients, int distributionType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -71,6 +71,7 @@ public class ConversationListItem extends RelativeLayout
|
|||
private QuickContactBadge contactPhotoBadge;
|
||||
|
||||
private final Handler handler = new Handler();
|
||||
private int distributionType;
|
||||
|
||||
public ConversationListItem(Context context) {
|
||||
super(context);
|
||||
|
@ -97,11 +98,12 @@ public class ConversationListItem extends RelativeLayout
|
|||
}
|
||||
|
||||
public void set(ThreadRecord thread, Set<Long> selectedThreads, boolean batchMode) {
|
||||
this.selectedThreads = selectedThreads;
|
||||
this.recipients = thread.getRecipients();
|
||||
this.threadId = thread.getThreadId();
|
||||
this.count = thread.getCount();
|
||||
this.read = thread.isRead();
|
||||
this.selectedThreads = selectedThreads;
|
||||
this.recipients = thread.getRecipients();
|
||||
this.threadId = thread.getThreadId();
|
||||
this.count = thread.getCount();
|
||||
this.read = thread.isRead();
|
||||
this.distributionType = thread.getDistributionType();
|
||||
|
||||
this.recipients.addListener(this);
|
||||
this.fromView.setText(formatFrom(recipients, count, read));
|
||||
|
@ -201,6 +203,10 @@ public class ConversationListItem extends RelativeLayout
|
|||
return threadId;
|
||||
}
|
||||
|
||||
public int getDistributionType() {
|
||||
return distributionType;
|
||||
}
|
||||
|
||||
private class CheckedChangedListener implements CompoundButton.OnCheckedChangeListener {
|
||||
@Override
|
||||
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
|
||||
|
|
|
@ -43,6 +43,7 @@ import ws.com.google.android.mms.ContentType;
|
|||
import ws.com.google.android.mms.MmsException;
|
||||
import ws.com.google.android.mms.pdu.MultimediaMessagePdu;
|
||||
import ws.com.google.android.mms.pdu.PduParser;
|
||||
import ws.com.google.android.mms.pdu.RetrieveConf;
|
||||
|
||||
/**
|
||||
* A work queue for processing a number of encryption operations.
|
||||
|
@ -186,7 +187,7 @@ public class DecryptingQueue {
|
|||
plaintextPduBytes = cipher.decryptMessage(ciphertextPduBytes);
|
||||
}
|
||||
|
||||
MultimediaMessagePdu plaintextPdu = (MultimediaMessagePdu)new PduParser(plaintextPduBytes).parse();
|
||||
RetrieveConf plaintextPdu = (RetrieveConf)new PduParser(plaintextPduBytes).parse();
|
||||
Log.w("DecryptingQueue", "Successfully decrypted MMS!");
|
||||
database.insertSecureDecryptedMessageInbox(masterSecret, plaintextPdu, threadId);
|
||||
database.delete(messageId);
|
||||
|
|
|
@ -158,9 +158,36 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
|
|||
}
|
||||
}
|
||||
|
||||
private long getThreadIdForHeaders(PduHeaders headers) throws RecipientFormattingException {
|
||||
private long getThreadIdFor(RetrieveConf retrieved) throws RecipientFormattingException {
|
||||
try {
|
||||
EncodedStringValue encodedString = headers.getEncodedStringValue(PduHeaders.FROM);
|
||||
Set<String> group = new HashSet<String>();
|
||||
|
||||
EncodedStringValue encodedFrom = retrieved.getFrom();
|
||||
group.add(new String(encodedFrom.getTextString(), CharacterSets.MIMENAME_ISO_8859_1));
|
||||
|
||||
EncodedStringValue[] encodedCcList = retrieved.getCc();
|
||||
if (encodedCcList != null) {
|
||||
for (EncodedStringValue encodedCc : encodedCcList) {
|
||||
group.add(new String(encodedCc.getTextString(), CharacterSets.MIMENAME_ISO_8859_1));
|
||||
}
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String recipient : group) {
|
||||
sb.append(recipient);
|
||||
sb.append(",");
|
||||
}
|
||||
|
||||
Recipients recipients = RecipientFactory.getRecipientsFromString(context, sb.toString(), false);
|
||||
return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new AssertionError(e);
|
||||
}
|
||||
}
|
||||
|
||||
private long getThreadIdFor(NotificationInd notification) throws RecipientFormattingException {
|
||||
try {
|
||||
EncodedStringValue encodedString = notification.getFrom();
|
||||
String fromString = new String(encodedString.getTextString(), CharacterSets.MIMENAME_ISO_8859_1);
|
||||
Recipients recipients = RecipientFactory.getRecipientsFromString(context, fromString, false);
|
||||
return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||
|
@ -313,13 +340,21 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
|
|||
}
|
||||
}
|
||||
|
||||
private long insertMessageInbox(MasterSecret masterSecret, MultimediaMessagePdu retrieved,
|
||||
String contentLocation, long threadId, long mailbox)
|
||||
private long insertMessageInbox(MasterSecret masterSecret, RetrieveConf retrieved,
|
||||
String contentLocation, long threadId, long mailbox)
|
||||
throws MmsException
|
||||
{
|
||||
PduHeaders headers = retrieved.getPduHeaders();
|
||||
ContentValues contentValues = getContentValuesFromHeader(headers);
|
||||
|
||||
if (!Util.isEmpty(retrieved.getCc())) {
|
||||
try {
|
||||
threadId = getThreadIdFor(retrieved);
|
||||
} catch (RecipientFormattingException e) {
|
||||
Log.w("MmsDatabase", e);
|
||||
}
|
||||
}
|
||||
|
||||
contentValues.put(MESSAGE_BOX, mailbox);
|
||||
contentValues.put(THREAD_ID, threadId);
|
||||
contentValues.put(CONTENT_LOCATION, contentLocation);
|
||||
|
@ -348,7 +383,8 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
|
|||
Types.BASE_INBOX_TYPE | Types.SECURE_MESSAGE_BIT | Types.ENCRYPTION_REMOTE_BIT);
|
||||
}
|
||||
|
||||
public long insertSecureDecryptedMessageInbox(MasterSecret masterSecret, MultimediaMessagePdu retrieved, long threadId)
|
||||
public long insertSecureDecryptedMessageInbox(MasterSecret masterSecret, RetrieveConf retrieved,
|
||||
long threadId)
|
||||
throws MmsException
|
||||
{
|
||||
return insertMessageInbox(masterSecret, retrieved, "", threadId,
|
||||
|
@ -360,7 +396,7 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
|
|||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
PduHeaders headers = notification.getPduHeaders();
|
||||
ContentValues contentValues = getContentValuesFromHeader(headers);
|
||||
long threadId = getThreadIdForHeaders(headers);
|
||||
long threadId = getThreadIdFor(notification);
|
||||
MmsAddressDatabase addressDatabase = DatabaseFactory.getMmsAddressDatabase(context);
|
||||
|
||||
Log.w("MmsDatabse", "Message received type: " + headers.getOctet(PduHeaders.MESSAGE_TYPE));
|
||||
|
@ -688,29 +724,12 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
|
|||
long box = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX));
|
||||
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.THREAD_ID));
|
||||
Recipient recipient = getMessageRecipient(id);
|
||||
MessageRecord.GroupData groupData = null;
|
||||
|
||||
SlideDeck slideDeck;
|
||||
|
||||
try {
|
||||
MultimediaMessagePdu pdu = getMediaMessage(id);
|
||||
slideDeck = getSlideDeck(masterSecret, pdu);
|
||||
|
||||
if (cursor.getColumnIndex(MmsSmsDatabase.GROUP_SIZE) != -1) {
|
||||
int groupSize = pdu.getTo().length;
|
||||
int groupSent = MmsDatabase.Types.isFailedMessageType(box) ? 0 : groupSize;
|
||||
int groupSendFailed = groupSize - groupSent;
|
||||
|
||||
if (groupSize <= 1) {
|
||||
groupSize = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsDatabase.GROUP_SIZE));
|
||||
groupSent = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsDatabase.MMS_GROUP_SENT_COUNT));
|
||||
groupSendFailed = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsDatabase.MMS_GROUP_SEND_FAILED_COUNT));
|
||||
}
|
||||
|
||||
Log.w("ConversationAdapter", "MMS GroupSize: " + groupSize + " , GroupSent: " + groupSent + " , GroupSendFailed: " + groupSendFailed);
|
||||
|
||||
groupData = new MessageRecord.GroupData(groupSize, groupSent, groupSendFailed);
|
||||
}
|
||||
} catch (MmsException me) {
|
||||
Log.w("ConversationAdapter", me);
|
||||
slideDeck = null;
|
||||
|
@ -718,7 +737,7 @@ public class MmsDatabase extends Database implements MmsSmsColumns {
|
|||
|
||||
return new MediaMmsMessageRecord(context, id, new Recipients(recipient), recipient,
|
||||
dateSent, dateReceived, threadId,
|
||||
slideDeck, box, groupData);
|
||||
slideDeck, box);
|
||||
}
|
||||
|
||||
protected SlideDeck getSlideDeck(MasterSecret masterSecret, MultimediaMessagePdu pdu) {
|
||||
|
|
|
@ -31,13 +31,7 @@ import java.util.Set;
|
|||
|
||||
public class MmsSmsDatabase extends Database {
|
||||
|
||||
public static final String TRANSPORT = "transport_type";
|
||||
public static final String GROUP_SIZE = "group_size";
|
||||
public static final String SMS_GROUP_SENT_COUNT = "sms_group_sent_count";
|
||||
public static final String SMS_GROUP_SEND_FAILED_COUNT = "sms_group_sent_failed_count";
|
||||
public static final String MMS_GROUP_SENT_COUNT = "mms_group_sent_count";
|
||||
public static final String MMS_GROUP_SEND_FAILED_COUNT = "mms_group_sent_failed_count";
|
||||
|
||||
public static final String TRANSPORT = "transport_type";
|
||||
public static final String MMS_TRANSPORT = "mms";
|
||||
public static final String SMS_TRANSPORT = "sms";
|
||||
|
||||
|
@ -45,53 +39,53 @@ public class MmsSmsDatabase extends Database {
|
|||
super(context, databaseHelper);
|
||||
}
|
||||
|
||||
public Cursor getCollatedGroupConversation(long threadId) {
|
||||
String smsCaseSecurity = "CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " " +
|
||||
"WHEN " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " THEN 1 " +
|
||||
"ELSE 0 END";
|
||||
|
||||
String mmsCaseSecurity = "CASE " + MmsDatabase.MESSAGE_BOX + " & " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " " +
|
||||
"WHEN " + MmsDatabase.Types.SECURE_MESSAGE_BIT + " THEN 'secure' " +
|
||||
"ELSE 'insecure' END";
|
||||
|
||||
String mmsGroupSentCount = "SUM(CASE " + MmsDatabase.MESSAGE_BOX + " & " + MmsDatabase.Types.BASE_TYPE_MASK + " " +
|
||||
"WHEN " + MmsDatabase.Types.BASE_SENT_TYPE + " THEN 1 " +
|
||||
"ELSE 0 END)";
|
||||
|
||||
|
||||
String smsGroupSentCount = "SUM(CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.BASE_TYPE_MASK + " " +
|
||||
"WHEN " + SmsDatabase.Types.BASE_SENT_TYPE + " THEN 1 " +
|
||||
"ELSE 0 END)";
|
||||
|
||||
String mmsGroupSentFailedCount = "SUM(CASE " + MmsDatabase.MESSAGE_BOX + " & " + MmsDatabase.Types.BASE_TYPE_MASK + " " +
|
||||
"WHEN " + MmsDatabase.Types.BASE_SENT_FAILED_TYPE + " THEN 1 " +
|
||||
"ELSE 0 END)";
|
||||
|
||||
String smsGroupSentFailedCount = "SUM(CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.BASE_TYPE_MASK + " " +
|
||||
"WHEN " + SmsDatabase.Types.BASE_SENT_FAILED_TYPE + " THEN 1 " +
|
||||
"ELSE 0 END)";
|
||||
|
||||
String[] projection = {MmsSmsColumns.ID, SmsDatabase.BODY, SmsDatabase.TYPE,
|
||||
MmsSmsColumns.THREAD_ID,
|
||||
SmsDatabase.ADDRESS, SmsDatabase.SUBJECT, SmsDatabase.STATUS,
|
||||
MmsSmsColumns.NORMALIZED_DATE_SENT, MmsSmsColumns.NORMALIZED_DATE_RECEIVED,
|
||||
MmsDatabase.MESSAGE_TYPE, MmsDatabase.MESSAGE_BOX, TRANSPORT,
|
||||
"COUNT(" + MmsSmsColumns.ID + ") AS " + GROUP_SIZE,
|
||||
mmsGroupSentCount + " AS " + MMS_GROUP_SENT_COUNT,
|
||||
mmsGroupSentFailedCount + " AS " + MMS_GROUP_SEND_FAILED_COUNT,
|
||||
smsGroupSentCount + " AS " + SMS_GROUP_SENT_COUNT,
|
||||
smsGroupSentFailedCount + " AS " + SMS_GROUP_SEND_FAILED_COUNT,
|
||||
smsCaseSecurity + " AS sms_collate", mmsCaseSecurity + " AS mms_collate"};
|
||||
|
||||
String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " ASC";
|
||||
String selection = MmsSmsColumns.THREAD_ID + " = " + threadId;
|
||||
String groupBy = MmsSmsColumns.NORMALIZED_DATE_SENT + " / 1000, sms_collate, mms_collate";
|
||||
|
||||
Cursor cursor = queryTables(projection, selection, order, groupBy, null);
|
||||
setNotifyConverationListeners(cursor, threadId);
|
||||
|
||||
return cursor;
|
||||
}
|
||||
// public Cursor getCollatedGroupConversation(long threadId) {
|
||||
// String smsCaseSecurity = "CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " " +
|
||||
// "WHEN " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " THEN 1 " +
|
||||
// "ELSE 0 END";
|
||||
//
|
||||
// String mmsCaseSecurity = "CASE " + MmsDatabase.MESSAGE_BOX + " & " + SmsDatabase.Types.SECURE_MESSAGE_BIT + " " +
|
||||
// "WHEN " + MmsDatabase.Types.SECURE_MESSAGE_BIT + " THEN 'secure' " +
|
||||
// "ELSE 'insecure' END";
|
||||
//
|
||||
// String mmsGroupSentCount = "SUM(CASE " + MmsDatabase.MESSAGE_BOX + " & " + MmsDatabase.Types.BASE_TYPE_MASK + " " +
|
||||
// "WHEN " + MmsDatabase.Types.BASE_SENT_TYPE + " THEN 1 " +
|
||||
// "ELSE 0 END)";
|
||||
//
|
||||
//
|
||||
// String smsGroupSentCount = "SUM(CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.BASE_TYPE_MASK + " " +
|
||||
// "WHEN " + SmsDatabase.Types.BASE_SENT_TYPE + " THEN 1 " +
|
||||
// "ELSE 0 END)";
|
||||
//
|
||||
// String mmsGroupSentFailedCount = "SUM(CASE " + MmsDatabase.MESSAGE_BOX + " & " + MmsDatabase.Types.BASE_TYPE_MASK + " " +
|
||||
// "WHEN " + MmsDatabase.Types.BASE_SENT_FAILED_TYPE + " THEN 1 " +
|
||||
// "ELSE 0 END)";
|
||||
//
|
||||
// String smsGroupSentFailedCount = "SUM(CASE " + SmsDatabase.TYPE + " & " + SmsDatabase.Types.BASE_TYPE_MASK + " " +
|
||||
// "WHEN " + SmsDatabase.Types.BASE_SENT_FAILED_TYPE + " THEN 1 " +
|
||||
// "ELSE 0 END)";
|
||||
//
|
||||
// String[] projection = {MmsSmsColumns.ID, SmsDatabase.BODY, SmsDatabase.TYPE,
|
||||
// MmsSmsColumns.THREAD_ID,
|
||||
// SmsDatabase.ADDRESS, SmsDatabase.SUBJECT, SmsDatabase.STATUS,
|
||||
// MmsSmsColumns.NORMALIZED_DATE_SENT, MmsSmsColumns.NORMALIZED_DATE_RECEIVED,
|
||||
// MmsDatabase.MESSAGE_TYPE, MmsDatabase.MESSAGE_BOX, TRANSPORT,
|
||||
// "COUNT(" + MmsSmsColumns.ID + ") AS " + GROUP_SIZE,
|
||||
// mmsGroupSentCount + " AS " + MMS_GROUP_SENT_COUNT,
|
||||
// mmsGroupSentFailedCount + " AS " + MMS_GROUP_SEND_FAILED_COUNT,
|
||||
// smsGroupSentCount + " AS " + SMS_GROUP_SENT_COUNT,
|
||||
// smsGroupSentFailedCount + " AS " + SMS_GROUP_SEND_FAILED_COUNT,
|
||||
// smsCaseSecurity + " AS sms_collate", mmsCaseSecurity + " AS mms_collate"};
|
||||
//
|
||||
// String order = MmsSmsColumns.NORMALIZED_DATE_RECEIVED + " ASC";
|
||||
// String selection = MmsSmsColumns.THREAD_ID + " = " + threadId;
|
||||
// String groupBy = MmsSmsColumns.NORMALIZED_DATE_SENT + " / 1000, sms_collate, mms_collate";
|
||||
//
|
||||
// Cursor cursor = queryTables(projection, selection, order, groupBy, null);
|
||||
// setNotifyConverationListeners(cursor, threadId);
|
||||
//
|
||||
// return cursor;
|
||||
// }
|
||||
|
||||
public Cursor getConversation(long threadId) {
|
||||
String[] projection = {MmsSmsColumns.ID, SmsDatabase.BODY, SmsDatabase.TYPE,
|
||||
|
|
|
@ -27,7 +27,6 @@ import android.util.Log;
|
|||
import android.util.Pair;
|
||||
|
||||
import org.thoughtcrime.securesms.contacts.ContactPhotoFactory;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
|
@ -405,22 +404,11 @@ public class SmsDatabase extends Database implements MmsSmsColumns {
|
|||
int status = cursor.getInt(cursor.getColumnIndexOrThrow(SmsDatabase.STATUS));
|
||||
Recipients recipients = getRecipientsFor(address);
|
||||
String body = getBody(cursor);
|
||||
MessageRecord.GroupData groupData = null;
|
||||
|
||||
if (cursor.getColumnIndex(MmsSmsDatabase.GROUP_SIZE) != -1) {
|
||||
int groupSize = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsDatabase.GROUP_SIZE));
|
||||
int groupSent = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsDatabase.SMS_GROUP_SENT_COUNT));
|
||||
int groupSendFailed = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsDatabase.SMS_GROUP_SEND_FAILED_COUNT));
|
||||
|
||||
Log.w("ConversationAdapter", "GroupSize: " + groupSize + " , GroupSent: " + groupSent + " , GroupSendFailed: " + groupSendFailed);
|
||||
|
||||
groupData = new MessageRecord.GroupData(groupSize, groupSent, groupSendFailed);
|
||||
}
|
||||
|
||||
return new SmsMessageRecord(context, messageId, body, recipients,
|
||||
recipients.getPrimaryRecipient(),
|
||||
dateSent, dateReceived, type,
|
||||
threadId, status, groupData);
|
||||
threadId, status);
|
||||
}
|
||||
|
||||
private Recipients getRecipientsFor(String address) {
|
||||
|
|
|
@ -38,18 +38,18 @@ import java.util.Set;
|
|||
|
||||
public class ThreadDatabase extends Database {
|
||||
|
||||
static final String TABLE_NAME = "thread";
|
||||
public static final String ID = "_id";
|
||||
public static final String DATE = "date";
|
||||
public static final String MESSAGE_COUNT = "message_count";
|
||||
public static final String RECIPIENT_IDS = "recipient_ids";
|
||||
public static final String SNIPPET = "snippet";
|
||||
private static final String SNIPPET_CHARSET = "snippet_cs";
|
||||
public static final String READ = "read";
|
||||
private static final String TYPE = "type";
|
||||
private static final String ERROR = "error";
|
||||
private static final String HAS_ATTACHMENT = "has_attachment";
|
||||
public static final String SNIPPET_TYPE = "snippet_type";
|
||||
static final String TABLE_NAME = "thread";
|
||||
public static final String ID = "_id";
|
||||
public static final String DATE = "date";
|
||||
public static final String MESSAGE_COUNT = "message_count";
|
||||
public static final String RECIPIENT_IDS = "recipient_ids";
|
||||
public static final String SNIPPET = "snippet";
|
||||
private static final String SNIPPET_CHARSET = "snippet_cs";
|
||||
public static final String READ = "read";
|
||||
private static final String TYPE = "type";
|
||||
private static final String ERROR = "error";
|
||||
private static final String HAS_ATTACHMENT = "has_attachment";
|
||||
public static final String SNIPPET_TYPE = "snippet_type";
|
||||
|
||||
public static final String CREATE_TABLE = "CREATE TABLE " + TABLE_NAME + " (" + ID + " INTEGER PRIMARY KEY, " +
|
||||
DATE + " INTEGER DEFAULT 0, " + MESSAGE_COUNT + " INTEGER DEFAULT 0, " +
|
||||
|
@ -98,7 +98,7 @@ public class ThreadDatabase extends Database {
|
|||
return sb.toString();
|
||||
}
|
||||
|
||||
private long createThreadForRecipients(String recipients, int recipientCount) {
|
||||
private long createThreadForRecipients(String recipients, int recipientCount, int distributionType) {
|
||||
ContentValues contentValues = new ContentValues(4);
|
||||
long date = System.currentTimeMillis();
|
||||
|
||||
|
@ -106,7 +106,7 @@ public class ThreadDatabase extends Database {
|
|||
contentValues.put(RECIPIENT_IDS, recipients);
|
||||
|
||||
if (recipientCount > 1)
|
||||
contentValues.put(TYPE, 1);
|
||||
contentValues.put(TYPE, distributionType);
|
||||
|
||||
contentValues.put(MESSAGE_COUNT, 0);
|
||||
|
||||
|
@ -216,7 +216,16 @@ public class ThreadDatabase extends Database {
|
|||
|
||||
public void setUnread(long threadId) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put("read", 0);
|
||||
contentValues.put(READ, 0);
|
||||
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {threadId+""});
|
||||
notifyConversationListListeners();
|
||||
}
|
||||
|
||||
public void setDistributionType(long threadId, int distributionType) {
|
||||
ContentValues contentValues = new ContentValues(1);
|
||||
contentValues.put(TYPE, distributionType);
|
||||
|
||||
SQLiteDatabase db = databaseHelper.getWritableDatabase();
|
||||
db.update(TABLE_NAME, contentValues, ID_WHERE, new String[] {threadId+""});
|
||||
|
@ -301,6 +310,10 @@ public class ThreadDatabase extends Database {
|
|||
}
|
||||
|
||||
public long getThreadIdFor(Recipients recipients) {
|
||||
return getThreadIdFor(recipients, 0);
|
||||
}
|
||||
|
||||
public long getThreadIdFor(Recipients recipients, int distributionType) {
|
||||
long[] recipientIds = getRecipientIds(recipients);
|
||||
String recipientsList = getRecipientsAsString(recipientIds);
|
||||
SQLiteDatabase db = databaseHelper.getReadableDatabase();
|
||||
|
@ -314,7 +327,7 @@ public class ThreadDatabase extends Database {
|
|||
if (cursor != null && cursor.moveToFirst())
|
||||
return cursor.getLong(cursor.getColumnIndexOrThrow(ID));
|
||||
else
|
||||
return createThreadForRecipients(recipientsList, recipientIds.length);
|
||||
return createThreadForRecipients(recipientsList, recipientIds.length, distributionType);
|
||||
} finally {
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
|
@ -378,6 +391,12 @@ public class ThreadDatabase extends Database {
|
|||
return new Reader(cursor, masterSecret);
|
||||
}
|
||||
|
||||
public static class DistributionTypes {
|
||||
public static final int DEFAULT = 2;
|
||||
public static final int BROADCAST = 1;
|
||||
public static final int CONVERSATION = 2;
|
||||
}
|
||||
|
||||
public class Reader {
|
||||
|
||||
private final Cursor cursor;
|
||||
|
@ -405,8 +424,10 @@ public class ThreadDatabase extends Database {
|
|||
long count = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.MESSAGE_COUNT));
|
||||
long read = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.READ));
|
||||
long type = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET_TYPE));
|
||||
int distributionType = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.TYPE));
|
||||
|
||||
return new ThreadRecord(context, body, recipients, date, count, read == 1, threadId, type);
|
||||
return new ThreadRecord(context, body, recipients, date, count,
|
||||
read == 1, threadId, type, distributionType);
|
||||
}
|
||||
|
||||
private String getPlaintextBody(Cursor cursor) {
|
||||
|
|
|
@ -10,21 +10,15 @@ public class ConversationLoader extends CursorLoader {
|
|||
|
||||
private final Context context;
|
||||
private final long threadId;
|
||||
private final boolean isGroupConversation;
|
||||
|
||||
public ConversationLoader(Context context, long threadId, boolean isGroupConversation) {
|
||||
public ConversationLoader(Context context, long threadId) {
|
||||
super(context);
|
||||
this.context = context.getApplicationContext();
|
||||
this.threadId = threadId;
|
||||
this.isGroupConversation = isGroupConversation;
|
||||
this.context = context.getApplicationContext();
|
||||
this.threadId = threadId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor loadInBackground() {
|
||||
if (!isGroupConversation) {
|
||||
return DatabaseFactory.getMmsSmsDatabase(context).getConversation(threadId);
|
||||
} else {
|
||||
return DatabaseFactory.getMmsSmsDatabase(context).getCollatedGroupConversation(threadId);
|
||||
}
|
||||
return DatabaseFactory.getMmsSmsDatabase(context).getConversation(threadId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,13 +41,11 @@ public class MediaMmsMessageRecord extends MessageRecord {
|
|||
|
||||
public MediaMmsMessageRecord(Context context, long id, Recipients recipients,
|
||||
Recipient individualRecipient, long dateSent, long dateReceived,
|
||||
long threadId, SlideDeck slideDeck, long mailbox,
|
||||
GroupData groupData)
|
||||
long threadId, SlideDeck slideDeck, long mailbox)
|
||||
{
|
||||
super(context, id, getBodyFromSlidesIfAvailable(slideDeck), recipients,
|
||||
individualRecipient, dateSent, dateReceived,
|
||||
threadId, DELIVERY_STATUS_NONE, mailbox,
|
||||
groupData);
|
||||
threadId, DELIVERY_STATUS_NONE, mailbox);
|
||||
|
||||
this.context = context.getApplicationContext();
|
||||
this.slideDeck = slideDeck;
|
||||
|
|
|
@ -45,19 +45,17 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
private final Recipient individualRecipient;
|
||||
private final long id;
|
||||
private final int deliveryStatus;
|
||||
private final GroupData groupData;
|
||||
|
||||
public MessageRecord(Context context, long id, String body, Recipients recipients,
|
||||
Recipient individualRecipient,
|
||||
long dateSent, long dateReceived,
|
||||
long threadId, int deliveryStatus,
|
||||
long type, GroupData groupData)
|
||||
long type)
|
||||
{
|
||||
super(context, body, recipients, dateSent, dateReceived, threadId, type);
|
||||
this.id = id;
|
||||
this.individualRecipient = individualRecipient;
|
||||
this.deliveryStatus = deliveryStatus;
|
||||
this.groupData = groupData;
|
||||
}
|
||||
|
||||
public abstract boolean isMms();
|
||||
|
@ -73,7 +71,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
}
|
||||
|
||||
public boolean isPending() {
|
||||
return MmsSmsColumns.Types.isPendingMessageType(type) || isGroupDeliveryPending();
|
||||
return MmsSmsColumns.Types.isPendingMessageType(type);
|
||||
}
|
||||
|
||||
public boolean isSecure() {
|
||||
|
@ -109,18 +107,6 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
return individualRecipient;
|
||||
}
|
||||
|
||||
public GroupData getGroupData() {
|
||||
return this.groupData;
|
||||
}
|
||||
|
||||
protected boolean isGroupDeliveryPending() {
|
||||
if (this.groupData != null) {
|
||||
return groupData.groupSentCount + groupData.groupSendFailedCount < groupData.groupSize;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected SpannableString emphasisAdded(String sequence) {
|
||||
SpannableString spannable = new SpannableString(sequence);
|
||||
spannable.setSpan(new ForegroundColorSpan(context.getResources().getColor(android.R.color.darker_gray)), 0, sequence.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
|
|
@ -47,7 +47,7 @@ public class NotificationMmsMessageRecord extends MessageRecord {
|
|||
int status, byte[] transactionId, long mailbox)
|
||||
{
|
||||
super(context, id, "", recipients, individualRecipient, dateSent, dateReceived,
|
||||
threadId, DELIVERY_STATUS_NONE, mailbox, null);
|
||||
threadId, DELIVERY_STATUS_NONE, mailbox);
|
||||
|
||||
this.contentLocation = contentLocation;
|
||||
this.messageSize = messageSize;
|
||||
|
|
|
@ -40,10 +40,10 @@ public class SmsMessageRecord extends MessageRecord {
|
|||
Recipient individualRecipient,
|
||||
long dateSent, long dateReceived,
|
||||
long type, long threadId,
|
||||
int status, GroupData groupData)
|
||||
int status)
|
||||
{
|
||||
super(context, id, body, recipients, individualRecipient, dateSent, dateReceived,
|
||||
threadId, getGenericDeliveryStatus(status), type, groupData);
|
||||
threadId, getGenericDeliveryStatus(status), type);
|
||||
}
|
||||
|
||||
public long getType() {
|
||||
|
|
|
@ -37,14 +37,17 @@ public class ThreadRecord extends DisplayRecord {
|
|||
private final Context context;
|
||||
private final long count;
|
||||
private final boolean read;
|
||||
private final int distributionType;
|
||||
|
||||
public ThreadRecord(Context context, String body, Recipients recipients, long date,
|
||||
long count, boolean read, long threadId, long type)
|
||||
long count, boolean read, long threadId, long snippetType,
|
||||
int distributionType)
|
||||
{
|
||||
super(context, body, recipients, date, date, threadId, type);
|
||||
this.context = context.getApplicationContext();
|
||||
this.count = count;
|
||||
this.read = read;
|
||||
super(context, body, recipients, date, date, threadId, snippetType);
|
||||
this.context = context.getApplicationContext();
|
||||
this.count = count;
|
||||
this.read = read;
|
||||
this.distributionType = distributionType;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -86,4 +89,7 @@ public class ThreadRecord extends DisplayRecord {
|
|||
return getDateReceived();
|
||||
}
|
||||
|
||||
public int getDistributionType() {
|
||||
return distributionType;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,7 @@ import org.thoughtcrime.securesms.crypto.MasterSecret;
|
|||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -137,13 +138,13 @@ public class MessageNotifier {
|
|||
NotificationState notificationState,
|
||||
boolean signal)
|
||||
{
|
||||
List<NotificationItem> notifications = notificationState.getNotifications();
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
|
||||
Recipients recipients = notifications.get(0).getRecipients();
|
||||
List<NotificationItem>notifications = notificationState.getNotifications();
|
||||
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
|
||||
Recipient recipient = notifications.get(0).getIndividualRecipient();
|
||||
|
||||
builder.setSmallIcon(R.drawable.icon_notification);
|
||||
builder.setLargeIcon(recipients.getPrimaryRecipient().getContactPhoto());
|
||||
builder.setContentTitle(recipients.getPrimaryRecipient().toShortString());
|
||||
builder.setLargeIcon(recipient.getContactPhoto());
|
||||
builder.setContentTitle(recipient.toShortString());
|
||||
builder.setContentText(notifications.get(0).getText());
|
||||
builder.setContentIntent(notifications.get(0).getPendingIntent(context));
|
||||
|
||||
|
@ -179,7 +180,7 @@ public class MessageNotifier {
|
|||
builder.setContentTitle(String.format(context.getString(R.string.MessageNotifier_d_new_messages),
|
||||
notificationState.getMessageCount()));
|
||||
builder.setContentText(String.format(context.getString(R.string.MessageNotifier_most_recent_from_s),
|
||||
notifications.get(0).getRecipientName()));
|
||||
notifications.get(0).getIndividualRecipientName()));
|
||||
builder.setContentIntent(PendingIntent.getActivity(context, 0, new Intent(context, RoutingActivity.class), 0));
|
||||
|
||||
InboxStyle style = new InboxStyle();
|
||||
|
@ -246,6 +247,7 @@ public class MessageNotifier {
|
|||
else reader = DatabaseFactory.getMmsSmsDatabase(context).readerFor(cursor, masterSecret);
|
||||
|
||||
while ((record = reader.getNext()) != null) {
|
||||
Recipient recipient = record.getIndividualRecipient();
|
||||
Recipients recipients = record.getRecipients();
|
||||
long threadId = record.getThreadId();
|
||||
SpannableString body = record.getDisplayBody();
|
||||
|
@ -257,7 +259,7 @@ public class MessageNotifier {
|
|||
body.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, body.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
}
|
||||
|
||||
notificationState.addNotification(new NotificationItem(recipients, threadId, body, image));
|
||||
notificationState.addNotification(new NotificationItem(recipient, recipients, threadId, body, image));
|
||||
}
|
||||
|
||||
return notificationState;
|
||||
|
|
|
@ -7,29 +7,34 @@ import android.net.Uri;
|
|||
import android.text.SpannableStringBuilder;
|
||||
|
||||
import org.thoughtcrime.securesms.RoutingActivity;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
||||
public class NotificationItem {
|
||||
|
||||
private final Recipients recipients;
|
||||
private final Recipient individualRecipient;
|
||||
private final long threadId;
|
||||
private final CharSequence text;
|
||||
private final Uri image;
|
||||
|
||||
public NotificationItem(Recipients recipients, long threadId, CharSequence text, Uri image) {
|
||||
this.recipients = recipients;
|
||||
this.text = text;
|
||||
this.image = image;
|
||||
this.threadId = threadId;
|
||||
public NotificationItem(Recipient individualRecipient, Recipients recipients, long threadId,
|
||||
CharSequence text, Uri image)
|
||||
{
|
||||
this.individualRecipient = individualRecipient;
|
||||
this.recipients = recipients;
|
||||
this.text = text;
|
||||
this.image = image;
|
||||
this.threadId = threadId;
|
||||
}
|
||||
|
||||
public Recipients getRecipients() {
|
||||
return recipients;
|
||||
public Recipient getIndividualRecipient() {
|
||||
return individualRecipient;
|
||||
}
|
||||
|
||||
public String getRecipientName() {
|
||||
return recipients.getPrimaryRecipient().toShortString();
|
||||
public String getIndividualRecipientName() {
|
||||
return individualRecipient.toShortString();
|
||||
}
|
||||
|
||||
public CharSequence getText() {
|
||||
|
@ -54,7 +59,7 @@ public class NotificationItem {
|
|||
|
||||
public CharSequence getTickerText() {
|
||||
SpannableStringBuilder builder = new SpannableStringBuilder();
|
||||
builder.append(Util.getBoldedString(getRecipientName()));
|
||||
builder.append(Util.getBoldedString(getIndividualRecipientName()));
|
||||
builder.append(": ");
|
||||
builder.append(getText());
|
||||
|
||||
|
@ -65,7 +70,7 @@ public class NotificationItem {
|
|||
Intent intent = new Intent(context, RoutingActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
||||
|
||||
if (recipients.getPrimaryRecipient() != null) {
|
||||
if (recipients != null) {
|
||||
intent.putExtra("recipients", recipients);
|
||||
intent.putExtra("thread_id", threadId);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ public class NotificationState {
|
|||
}
|
||||
|
||||
public Bitmap getContactPhoto() {
|
||||
return notifications.get(0).getRecipients().getPrimaryRecipient().getContactPhoto();
|
||||
return notifications.get(0).getIndividualRecipient().getContactPhoto();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -91,29 +91,29 @@ public class Recipients implements Parcelable {
|
|||
return false;
|
||||
}
|
||||
|
||||
public Recipients getSecureSessionRecipients(Context context) {
|
||||
List<Recipient> secureRecipients = new LinkedList<Recipient>();
|
||||
|
||||
for (Recipient recipient : recipients) {
|
||||
if (KeyUtil.isSessionFor(context, recipient)) {
|
||||
secureRecipients.add(recipient);
|
||||
}
|
||||
}
|
||||
|
||||
return new Recipients(secureRecipients);
|
||||
}
|
||||
|
||||
public Recipients getInsecureSessionRecipients(Context context) {
|
||||
List<Recipient> insecureRecipients = new LinkedList<Recipient>();
|
||||
|
||||
for (Recipient recipient : recipients) {
|
||||
if (!KeyUtil.isSessionFor(context, recipient)) {
|
||||
insecureRecipients.add(recipient);
|
||||
}
|
||||
}
|
||||
|
||||
return new Recipients(insecureRecipients);
|
||||
}
|
||||
// public Recipients getSecureSessionRecipients(Context context) {
|
||||
// List<Recipient> secureRecipients = new LinkedList<Recipient>();
|
||||
//
|
||||
// for (Recipient recipient : recipients) {
|
||||
// if (KeyUtil.isSessionFor(context, recipient)) {
|
||||
// secureRecipients.add(recipient);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return new Recipients(secureRecipients);
|
||||
// }
|
||||
//
|
||||
// public Recipients getInsecureSessionRecipients(Context context) {
|
||||
// List<Recipient> insecureRecipients = new LinkedList<Recipient>();
|
||||
//
|
||||
// for (Recipient recipient : recipients) {
|
||||
// if (!KeyUtil.isSessionFor(context, recipient)) {
|
||||
// insecureRecipients.add(recipient);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return new Recipients(insecureRecipients);
|
||||
// }
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.recipients.isEmpty();
|
||||
|
|
|
@ -22,9 +22,9 @@ import android.util.Log;
|
|||
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.mms.TextSlide;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
import org.thoughtcrime.securesms.service.SendReceiveService;
|
||||
|
||||
|
@ -39,11 +39,12 @@ import ws.com.google.android.mms.pdu.SendReq;
|
|||
public class MessageSender {
|
||||
|
||||
public static long sendMms(Context context, MasterSecret masterSecret, Recipients recipients,
|
||||
long threadId, SlideDeck slideDeck, String message, boolean forcePlaintext)
|
||||
long threadId, SlideDeck slideDeck, String message, int distributionType,
|
||||
boolean forcePlaintext)
|
||||
throws MmsException
|
||||
{
|
||||
if (threadId == -1)
|
||||
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients);
|
||||
threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients, distributionType);
|
||||
|
||||
if (message.trim().length() > 0)
|
||||
slideDeck.addSlide(new TextSlide(context, message));
|
||||
|
@ -55,17 +56,19 @@ public class MessageSender {
|
|||
sendRequest.setBody(body);
|
||||
sendRequest.setContentType(ContentType.MULTIPART_MIXED.getBytes());
|
||||
|
||||
Recipients secureRecipients = recipients.getSecureSessionRecipients(context);
|
||||
Recipients insecureRecipients = recipients.getInsecureSessionRecipients(context);
|
||||
// Recipients secureRecipients = recipients.getSecureSessionRecipients(context);
|
||||
// Recipients insecureRecipients = recipients.getInsecureSessionRecipients(context);
|
||||
|
||||
for (Recipient secureRecipient : secureRecipients.getRecipientsList()) {
|
||||
sendMms(context, new Recipients(secureRecipient), masterSecret,
|
||||
sendRequest, threadId, !forcePlaintext);
|
||||
}
|
||||
// for (Recipient secureRecipient : secureRecipients.getRecipientsList()) {
|
||||
// sendMms(context, new Recipients(secureRecipient), masterSecret,
|
||||
// sendRequest, threadId, !forcePlaintext);
|
||||
// }
|
||||
//
|
||||
// if (!insecureRecipients.isEmpty()) {
|
||||
// sendMms(context, insecureRecipients, masterSecret, sendRequest, threadId, false);
|
||||
// }
|
||||
|
||||
if (!insecureRecipients.isEmpty()) {
|
||||
sendMms(context, insecureRecipients, masterSecret, sendRequest, threadId, false);
|
||||
}
|
||||
sendMms(context, recipients, masterSecret, sendRequest, threadId, distributionType, false);
|
||||
|
||||
return threadId;
|
||||
}
|
||||
|
@ -93,13 +96,19 @@ public class MessageSender {
|
|||
}
|
||||
|
||||
private static void sendMms(Context context, Recipients recipients, MasterSecret masterSecret,
|
||||
SendReq sendRequest, long threadId, boolean secure)
|
||||
SendReq sendRequest, long threadId, int distributionType, boolean secure)
|
||||
throws MmsException
|
||||
{
|
||||
String[] recipientsArray = recipients.toNumberStringArray(true);
|
||||
EncodedStringValue[] encodedNumbers = EncodedStringValue.encodeStrings(recipientsArray);
|
||||
|
||||
sendRequest.setTo(encodedNumbers);
|
||||
if (recipients.isSingleRecipient()) {
|
||||
sendRequest.setTo(encodedNumbers);
|
||||
} else if (distributionType == ThreadDatabase.DistributionTypes.BROADCAST) {
|
||||
sendRequest.setBcc(encodedNumbers);
|
||||
} else if (distributionType == ThreadDatabase.DistributionTypes.CONVERSATION) {
|
||||
sendRequest.setCc(encodedNumbers);
|
||||
}
|
||||
|
||||
long messageId = DatabaseFactory.getMmsDatabase(context)
|
||||
.insertMessageOutbox(masterSecret, sendRequest, threadId, secure);
|
||||
|
|
|
@ -24,7 +24,7 @@ public class UniversalTransport {
|
|||
}
|
||||
|
||||
public void deliver(SmsMessageRecord message) throws UndeliverableMessageException {
|
||||
Recipient recipient = message.getRecipients().getPrimaryRecipient();
|
||||
Recipient recipient = message.getIndividualRecipient();
|
||||
String number = PhoneNumberFormatter.formatNumber(context, recipient.getNumber());
|
||||
|
||||
if (NumberFilter.getInstance(context).containsNumber(number)) {
|
||||
|
|
|
@ -33,6 +33,8 @@ import java.util.concurrent.ExecutorService;
|
|||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import ws.com.google.android.mms.pdu.EncodedStringValue;
|
||||
|
||||
public class Util {
|
||||
|
||||
public static byte[] combine(byte[] one, byte[] two) {
|
||||
|
@ -105,6 +107,10 @@ public class Util {
|
|||
return value == null || value.length() == 0;
|
||||
}
|
||||
|
||||
public static boolean isEmpty(EncodedStringValue[] value) {
|
||||
return value == null || value.length == 0;
|
||||
}
|
||||
|
||||
public static CharSequence getBoldedString(String value) {
|
||||
SpannableString spanned = new SpannableString(value);
|
||||
spanned.setSpan(new StyleSpan(Typeface.BOLD), 0,
|
||||
|
@ -156,6 +162,7 @@ public class Util {
|
|||
return new String(bout.toByteArray());
|
||||
}
|
||||
|
||||
|
||||
// public static Bitmap loadScaledBitmap(InputStream src, int targetWidth, int targetHeight) {
|
||||
// return BitmapFactory.decodeStream(src);
|
||||
//// BitmapFactory.Options options = new BitmapFactory.Options();
|
||||
|
|
Loading…
Add table
Reference in a new issue