mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-22 07:57:30 +00:00
Major reorganization of view/model interactions.
Mostly, the inheritance graph for MessageRecord/MmsMessageRecord was all messed up, and each class was overloaded for things it shouldn't have been. 1) Broke MessageRecord/MmsMessageRecord up into: DisplayRecord, ThreadRecord, MessageRecord, SmsMessageRecord, NotificationMmsMessageRecord, and MediaMmsMessageRecord. 2) Updated all the adapters/views to keep pace with that change.
This commit is contained in:
parent
0b3e939ac8
commit
3a8d29e279
@ -30,17 +30,25 @@ import org.thoughtcrime.securesms.crypto.MasterCipher;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.crypto.MessageDisplayHelper;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.MmsSmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.mms.MmsFactory;
|
||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
|
||||
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.service.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.util.InvalidMessageException;
|
||||
|
||||
import ws.com.google.android.mms.MmsException;
|
||||
import ws.com.google.android.mms.pdu.MultimediaMessagePdu;
|
||||
import ws.com.google.android.mms.pdu.NotificationInd;
|
||||
import ws.com.google.android.mms.pdu.PduHeaders;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@ -56,6 +64,8 @@ public class ConversationAdapter extends CursorAdapter {
|
||||
|
||||
private static final int MAX_CACHE_SIZE = 40;
|
||||
|
||||
|
||||
|
||||
private final TouchListener touchListener = new TouchListener();
|
||||
private final LinkedHashMap<String,MessageRecord> messageRecordCache;
|
||||
private final Handler failedIconClickHandler;
|
||||
@ -68,7 +78,9 @@ public class ConversationAdapter extends CursorAdapter {
|
||||
|
||||
private boolean dataChanged;
|
||||
|
||||
public ConversationAdapter(Recipients recipients, long threadId, Context context, MasterSecret masterSecret, Handler failedIconClickHandler) {
|
||||
public ConversationAdapter(Recipients recipients, long threadId, Context context,
|
||||
MasterSecret masterSecret, Handler failedIconClickHandler)
|
||||
{
|
||||
super(context, null);
|
||||
this.context = context;
|
||||
this.recipients = recipients;
|
||||
@ -85,27 +97,15 @@ public class ConversationAdapter extends CursorAdapter {
|
||||
MessageNotifier.updateNotification(context, false);
|
||||
}
|
||||
|
||||
private Recipient buildRecipient(String address) {
|
||||
Recipient recipient;
|
||||
|
||||
try {
|
||||
if (address == null) recipient = recipients.getPrimaryRecipient();
|
||||
else recipient = RecipientFactory.getRecipientsFromString(context, address).getPrimaryRecipient();
|
||||
} catch (RecipientFormattingException e) {
|
||||
Log.w("ConversationAdapter", e);
|
||||
recipient = new Recipient("Unknown", "Unknown", null);
|
||||
}
|
||||
|
||||
return recipient;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(View view, Context context, Cursor cursor) {
|
||||
ConversationItem item = (ConversationItem)view;
|
||||
long id = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.ID));
|
||||
String type = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.TRANSPORT));
|
||||
String type = cursor.getString(cursor.getColumnIndexOrThrow(MmsSmsDatabase.TRANSPORT));
|
||||
MessageRecord messageRecord = getMessageRecord(id, cursor, type);
|
||||
|
||||
((ConversationItem)view).set(masterSecret, messageRecord, failedIconClickHandler);
|
||||
item.set(masterSecret, messageRecord, failedIconClickHandler);
|
||||
|
||||
view.setOnTouchListener(touchListener);
|
||||
}
|
||||
|
||||
@ -135,35 +135,85 @@ public class ConversationAdapter extends CursorAdapter {
|
||||
|
||||
private int getItemViewType(Cursor cursor) {
|
||||
long id = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.ID));
|
||||
String type = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.TRANSPORT));
|
||||
String type = cursor.getString(cursor.getColumnIndexOrThrow(MmsSmsDatabase.TRANSPORT));
|
||||
MessageRecord messageRecord = getMessageRecord(id, cursor, type);
|
||||
|
||||
if (messageRecord.isOutgoing()) return 0;
|
||||
else return 1;
|
||||
}
|
||||
|
||||
private MessageRecord getNewMmsMessageRecord(long messageId, Cursor cursor) {
|
||||
MessageRecord messageRecord = getNewSmsMessageRecord(messageId, cursor);
|
||||
long mmsType = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_TYPE));
|
||||
long mmsBox = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX));
|
||||
private MediaMmsMessageRecord getMediaMmsMessageRecord(long messageId, Cursor cursor) {
|
||||
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.ID));
|
||||
long date = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.DATE));
|
||||
long box = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_BOX));
|
||||
Recipient recipient = getIndividualRecipientFor(null);
|
||||
|
||||
SlideDeck slideDeck;
|
||||
|
||||
try {
|
||||
return MmsFactory.getMms(context, masterSecret, messageRecord, mmsType, mmsBox);
|
||||
MultimediaMessagePdu pdu = DatabaseFactory.getEncryptingMmsDatabase(context, masterSecret).getMediaMessage(messageId);
|
||||
slideDeck = new SlideDeck(context, masterSecret, pdu.getBody());
|
||||
} catch (MmsException me) {
|
||||
Log.w("ConversationAdapter", me);
|
||||
return messageRecord;
|
||||
slideDeck = null;
|
||||
}
|
||||
|
||||
return new MediaMmsMessageRecord(context, id, recipients, recipient,
|
||||
date, threadId, slideDeck, box);
|
||||
}
|
||||
|
||||
private MessageRecord getNewSmsMessageRecord(long messageId, Cursor cursor) {
|
||||
long date = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.DATE));
|
||||
long type = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.TYPE));
|
||||
String address = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.ADDRESS));
|
||||
Recipient recipient = buildRecipient(address);
|
||||
MessageRecord messageRecord = new MessageRecord(messageId, recipients, date, type, threadId);
|
||||
private NotificationMmsMessageRecord getNotificationMmsMessageRecord(long messageId, Cursor cursor) {
|
||||
Recipient recipient = getIndividualRecipientFor(null);
|
||||
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.ID));
|
||||
long date = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.DATE));
|
||||
|
||||
messageRecord.setMessageRecipient(recipient);
|
||||
setBody(cursor, messageRecord);
|
||||
NotificationInd notification;
|
||||
|
||||
try {
|
||||
notification = DatabaseFactory.getMmsDatabase(context).getNotificationMessage(messageId);
|
||||
} catch (MmsException me) {
|
||||
Log.w("ConversationAdapter", me);
|
||||
notification = new NotificationInd(new PduHeaders());
|
||||
}
|
||||
|
||||
return new NotificationMmsMessageRecord(id, recipients, recipient, date, threadId,
|
||||
notification.getContentLocation(),
|
||||
notification.getMessageSize(),
|
||||
notification.getExpiry(),
|
||||
notification.getStatus(),
|
||||
notification.getTransactionId());
|
||||
}
|
||||
|
||||
private SmsMessageRecord getSmsMessageRecord(long messageId, Cursor cursor) {
|
||||
long date = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.DATE));
|
||||
long type = cursor.getLong(cursor.getColumnIndexOrThrow(SmsDatabase.TYPE));
|
||||
String body = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.BODY));
|
||||
String address = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.ADDRESS));
|
||||
Recipient recipient = getIndividualRecipientFor(address);
|
||||
// MessageRecord.GroupData groupData = null;
|
||||
//
|
||||
// if (recipients != null && recipients.isSingleRecipient()) {
|
||||
// int groupSize = cursor.getInt(cursor.getColumnIndexOrThrow(MmsSmsDatabase.SMS_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));
|
||||
//
|
||||
// groupData = new MessageRecord.GroupData(groupSize, groupSent, groupSendFailed);
|
||||
// }
|
||||
SmsMessageRecord messageRecord = new SmsMessageRecord(context, messageId, recipients,
|
||||
recipient, date, type, threadId);
|
||||
|
||||
if (body == null) {
|
||||
body = "";
|
||||
}
|
||||
|
||||
try {
|
||||
String decryptedBody = MessageDisplayHelper.getDecryptedMessageBody(masterCipher, body);
|
||||
messageRecord.setBody(decryptedBody);
|
||||
} catch (InvalidMessageException ime) {
|
||||
Log.w("ConversationAdapter", ime);
|
||||
messageRecord.setBody(context.getString(R.string.MessageDisplayHelper_decryption_error_local_message_corrupted_mac_doesn_t_match_potential_tampering_question));
|
||||
messageRecord.setEmphasis(true);
|
||||
}
|
||||
|
||||
return messageRecord;
|
||||
}
|
||||
@ -174,22 +224,35 @@ public class ConversationAdapter extends CursorAdapter {
|
||||
|
||||
MessageRecord messageRecord;
|
||||
|
||||
if (type.equals("mms")) messageRecord = getNewMmsMessageRecord(messageId, cursor);
|
||||
else messageRecord = getNewSmsMessageRecord(messageId, cursor);
|
||||
if (type.equals("mms")) {
|
||||
long mmsType = cursor.getLong(cursor.getColumnIndexOrThrow(MmsDatabase.MESSAGE_TYPE));
|
||||
|
||||
if (mmsType == PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND) {
|
||||
messageRecord = getNotificationMmsMessageRecord(messageId, cursor);
|
||||
} else {
|
||||
messageRecord = getMediaMmsMessageRecord(messageId, cursor);
|
||||
}
|
||||
} else {
|
||||
messageRecord = getSmsMessageRecord(messageId, cursor);
|
||||
}
|
||||
|
||||
messageRecordCache.put(type + messageId, messageRecord);
|
||||
return messageRecord;
|
||||
}
|
||||
|
||||
protected void setBody(Cursor cursor, MessageRecord message) {
|
||||
String body = cursor.getString(cursor.getColumnIndexOrThrow(SmsDatabase.BODY));
|
||||
private Recipient getIndividualRecipientFor(String address) {
|
||||
Recipient recipient;
|
||||
|
||||
if (body == null)
|
||||
message.setBody("");
|
||||
else
|
||||
MessageDisplayHelper.setDecryptedMessageBody(context, body, message, masterCipher);
|
||||
try {
|
||||
if (address == null) recipient = recipients.getPrimaryRecipient();
|
||||
else recipient = RecipientFactory.getRecipientsFromString(context, address).getPrimaryRecipient();
|
||||
} catch (RecipientFormattingException e) {
|
||||
Log.w("ConversationAdapter", e);
|
||||
recipient = new Recipient("Unknown", "Unknown", null);
|
||||
}
|
||||
|
||||
return recipient;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onContentChanged() {
|
||||
super.onContentChanged();
|
||||
|
@ -21,8 +21,8 @@ import com.actionbarsherlock.app.SherlockListFragment;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.loaders.ConversationLoader;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
import java.sql.Date;
|
||||
@ -98,9 +98,8 @@ public class ConversationFragment extends SherlockListFragment
|
||||
clipboard.setText(body);
|
||||
}
|
||||
|
||||
private void handleDeleteMessage(MessageRecord message) {
|
||||
private void handleDeleteMessage(final MessageRecord message) {
|
||||
final long messageId = message.getId();
|
||||
final String transport = message.isMms() ? "mms" : "sms";
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setTitle(R.string.ConversationFragment_confirm_message_delete);
|
||||
@ -111,7 +110,7 @@ public class ConversationFragment extends SherlockListFragment
|
||||
builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (transport.equals("mms")) {
|
||||
if (message.isMms()) {
|
||||
DatabaseFactory.getMmsDatabase(getActivity()).delete(messageId);
|
||||
} else {
|
||||
DatabaseFactory.getSmsDatabase(getActivity()).deleteMessage(messageId);
|
||||
@ -165,7 +164,8 @@ public class ConversationFragment extends SherlockListFragment
|
||||
|
||||
@Override
|
||||
public Loader<Cursor> onCreateLoader(int arg0, Bundle arg1) {
|
||||
return new ConversationLoader(getActivity(), threadId);
|
||||
return new ConversationLoader(getActivity(), threadId,
|
||||
(recipients != null && !recipients.isSingleRecipient()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -43,9 +43,10 @@ import android.widget.Toast;
|
||||
|
||||
import org.thoughtcrime.securesms.contacts.ContactIdentityManager;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.MmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.mms.SlideDeck;
|
||||
import org.thoughtcrime.securesms.protocol.Tag;
|
||||
@ -126,90 +127,27 @@ public class ConversationItem extends LinearLayout {
|
||||
this.masterSecret = masterSecret;
|
||||
this.failedIconHandler = failedIconHandler;
|
||||
|
||||
// Double-dispatch back to methods below.
|
||||
messageRecord.setOnConversationItem(this);
|
||||
setBodyText(messageRecord);
|
||||
setStatusIcons(messageRecord);
|
||||
setContactPhoto(messageRecord);
|
||||
setEvents(messageRecord);
|
||||
|
||||
if (messageRecord instanceof NotificationMmsMessageRecord) {
|
||||
setNotificationMmsAttributes((NotificationMmsMessageRecord)messageRecord);
|
||||
} else if (messageRecord instanceof MediaMmsMessageRecord) {
|
||||
setMediaMmsAttributes((MediaMmsMessageRecord)messageRecord);
|
||||
}
|
||||
}
|
||||
|
||||
public MessageRecord getMessageRecord() {
|
||||
return messageRecord;
|
||||
}
|
||||
|
||||
public void setMessageRecord(MessageRecord messageRecord) {
|
||||
setBody(messageRecord);
|
||||
setStatusIcons(messageRecord);
|
||||
setEvents(messageRecord);
|
||||
}
|
||||
|
||||
public void setMessageRecord(MmsMessageRecord messageRecord) {
|
||||
setMessageRecord((MessageRecord)messageRecord);
|
||||
|
||||
if (messageRecord.isNotification())
|
||||
setMmsNotificationAttributes(messageRecord);
|
||||
else
|
||||
setMmsMediaAttributes(messageRecord);
|
||||
}
|
||||
|
||||
private void setMmsNotificationAttributes(MmsMessageRecord messageRecord) {
|
||||
String messageSize = String.format(getContext()
|
||||
.getString(R.string.ConversationItem_message_size_d_kb),
|
||||
messageRecord.getMessageSize());
|
||||
String expires = String.format(getContext()
|
||||
.getString(R.string.ConversationItem_expires_s),
|
||||
DateUtils.getRelativeTimeSpanString(getContext(),
|
||||
messageRecord.getExpiration(),
|
||||
false));
|
||||
|
||||
dateText.setText(messageSize + "\n" + expires);
|
||||
|
||||
if (MmsDatabase.Types.isDisplayDownloadButton(messageRecord.getStatus())) {
|
||||
mmsDownloadButton.setVisibility(View.VISIBLE);
|
||||
mmsDownloadingLabel.setVisibility(View.GONE);
|
||||
} else {
|
||||
mmsDownloadingLabel.setText(MmsDatabase.Types.getLabelForStatus(context, messageRecord.getStatus()));
|
||||
mmsDownloadButton.setVisibility(View.GONE);
|
||||
mmsDownloadingLabel.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
if (MmsDatabase.Types.isHardError(messageRecord.getStatus()))
|
||||
failedImage.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void setMmsMediaAttributes(MmsMessageRecord messageRecord) {
|
||||
SlideDeck slideDeck = messageRecord.getSlideDeck();
|
||||
List<Slide> slides = slideDeck.getSlides();
|
||||
|
||||
Iterator<Slide> iterator = slides.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Slide slide = iterator.next();
|
||||
if (slide.hasImage()) {
|
||||
mmsThumbnail.setImageBitmap(slide.getThumbnail());
|
||||
mmsThumbnail.setOnClickListener(new ThumbnailClickListener(slide));
|
||||
mmsThumbnail.setOnLongClickListener(new ThumbnailSaveListener(slide));
|
||||
mmsThumbnail.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mmsThumbnail.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void setHandler(Handler failedIconHandler) {
|
||||
this.failedIconHandler = failedIconHandler;
|
||||
}
|
||||
|
||||
private void checkForAutoInitiate(MessageRecord messageRecord) {
|
||||
if (AutoInitiateActivity.isValidAutoInitiateSituation(context, masterSecret, messageRecord.getRecipients().getPrimaryRecipient(), messageRecord.getBody(), messageRecord.getThreadId())) {
|
||||
AutoInitiateActivity.exemptThread(context, messageRecord.getThreadId());
|
||||
Intent intent = new Intent();
|
||||
intent.setClass(context, AutoInitiateActivity.class);
|
||||
intent.putExtra("threadId", messageRecord.getThreadId());
|
||||
intent.putExtra("masterSecret", masterSecret);
|
||||
intent.putExtra("recipient", messageRecord.getRecipients().getPrimaryRecipient());
|
||||
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
/// MessageRecord Attribute Parsers
|
||||
|
||||
private void setBodyText(MessageRecord messageRecord) {
|
||||
String body = messageRecord.getBody();
|
||||
@ -228,46 +166,12 @@ public class ConversationItem extends LinearLayout {
|
||||
}
|
||||
}
|
||||
|
||||
private void setContactPhotoForUserIdentity() {
|
||||
Uri selfIdentityContact = ContactIdentityManager.getInstance(context).getSelfIdentityUri();
|
||||
|
||||
if (selfIdentityContact!= null) {
|
||||
Recipient recipient = RecipientFactory.getRecipientForUri(context, selfIdentityContact);
|
||||
if (recipient != null) {
|
||||
contactPhoto.setImageBitmap(recipient.getContactPhoto());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
contactPhoto.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_contact_picture));
|
||||
}
|
||||
}
|
||||
|
||||
private void setBodyImage(MessageRecord messageRecord) {
|
||||
final Recipient recipient = messageRecord.getMessageRecipient();
|
||||
|
||||
if (!messageRecord.isOutgoing()) {
|
||||
contactPhoto.setImageBitmap(recipient.getContactPhoto());
|
||||
contactPhoto.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (recipient.getContactUri() != null) {
|
||||
QuickContact.showQuickContact(context, contactPhoto, recipient.getContactUri(), QuickContact.MODE_LARGE, null);
|
||||
} else {
|
||||
Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, Uri.fromParts("tel", recipient.getNumber(), null));
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
private void setContactPhoto(MessageRecord messageRecord) {
|
||||
if (messageRecord.isOutgoing()) {
|
||||
setContactPhotoForUserIdentity();
|
||||
} else {
|
||||
setContactPhotoForRecipient(messageRecord.getIndividualRecipient());
|
||||
}
|
||||
|
||||
contactPhoto.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void setBody(MessageRecord messageRecord) {
|
||||
setBodyText(messageRecord);
|
||||
setBodyImage(messageRecord);
|
||||
}
|
||||
|
||||
private void setStatusIcons(MessageRecord messageRecord) {
|
||||
@ -289,10 +193,112 @@ public class ConversationItem extends LinearLayout {
|
||||
private void setEvents(MessageRecord messageRecord) {
|
||||
setClickable(messageRecord.isKeyExchange() && !messageRecord.isOutgoing());
|
||||
|
||||
if (!messageRecord.isOutgoing() && messageRecord.getRecipients().isSingleRecipient())
|
||||
checkForAutoInitiate(messageRecord);
|
||||
if (!messageRecord.isOutgoing() && messageRecord.getRecipients().isSingleRecipient()) {
|
||||
checkForAutoInitiate(messageRecord.getIndividualRecipient(),
|
||||
messageRecord.getBody(),
|
||||
messageRecord.getThreadId());
|
||||
}
|
||||
}
|
||||
|
||||
private void setNotificationMmsAttributes(NotificationMmsMessageRecord messageRecord) {
|
||||
String messageSize = String.format(getContext()
|
||||
.getString(R.string.ConversationItem_message_size_d_kb),
|
||||
messageRecord.getMessageSize());
|
||||
String expires = String.format(getContext()
|
||||
.getString(R.string.ConversationItem_expires_s),
|
||||
DateUtils.getRelativeTimeSpanString(getContext(),
|
||||
messageRecord.getExpiration(),
|
||||
false));
|
||||
|
||||
dateText.setText(messageSize + "\n" + expires);
|
||||
|
||||
if (MmsDatabase.Types.isDisplayDownloadButton(messageRecord.getStatus())) {
|
||||
mmsDownloadButton.setVisibility(View.VISIBLE);
|
||||
mmsDownloadingLabel.setVisibility(View.GONE);
|
||||
} else {
|
||||
mmsDownloadingLabel.setText(MmsDatabase.Types.getLabelForStatus(context, messageRecord.getStatus()));
|
||||
mmsDownloadButton.setVisibility(View.GONE);
|
||||
mmsDownloadingLabel.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setMediaMmsAttributes(MediaMmsMessageRecord messageRecord) {
|
||||
SlideDeck slideDeck = messageRecord.getSlideDeck();
|
||||
|
||||
if (slideDeck != null) {
|
||||
List<Slide> slides = slideDeck.getSlides();
|
||||
|
||||
Iterator<Slide> iterator = slides.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
Slide slide = iterator.next();
|
||||
if (slide.hasImage()) {
|
||||
mmsThumbnail.setImageBitmap(slide.getThumbnail());
|
||||
mmsThumbnail.setOnClickListener(new ThumbnailClickListener(slide));
|
||||
mmsThumbnail.setOnLongClickListener(new ThumbnailSaveListener(slide));
|
||||
mmsThumbnail.setVisibility(View.VISIBLE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mmsThumbnail.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
/// Helper Methods
|
||||
|
||||
private void checkForAutoInitiate(Recipient recipient, String body, long threadId) {
|
||||
if (AutoInitiateActivity.isValidAutoInitiateSituation(context, masterSecret, recipient,
|
||||
body, threadId))
|
||||
{
|
||||
AutoInitiateActivity.exemptThread(context, threadId);
|
||||
|
||||
Intent intent = new Intent();
|
||||
intent.setClass(context, AutoInitiateActivity.class);
|
||||
intent.putExtra("threadId", threadId);
|
||||
intent.putExtra("masterSecret", masterSecret);
|
||||
intent.putExtra("recipient", recipient);
|
||||
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setContactPhotoForUserIdentity() {
|
||||
Uri selfIdentityContact = ContactIdentityManager.getInstance(context).getSelfIdentityUri();
|
||||
|
||||
if (selfIdentityContact!= null) {
|
||||
Recipient recipient = RecipientFactory.getRecipientForUri(context, selfIdentityContact);
|
||||
if (recipient != null) {
|
||||
contactPhoto.setImageBitmap(recipient.getContactPhoto());
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
contactPhoto.setImageDrawable(context.getResources().getDrawable(R.drawable.ic_contact_picture));
|
||||
}
|
||||
|
||||
contactPhoto.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void setContactPhotoForRecipient(final Recipient recipient) {
|
||||
contactPhoto.setImageBitmap(recipient.getContactPhoto());
|
||||
contactPhoto.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (recipient.getContactUri() != null) {
|
||||
QuickContact.showQuickContact(context, contactPhoto, recipient.getContactUri(), QuickContact.MODE_LARGE, null);
|
||||
} else {
|
||||
Intent intent = new Intent(Intents.SHOW_OR_CREATE_CONTACT, Uri.fromParts("tel", recipient.getNumber(), null));
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
contactPhoto.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
/// Event handlers
|
||||
|
||||
private void handleKeyExchangeClicked() {
|
||||
Intent intent = new Intent(context, ReceiveKeyActivity.class);
|
||||
intent.putExtra("recipient", messageRecord.getRecipients().getPrimaryRecipient());
|
||||
@ -452,15 +458,16 @@ public class ConversationItem extends LinearLayout {
|
||||
|
||||
private class MmsDownloadClickListener implements View.OnClickListener {
|
||||
public void onClick(View v) {
|
||||
Log.w("MmsDownloadClickListener", "Content location: " + new String(((MmsMessageRecord)messageRecord).getContentLocation()));
|
||||
NotificationMmsMessageRecord notificationRecord = (NotificationMmsMessageRecord)messageRecord;
|
||||
Log.w("MmsDownloadClickListener", "Content location: " + new String(notificationRecord.getContentLocation()));
|
||||
mmsDownloadButton.setVisibility(View.GONE);
|
||||
mmsDownloadingLabel.setVisibility(View.VISIBLE);
|
||||
|
||||
Intent intent = new Intent(context, SendReceiveService.class);
|
||||
intent.putExtra("content_location", new String(((MmsMessageRecord)messageRecord).getContentLocation()));
|
||||
intent.putExtra("message_id", ((MmsMessageRecord)messageRecord).getId());
|
||||
intent.putExtra("transaction_id", ((MmsMessageRecord)messageRecord).getTransactionId());
|
||||
intent.putExtra("thread_id", ((MmsMessageRecord)messageRecord).getThreadId());
|
||||
intent.putExtra("content_location", new String(notificationRecord.getContentLocation()));
|
||||
intent.putExtra("message_id", notificationRecord.getId());
|
||||
intent.putExtra("transaction_id", notificationRecord.getTransactionId());
|
||||
intent.putExtra("thread_id", notificationRecord.getThreadId());
|
||||
intent.setAction(SendReceiveService.DOWNLOAD_MMS_ACTION);
|
||||
context.startService(intent);
|
||||
}
|
||||
|
@ -23,9 +23,8 @@ import android.view.ViewGroup;
|
||||
import android.widget.CursorAdapter;
|
||||
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.protocol.Prefix;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
@ -68,28 +67,19 @@ public class ConversationListAdapter extends CursorAdapter {
|
||||
long count = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.MESSAGE_COUNT));
|
||||
long read = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.READ));
|
||||
|
||||
MessageRecord message = new MessageRecord(-1, recipients, date, count, read == 1, threadId);
|
||||
setBody(cursor, message);
|
||||
ThreadRecord thread = new ThreadRecord(context, recipients, date, count, read == 1, threadId);
|
||||
setBody(cursor, thread);
|
||||
|
||||
((ConversationListItem)view).set(message, batchMode);
|
||||
((ConversationListItem)view).set(thread, batchMode);
|
||||
}
|
||||
|
||||
protected void filterBody(MessageRecord message, String body) {
|
||||
protected void filterBody(ThreadRecord thread, String body) {
|
||||
if (body == null) body = "(No subject)";
|
||||
|
||||
if (body.startsWith(Prefix.SYMMETRIC_ENCRYPT) || body.startsWith(Prefix.ASYMMETRIC_ENCRYPT) || body.startsWith(Prefix.ASYMMETRIC_LOCAL_ENCRYPT)) {
|
||||
message.setBody(context.getString(R.string.ConversationListAdapter_encrypted_message_enter_passphrase));
|
||||
message.setEmphasis(true);
|
||||
} else if (body.startsWith(Prefix.KEY_EXCHANGE)) {
|
||||
message.setBody(context.getString(R.string.ConversationListAdapter_key_exchange_message));
|
||||
message.setEmphasis(true);
|
||||
} else {
|
||||
message.setBody(body);
|
||||
}
|
||||
thread.setBody(body);
|
||||
}
|
||||
|
||||
protected void setBody(Cursor cursor, MessageRecord message) {
|
||||
filterBody(message, cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET)));
|
||||
protected void setBody(Cursor cursor, ThreadRecord thread) {
|
||||
filterBody(thread, cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET)));
|
||||
}
|
||||
|
||||
public void addToBatchSet(long threadId) {
|
||||
|
@ -33,7 +33,7 @@ import android.widget.QuickContactBadge;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.thoughtcrime.securesms.database.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
import java.util.Set;
|
||||
@ -84,22 +84,22 @@ public class ConversationListItem extends RelativeLayout {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public void set(MessageRecord message, boolean batchMode) {
|
||||
this.recipients = message.getRecipients();
|
||||
this.threadId = message.getThreadId();
|
||||
this.fromView.setText(formatFrom(recipients, message.getCount(), message.getRead()));
|
||||
public void set(ThreadRecord thread, boolean batchMode) {
|
||||
this.recipients = thread.getRecipients();
|
||||
this.threadId = thread.getThreadId();
|
||||
this.fromView.setText(formatFrom(recipients, thread.getCount(), thread.isRead()));
|
||||
|
||||
if (message.isKeyExchange())
|
||||
if (thread.isKeyExchange())
|
||||
this.subjectView.setText(R.string.ConversationListItem_key_exchange_message,
|
||||
TextView.BufferType.SPANNABLE);
|
||||
else
|
||||
this.subjectView.setText(message.getBody(), TextView.BufferType.SPANNABLE);
|
||||
this.subjectView.setText(thread.getBody(), TextView.BufferType.SPANNABLE);
|
||||
|
||||
if (message.getEmphasis())
|
||||
if (thread.getEmphasis())
|
||||
((Spannable)this.subjectView.getText()).setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, this.subjectView.getText().length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||
|
||||
if (message.getDate() > 0)
|
||||
this.dateView.setText(DateUtils.getRelativeTimeSpanString(getContext(), message.getDate(), false));
|
||||
if (thread.getDate() > 0)
|
||||
this.dateView.setText(DateUtils.getRelativeTimeSpanString(getContext(), thread.getDate(), false));
|
||||
|
||||
if (selectedThreads != null)
|
||||
this.checkbox.setChecked(selectedThreads.contains(threadId));
|
||||
|
@ -22,8 +22,9 @@ import android.database.Cursor;
|
||||
import org.thoughtcrime.securesms.crypto.MasterCipher;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.crypto.MessageDisplayHelper;
|
||||
import org.thoughtcrime.securesms.database.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.ThreadRecord;
|
||||
import org.thoughtcrime.securesms.util.InvalidMessageException;
|
||||
|
||||
/**
|
||||
* A ConversationListAdapter that decrypts encrypted message bodies.
|
||||
@ -43,9 +44,16 @@ public class DecryptingConversationListAdapter extends ConversationListAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setBody(Cursor cursor, MessageRecord message) {
|
||||
protected void setBody(Cursor cursor, ThreadRecord thread) {
|
||||
String body = cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET));
|
||||
if (body == null || body.equals("")) body = "(No subject)";
|
||||
MessageDisplayHelper.setDecryptedMessageBody(context, body, message, bodyCipher);
|
||||
|
||||
try {
|
||||
String decryptedBody = MessageDisplayHelper.getDecryptedMessageBody(bodyCipher, body);
|
||||
thread.setBody(decryptedBody);
|
||||
} catch (InvalidMessageException ime) {
|
||||
thread.setBody(context.getString(R.string.MessageDisplayHelper_decryption_error_local_message_corrupted_mac_doesn_t_match_potential_tampering_question));
|
||||
thread.setEmphasis(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,7 @@ class ContactIdentityManagerICS extends ContactIdentityManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
@Override
|
||||
public List<Long> getSelfIdentityRawContactIds() {
|
||||
List<Long> results = new LinkedList<Long>();
|
||||
|
@ -16,17 +16,11 @@
|
||||
*/
|
||||
package org.thoughtcrime.securesms.crypto;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.protocol.Prefix;
|
||||
import org.thoughtcrime.securesms.util.InvalidMessageException;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class MessageDisplayHelper {
|
||||
|
||||
@ -39,30 +33,6 @@ public class MessageDisplayHelper {
|
||||
}
|
||||
};
|
||||
|
||||
private static boolean isUnreadableAsymmetricMessage(long type) {
|
||||
return type == SmsDatabase.Types.FAILED_DECRYPT_TYPE;
|
||||
}
|
||||
|
||||
private static boolean isInProcessAsymmetricMessage(String body, long type) {
|
||||
return type == SmsDatabase.Types.DECRYPT_IN_PROGRESS_TYPE || (type == 0 && body.startsWith(Prefix.ASYMMETRIC_ENCRYPT)) || (type == 0 && body.startsWith(Prefix.ASYMMETRIC_LOCAL_ENCRYPT));
|
||||
}
|
||||
|
||||
private static boolean isRogueAsymmetricMessage(long type) {
|
||||
return type == SmsDatabase.Types.NO_SESSION_TYPE;
|
||||
}
|
||||
|
||||
private static boolean isKeyExchange(String body) {
|
||||
return body.startsWith(Prefix.KEY_EXCHANGE);
|
||||
}
|
||||
|
||||
private static boolean isProcessedKeyExchange(String body) {
|
||||
return body.startsWith(Prefix.PROCESSED_KEY_EXCHANGE);
|
||||
}
|
||||
|
||||
private static boolean isStaleKeyExchange(String body) {
|
||||
return body.startsWith(Prefix.STALE_KEY_EXCHANGE);
|
||||
}
|
||||
|
||||
private static String checkCacheForBody(String body) {
|
||||
if (decryptedBodyCache.containsKey(body)) {
|
||||
String decryptedBody = decryptedBodyCache.get(body).get();
|
||||
@ -77,50 +47,19 @@ public class MessageDisplayHelper {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void setDecryptedMessageBody(Context context, String body,
|
||||
MessageRecord message, MasterCipher bodyCipher)
|
||||
{
|
||||
try {
|
||||
if (body.startsWith(Prefix.SYMMETRIC_ENCRYPT)) {
|
||||
String cacheResult = checkCacheForBody(body);
|
||||
if (cacheResult != null) {
|
||||
body = cacheResult;
|
||||
} else {
|
||||
String decryptedBody = bodyCipher.decryptBody(body.substring(Prefix.SYMMETRIC_ENCRYPT.length()));
|
||||
decryptedBodyCache.put(body, new SoftReference<String>(decryptedBody));
|
||||
body = decryptedBody;
|
||||
}
|
||||
}
|
||||
public static String getDecryptedMessageBody(MasterCipher bodyCipher, String body) throws InvalidMessageException {
|
||||
if (body.startsWith(Prefix.SYMMETRIC_ENCRYPT)) {
|
||||
String cacheResult = checkCacheForBody(body);
|
||||
|
||||
if (isUnreadableAsymmetricMessage(message.getType())) {
|
||||
message.setBody(context.getString(R.string.MessageDisplayHelper_bad_encrypted_message));
|
||||
message.setEmphasis(true);
|
||||
} else if (isInProcessAsymmetricMessage(body, message.getType())) {
|
||||
message.setBody(context.getString(R.string.MessageDisplayHelper_decrypting_please_wait));
|
||||
message.setEmphasis(true);
|
||||
} else if (isRogueAsymmetricMessage(message.getType())) {
|
||||
message.setBody(context.getString(R.string.MessageDisplayHelper_message_encrypted_for_non_existing_session));
|
||||
message.setEmphasis(true);
|
||||
} else if (isKeyExchange(body)) {
|
||||
message.setKeyExchange(true);
|
||||
message.setEmphasis(true);
|
||||
message.setBody(body);
|
||||
} else if (isProcessedKeyExchange(body)) {
|
||||
message.setProcessedKeyExchange(true);
|
||||
message.setEmphasis(true);
|
||||
message.setBody(body);
|
||||
} else if (isStaleKeyExchange(body)) {
|
||||
message.setStaleKeyExchange(true);
|
||||
message.setEmphasis(true);
|
||||
message.setBody(body);
|
||||
} else {
|
||||
message.setBody(body);
|
||||
message.setEmphasis(false);
|
||||
}
|
||||
} catch (InvalidMessageException ime) {
|
||||
message.setBody(context.getString(R.string.MessageDisplayHelper_decryption_error_local_message_corrupted_mac_doesn_t_match_potential_tampering_question));
|
||||
message.setEmphasis(true);
|
||||
if (cacheResult != null)
|
||||
return cacheResult;
|
||||
|
||||
String decryptedBody = bodyCipher.decryptBody(body.substring(Prefix.SYMMETRIC_ENCRYPT.length()));
|
||||
decryptedBodyCache.put(body, new SoftReference<String>(decryptedBody));
|
||||
|
||||
return decryptedBody;
|
||||
}
|
||||
}
|
||||
|
||||
return body;
|
||||
}
|
||||
}
|
||||
|
@ -1,181 +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 org.thoughtcrime.securesms.ConversationItem;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
public class MessageRecord {
|
||||
|
||||
private long id;
|
||||
private long threadId;
|
||||
private Recipient messageRecipient;
|
||||
private Recipients recipients;
|
||||
private String body;
|
||||
private long date;
|
||||
private long count;
|
||||
private boolean read;
|
||||
private long type;
|
||||
private boolean emphasis;
|
||||
private boolean keyExchange;
|
||||
private boolean processedKeyExchange;
|
||||
private boolean staleKeyExchange;
|
||||
|
||||
public MessageRecord(MessageRecord copy) {
|
||||
this.id = copy.id;
|
||||
this.threadId = copy.threadId;
|
||||
this.messageRecipient = copy.messageRecipient;
|
||||
this.recipients = copy.recipients;
|
||||
this.body = copy.body;
|
||||
this.date = copy.date;
|
||||
this.count = copy.count;
|
||||
this.read = copy.read;
|
||||
this.type = copy.type;
|
||||
this.emphasis = copy.emphasis;
|
||||
this.keyExchange = copy.keyExchange;
|
||||
this.processedKeyExchange = copy.processedKeyExchange;
|
||||
}
|
||||
|
||||
public MessageRecord(long id, Recipients recipients, long date, long type, long threadId) {
|
||||
this.id = id;
|
||||
this.date = date;
|
||||
this.type = type;
|
||||
this.recipients = recipients;
|
||||
this.threadId = threadId;
|
||||
}
|
||||
|
||||
public MessageRecord(long id, Recipients recipients, long date, long count, boolean read, long threadId) {
|
||||
this.id = id;
|
||||
this.threadId = threadId;
|
||||
this.recipients = recipients;
|
||||
this.date = date;
|
||||
this.count = count;
|
||||
this.read = read;
|
||||
}
|
||||
|
||||
public void setOnConversationItem(ConversationItem item) {
|
||||
item.setMessageRecord(this);
|
||||
}
|
||||
|
||||
public boolean isMms() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public long getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setMessageRecipient(Recipient recipient) {
|
||||
this.messageRecipient = recipient;
|
||||
}
|
||||
|
||||
public Recipient getMessageRecipient() {
|
||||
return this.messageRecipient;
|
||||
}
|
||||
|
||||
public void setEmphasis(boolean emphasis) {
|
||||
this.emphasis = emphasis;
|
||||
}
|
||||
|
||||
public boolean getEmphasis() {
|
||||
return this.emphasis;
|
||||
}
|
||||
|
||||
public void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public void setBody(String body) {
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
public long getThreadId() {
|
||||
return threadId;
|
||||
}
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public Recipients getRecipients() {
|
||||
return recipients;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public long getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public long getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public boolean getRead() {
|
||||
return read;
|
||||
}
|
||||
|
||||
public boolean isStaleKeyExchange() {
|
||||
return this.staleKeyExchange;
|
||||
}
|
||||
|
||||
public void setStaleKeyExchange(boolean staleKeyExchange) {
|
||||
this.staleKeyExchange = staleKeyExchange;
|
||||
}
|
||||
|
||||
public boolean isProcessedKeyExchange() {
|
||||
return processedKeyExchange;
|
||||
}
|
||||
|
||||
public void setProcessedKeyExchange(boolean processedKeyExchange) {
|
||||
this.processedKeyExchange = processedKeyExchange;
|
||||
}
|
||||
|
||||
public boolean isKeyExchange() {
|
||||
return keyExchange || processedKeyExchange || staleKeyExchange;
|
||||
}
|
||||
|
||||
public void setKeyExchange(boolean keyExchange) {
|
||||
this.keyExchange = keyExchange;
|
||||
}
|
||||
|
||||
public boolean isFailedDecryptType() {
|
||||
return type == SmsDatabase.Types.FAILED_DECRYPT_TYPE;
|
||||
}
|
||||
|
||||
public boolean isFailed() {
|
||||
return SmsDatabase.Types.isFailedMessageType(type);
|
||||
}
|
||||
|
||||
public boolean isOutgoing() {
|
||||
return SmsDatabase.Types.isOutgoingMessageType(type);
|
||||
}
|
||||
|
||||
public boolean isPending() {
|
||||
return SmsDatabase.Types.isPendingMessageType(type);
|
||||
}
|
||||
|
||||
public boolean isSecure() {
|
||||
return SmsDatabase.Types.isSecureType(type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -49,7 +49,7 @@ public class MmsDatabase extends Database {
|
||||
public static final String TABLE_NAME = "mms";
|
||||
public static final String ID = "_id";
|
||||
private static final String THREAD_ID = "thread_id";
|
||||
private static final String DATE = "date";
|
||||
public static final String DATE = "date";
|
||||
public static final String MESSAGE_BOX = "msg_box";
|
||||
private static final String READ = "read";
|
||||
private static final String MESSAGE_ID = "m_id";
|
||||
|
@ -7,17 +7,24 @@ import android.support.v4.content.CursorLoader;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
|
||||
public class ConversationLoader extends CursorLoader {
|
||||
|
||||
private final Context context;
|
||||
private final long threadId;
|
||||
// private final boolean isGroupConversation;
|
||||
|
||||
public ConversationLoader(Context context, long threadId) {
|
||||
public ConversationLoader(Context context, long threadId, boolean isGroupConversation) {
|
||||
super(context);
|
||||
this.context = context.getApplicationContext();
|
||||
this.threadId = threadId;
|
||||
this.context = context.getApplicationContext();
|
||||
this.threadId = threadId;
|
||||
// this.isGroupConversation = isGroupConversation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Cursor loadInBackground() {
|
||||
return DatabaseFactory.getMmsSmsDatabase(context).getConversation(threadId);
|
||||
// if (!isGroupConversation) {
|
||||
return DatabaseFactory.getMmsSmsDatabase(context).getConversation(threadId);
|
||||
// } else {
|
||||
// return DatabaseFactory.getMmsSmsDatabase(context).getCollatedGroupConversation(threadId);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,96 @@
|
||||
/**
|
||||
* Copyright (C) 2012 Moxie Marlinspike
|
||||
*
|
||||
* 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.model;
|
||||
|
||||
import org.thoughtcrime.securesms.protocol.Prefix;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
/**
|
||||
* The base class for all message record models. Encapsulates basic data
|
||||
* shared between ThreadRecord and MessageRecord.
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*
|
||||
*/
|
||||
|
||||
public abstract class DisplayRecord {
|
||||
|
||||
private final Recipients recipients;
|
||||
private final long date;
|
||||
private final long threadId;
|
||||
|
||||
private String body;
|
||||
protected boolean emphasis;
|
||||
protected boolean keyExchange;
|
||||
protected boolean processedKeyExchange;
|
||||
protected boolean staleKeyExchange;
|
||||
|
||||
public DisplayRecord(Recipients recipients, long date, long threadId) {
|
||||
this.threadId = threadId;
|
||||
this.recipients = recipients;
|
||||
this.date = date;
|
||||
this.emphasis = false;
|
||||
}
|
||||
|
||||
public void setEmphasis(boolean emphasis) {
|
||||
this.emphasis = emphasis;
|
||||
}
|
||||
|
||||
public boolean getEmphasis() {
|
||||
return emphasis;
|
||||
}
|
||||
|
||||
public void setBody(String body) {
|
||||
if (body.startsWith(Prefix.KEY_EXCHANGE)) {
|
||||
this.keyExchange = true;
|
||||
this.emphasis = true;
|
||||
this.body = body;
|
||||
} else if (body.startsWith(Prefix.PROCESSED_KEY_EXCHANGE)) {
|
||||
this.processedKeyExchange = true;
|
||||
this.emphasis = true;
|
||||
this.body = body;
|
||||
} else if (body.startsWith(Prefix.STALE_KEY_EXCHANGE)) {
|
||||
this.staleKeyExchange = true;
|
||||
this.emphasis = true;
|
||||
this.body = body;
|
||||
} else {
|
||||
this.body = body;
|
||||
this.emphasis = false;
|
||||
}
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public Recipients getRecipients() {
|
||||
return recipients;
|
||||
}
|
||||
|
||||
public long getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public long getThreadId() {
|
||||
return threadId;
|
||||
}
|
||||
|
||||
public boolean isKeyExchange() {
|
||||
return keyExchange || processedKeyExchange || staleKeyExchange;
|
||||
}
|
||||
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright (C) 2011 Whisper Systems
|
||||
* Copyright (C) 2012 Moxie Marlinspike
|
||||
*
|
||||
* 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
|
||||
@ -14,56 +14,44 @@
|
||||
* 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;
|
||||
package org.thoughtcrime.securesms.database.model;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.thoughtcrime.securesms.ConversationItem;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
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.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
public class MmsMessageRecord extends MessageRecord {
|
||||
/**
|
||||
* Represents the message record model for MMS messages that contain
|
||||
* media (ie: they've been downloaded).
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*
|
||||
*/
|
||||
|
||||
private SlideDeck slideDeck;
|
||||
private byte[] contentLocation;
|
||||
private long messageSize;
|
||||
private long expiry;
|
||||
private boolean isNotification;
|
||||
private long mailbox;
|
||||
private int status;
|
||||
private byte[] transactionId;
|
||||
public class MediaMmsMessageRecord extends MessageRecord {
|
||||
|
||||
public MmsMessageRecord(Context context, MessageRecord record, SlideDeck slideDeck, long mailbox) {
|
||||
super(record);
|
||||
this.slideDeck = slideDeck;
|
||||
this.isNotification = false;
|
||||
this.mailbox = mailbox;
|
||||
private final SlideDeck slideDeck;
|
||||
private final long mailbox;
|
||||
|
||||
public MediaMmsMessageRecord(Context context, long id, Recipients recipients,
|
||||
Recipient individualRecipient, long date, long threadId,
|
||||
SlideDeck slideDeck, long mailbox)
|
||||
{
|
||||
super(id, recipients, individualRecipient, date, threadId);
|
||||
this.slideDeck = slideDeck;
|
||||
this.mailbox = mailbox;
|
||||
|
||||
setBodyIfTextAvailable(context);
|
||||
}
|
||||
|
||||
public MmsMessageRecord(MessageRecord record, byte[] contentLocation, long messageSize, long expiry, int status, byte[] transactionId) {
|
||||
super(record);
|
||||
this.contentLocation = contentLocation;
|
||||
this.messageSize = messageSize;
|
||||
this.expiry = expiry;
|
||||
this.isNotification = true;
|
||||
this.status = status;
|
||||
this.transactionId = transactionId;
|
||||
}
|
||||
|
||||
public byte[] getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOutgoing() {
|
||||
return MmsDatabase.Types.isOutgoingMmsBox(mailbox);
|
||||
@ -84,43 +72,13 @@ public class MmsMessageRecord extends MessageRecord {
|
||||
return MmsDatabase.Types.isSecureMmsBox(mailbox);
|
||||
}
|
||||
|
||||
// This is the double-dispatch pattern, don't refactor
|
||||
// this into the base class.
|
||||
@Override
|
||||
public void setOnConversationItem(ConversationItem item) {
|
||||
item.setMessageRecord(this);
|
||||
}
|
||||
|
||||
public byte[] getContentLocation() {
|
||||
return contentLocation;
|
||||
}
|
||||
|
||||
public long getMessageSize() {
|
||||
return (messageSize + 1023) / 1024;
|
||||
}
|
||||
|
||||
public long getExpiration() {
|
||||
return expiry * 1000;
|
||||
}
|
||||
|
||||
public boolean isNotification() {
|
||||
return isNotification;
|
||||
}
|
||||
|
||||
public SlideDeck getSlideDeck() {
|
||||
return slideDeck;
|
||||
}
|
||||
|
||||
private void setBodyFromSlidesIfTextAvailable() {
|
||||
List<Slide> slides = slideDeck.getSlides();
|
||||
Iterator<Slide> i = slides.iterator();
|
||||
|
||||
while (i.hasNext()) {
|
||||
Slide slide = i.next();
|
||||
|
||||
if (slide.hasText())
|
||||
setBody(slide.getText());
|
||||
}
|
||||
@Override
|
||||
public boolean isMms() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private void setBodyIfTextAvailable(Context context) {
|
||||
@ -135,7 +93,7 @@ public class MmsMessageRecord extends MessageRecord {
|
||||
return;
|
||||
case MmsDatabase.Types.MESSAGE_BOX_NO_SESSION_INBOX:
|
||||
setBody(context
|
||||
.getString(R.string.MmsMessageRecord_mms_message_encrypted_for_non_existing_session));
|
||||
.getString(R.string.MmsMessageRecord_mms_message_encrypted_for_non_existing_session));
|
||||
setEmphasis(true);
|
||||
return;
|
||||
}
|
||||
@ -143,9 +101,16 @@ public class MmsMessageRecord extends MessageRecord {
|
||||
setBodyFromSlidesIfTextAvailable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMms() {
|
||||
return true;
|
||||
private void setBodyFromSlidesIfTextAvailable() {
|
||||
List<Slide> slides = slideDeck.getSlides();
|
||||
Iterator<Slide> i = slides.iterator();
|
||||
|
||||
while (i.hasNext()) {
|
||||
Slide slide = i.next();
|
||||
|
||||
if (slide.hasText())
|
||||
setBody(slide.getText());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Copyright (C) 2012 Moxie Marlinpsike
|
||||
*
|
||||
* 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.model;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
/**
|
||||
* The base class for message record models that are displayed in
|
||||
* conversations, as opposed to models that are displayed in a thread list.
|
||||
* Encapsulates the shared data between both SMS and MMS messages.
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*
|
||||
*/
|
||||
public abstract class MessageRecord extends DisplayRecord {
|
||||
|
||||
private final Recipient individualRecipient;
|
||||
private final long id;
|
||||
|
||||
public MessageRecord(long id, Recipients recipients,
|
||||
Recipient individualRecipient,
|
||||
long date, long threadId)
|
||||
{
|
||||
super(recipients, date, threadId);
|
||||
this.id = id;
|
||||
this.individualRecipient = individualRecipient;
|
||||
}
|
||||
|
||||
public abstract boolean isOutgoing();
|
||||
|
||||
public abstract boolean isFailed();
|
||||
|
||||
public abstract boolean isSecure();
|
||||
|
||||
public abstract boolean isPending();
|
||||
|
||||
public abstract boolean isMms();
|
||||
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public boolean isStaleKeyExchange() {
|
||||
return this.staleKeyExchange;
|
||||
}
|
||||
|
||||
public boolean isProcessedKeyExchange() {
|
||||
return this.processedKeyExchange;
|
||||
}
|
||||
|
||||
public Recipient getIndividualRecipient() {
|
||||
return individualRecipient;
|
||||
}
|
||||
|
||||
//
|
||||
// public static class GroupData {
|
||||
// public final int groupSize;
|
||||
// public final int groupSentCount;
|
||||
// public final int groupSendFailedCount;
|
||||
//
|
||||
// public GroupData(int groupSize, int groupSentCount, int groupSendFailedCount) {
|
||||
// this.groupSize = groupSize;
|
||||
// this.groupSentCount = groupSentCount;
|
||||
// this.groupSendFailedCount = groupSendFailedCount;
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
/**
|
||||
* Copyright (C) 2012 Moxie Marlinspike
|
||||
*
|
||||
* 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.model;
|
||||
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
/**
|
||||
* Represents the message record model for MMS messages that are
|
||||
* notifications (ie: they're pointers to undownloaded media).
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*
|
||||
*/
|
||||
|
||||
public class NotificationMmsMessageRecord extends MessageRecord {
|
||||
|
||||
private final byte[] contentLocation;
|
||||
private final long messageSize;
|
||||
private final long expiry;
|
||||
private final int status;
|
||||
private final byte[] transactionId;
|
||||
|
||||
public NotificationMmsMessageRecord(long id, Recipients recipients, Recipient individualRecipient,
|
||||
long date, long threadId, byte[] contentLocation,
|
||||
long messageSize, long expiry,
|
||||
int status, byte[] transactionId)
|
||||
{
|
||||
super(id, recipients, individualRecipient, date, threadId);
|
||||
this.contentLocation = contentLocation;
|
||||
this.messageSize = messageSize;
|
||||
this.expiry = expiry;
|
||||
this.status = status;
|
||||
this.transactionId = transactionId;
|
||||
|
||||
setBody("Multimedia Message");
|
||||
setEmphasis(true);
|
||||
}
|
||||
|
||||
public byte[] getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
|
||||
public byte[] getContentLocation() {
|
||||
return contentLocation;
|
||||
}
|
||||
|
||||
public long getMessageSize() {
|
||||
return (messageSize + 1023) / 1024;
|
||||
}
|
||||
|
||||
public long getExpiration() {
|
||||
return expiry * 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOutgoing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFailed() {
|
||||
return MmsDatabase.Types.isHardError(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPending() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMms() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
/**
|
||||
* Copyright (C) 2012 Moxie Marlinspike
|
||||
*
|
||||
* 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.model;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.SmsDatabase;
|
||||
import org.thoughtcrime.securesms.protocol.Prefix;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
/**
|
||||
* The message record model which represents standard SMS messages.
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*
|
||||
*/
|
||||
|
||||
public class SmsMessageRecord extends MessageRecord {
|
||||
|
||||
private final Context context;
|
||||
private final long type;
|
||||
|
||||
public SmsMessageRecord(Context context, long id,
|
||||
Recipients recipients,
|
||||
Recipient individualRecipient,
|
||||
long date, long type, long threadId)
|
||||
{
|
||||
super(id, recipients, individualRecipient, date, threadId);
|
||||
this.context = context.getApplicationContext();
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public long getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBody(String body) {
|
||||
if (this.type == SmsDatabase.Types.FAILED_DECRYPT_TYPE) {
|
||||
super.setBody(context.getString(R.string.MessageDisplayHelper_bad_encrypted_message));
|
||||
setEmphasis(true);
|
||||
} else if (this.type == SmsDatabase.Types.DECRYPT_IN_PROGRESS_TYPE ||
|
||||
(type == 0 && body.startsWith(Prefix.ASYMMETRIC_ENCRYPT)) ||
|
||||
(type == 0 && body.startsWith(Prefix.ASYMMETRIC_LOCAL_ENCRYPT)))
|
||||
{
|
||||
super.setBody(context.getString(R.string.MessageDisplayHelper_decrypting_please_wait));
|
||||
setEmphasis(true);
|
||||
} else if (type == SmsDatabase.Types.NO_SESSION_TYPE) {
|
||||
super.setBody(context.getString(R.string.MessageDisplayHelper_message_encrypted_for_non_existing_session));
|
||||
setEmphasis(true);
|
||||
} else {
|
||||
super.setBody(body);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFailed() {
|
||||
return SmsDatabase.Types.isFailedMessageType(getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOutgoing() {
|
||||
return SmsDatabase.Types.isOutgoingMessageType(getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPending() {
|
||||
return SmsDatabase.Types.isPendingMessageType(getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return SmsDatabase.Types.isSecureType(getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMms() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static class GroupData {
|
||||
public final int groupSize;
|
||||
public final int groupSentCount;
|
||||
public final int groupSendFailedCount;
|
||||
|
||||
public GroupData(int groupSize, int groupSentCount, int groupSendFailedCount) {
|
||||
this.groupSize = groupSize;
|
||||
this.groupSentCount = groupSentCount;
|
||||
this.groupSendFailedCount = groupSendFailedCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Copyright (C) 2012 Moxie Marlinspike
|
||||
*
|
||||
* 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.model;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.protocol.Prefix;
|
||||
import org.thoughtcrime.securesms.recipients.Recipients;
|
||||
|
||||
/**
|
||||
* The message record model which represents thread heading messages.
|
||||
*
|
||||
* @author Moxie Marlinspike
|
||||
*
|
||||
*/
|
||||
public class ThreadRecord extends DisplayRecord {
|
||||
|
||||
private final Context context;
|
||||
private final long count;
|
||||
private final boolean read;
|
||||
|
||||
public ThreadRecord(Context context, Recipients recipients,
|
||||
long date, long count,
|
||||
boolean read, long threadId)
|
||||
{
|
||||
super(recipients, date, threadId);
|
||||
this.context = context.getApplicationContext();
|
||||
this.count = count;
|
||||
this.read = read;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBody(String body) {
|
||||
if (body.startsWith(Prefix.SYMMETRIC_ENCRYPT) ||
|
||||
body.startsWith(Prefix.ASYMMETRIC_ENCRYPT) ||
|
||||
body.startsWith(Prefix.ASYMMETRIC_LOCAL_ENCRYPT))
|
||||
{
|
||||
super.setBody(context.getString(R.string.ConversationListAdapter_encrypted_message_enter_passphrase));
|
||||
setEmphasis(true);
|
||||
} else if (body.startsWith(Prefix.KEY_EXCHANGE)) {
|
||||
super.setBody(context.getString(R.string.ConversationListAdapter_key_exchange_message));
|
||||
setEmphasis(true);
|
||||
} else {
|
||||
super.setBody(body);
|
||||
}
|
||||
}
|
||||
|
||||
public long getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public boolean isRead() {
|
||||
return read;
|
||||
}
|
||||
|
||||
}
|
@ -1,79 +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.mms;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||
import org.thoughtcrime.securesms.database.MmsMessageRecord;
|
||||
|
||||
import ws.com.google.android.mms.MmsException;
|
||||
import ws.com.google.android.mms.pdu.MultimediaMessagePdu;
|
||||
import ws.com.google.android.mms.pdu.NotificationInd;
|
||||
import ws.com.google.android.mms.pdu.PduHeaders;
|
||||
|
||||
public class MmsFactory {
|
||||
|
||||
public static MmsMessageRecord getMms(Context context, MasterSecret masterSecret, MessageRecord record, long mmsType, long box) throws MmsException {
|
||||
Log.w("MmsFactory", "MMS Type: " + mmsType);
|
||||
if (mmsType == PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND) {
|
||||
return getNotificationMmsRecord(context, record);
|
||||
} else {
|
||||
return getMediaMmsRecord(context, masterSecret, record, box);
|
||||
}
|
||||
}
|
||||
|
||||
private static MmsMessageRecord getNotificationMmsRecord(Context context, MessageRecord record) throws MmsException {
|
||||
MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
NotificationInd notification = database.getNotificationMessage(record.getId());
|
||||
return new MmsMessageRecord(record, notification.getContentLocation(), notification.getMessageSize(),
|
||||
notification.getExpiry(), notification.getStatus(), notification.getTransactionId());
|
||||
}
|
||||
|
||||
private static MmsMessageRecord getMediaMmsRecord(Context context, MasterSecret masterSecret, MessageRecord record, long box) throws MmsException {
|
||||
MmsDatabase database = DatabaseFactory.getEncryptingMmsDatabase(context, masterSecret);
|
||||
MultimediaMessagePdu msg = database.getMediaMessage(record.getId());
|
||||
SlideDeck slideDeck = new SlideDeck(context, masterSecret, msg.getBody());
|
||||
|
||||
return new MmsMessageRecord(context, record, slideDeck, box);
|
||||
}
|
||||
|
||||
// private static void setBodyIfText(SlideModel slide, MessageRecord record) {
|
||||
// if ((slide != null) && slide.hasText()) {
|
||||
// TextModel tm = slide.getText();
|
||||
//
|
||||
// if (tm.isDrmProtected()) {
|
||||
// record.setBody("DRM protected");
|
||||
// } else {
|
||||
// record.setBody(tm.getText());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// private static SlideshowModel getSlideshowModel(Context context, long messageId) throws MmsException {
|
||||
// LayoutManager.init(context);
|
||||
// MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
|
||||
// MultimediaMessagePdu msg = database.getMediaMessage(messageId);
|
||||
// return SlideshowModel.createFromPduBody(context, msg.getBody());
|
||||
// }
|
||||
|
||||
|
||||
}
|
@ -19,7 +19,7 @@ public class Tag {
|
||||
}
|
||||
|
||||
public static boolean isTagged(String message) {
|
||||
return message.matches(".*[^\\s]" + WHITESPACE_TAG + "$");
|
||||
return message != null && message.matches(".*[^\\s]" + WHITESPACE_TAG + "$");
|
||||
}
|
||||
|
||||
public static String getTaggedMessage(String message) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user