diff --git a/res/drawable-hdpi/ic_note_to_self.png b/res/drawable-hdpi/ic_note_to_self.png
new file mode 100644
index 0000000000..1cca57650f
Binary files /dev/null and b/res/drawable-hdpi/ic_note_to_self.png differ
diff --git a/res/drawable-mdpi/ic_note_to_self.png b/res/drawable-mdpi/ic_note_to_self.png
new file mode 100644
index 0000000000..6ed37fdb10
Binary files /dev/null and b/res/drawable-mdpi/ic_note_to_self.png differ
diff --git a/res/drawable-xhdpi/ic_note_to_self.png b/res/drawable-xhdpi/ic_note_to_self.png
new file mode 100644
index 0000000000..cd1520cf74
Binary files /dev/null and b/res/drawable-xhdpi/ic_note_to_self.png differ
diff --git a/res/drawable-xxhdpi/ic_note_to_self.png b/res/drawable-xxhdpi/ic_note_to_self.png
new file mode 100644
index 0000000000..59bf9e76aa
Binary files /dev/null and b/res/drawable-xxhdpi/ic_note_to_self.png differ
diff --git a/res/drawable-xxxhdpi/ic_note_to_self.png b/res/drawable-xxxhdpi/ic_note_to_self.png
new file mode 100644
index 0000000000..149489384f
Binary files /dev/null and b/res/drawable-xxxhdpi/ic_note_to_self.png differ
diff --git a/res/layout/conversation_title_view.xml b/res/layout/conversation_title_view.xml
index affbee4a19..69efe6dfab 100644
--- a/res/layout/conversation_title_view.xml
+++ b/res/layout/conversation_title_view.xml
@@ -20,6 +20,7 @@
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
+ android:background="?selectableItemBackgroundBorderless"
android:visibility="visible"/>
-
+
+
+
+
+
+ android:layout_marginRight="3dp"
+ android:layout_marginEnd="3dp"
+ android:layout_gravity="bottom"
+ android:alpha="0.7"
+ android:visibility="gone"/>
-
-
-
-
+
+
+
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 31b3b9e7bd..d954992de7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -6,6 +6,7 @@
Delete
Please wait...
Save
+ Note to Self
New message
diff --git a/src/org/thoughtcrime/securesms/ConversationListItem.java b/src/org/thoughtcrime/securesms/ConversationListItem.java
index 0e26856e67..7add0076ce 100644
--- a/src/org/thoughtcrime/securesms/ConversationListItem.java
+++ b/src/org/thoughtcrime/securesms/ConversationListItem.java
@@ -24,18 +24,12 @@ import android.os.Build.VERSION;
import android.os.Build.VERSION_CODES;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.text.Spannable;
-import android.text.SpannableString;
-import android.text.Spanned;
-import android.text.TextUtils;
import android.text.style.StyleSpan;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.TextView;
-import com.annimon.stream.Stream;
-
import org.thoughtcrime.securesms.components.AlertView;
import org.thoughtcrime.securesms.components.AvatarImageView;
import org.thoughtcrime.securesms.components.DeliveryStatusView;
@@ -49,13 +43,11 @@ import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.search.model.MessageResult;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.util.SearchUtil;
-import org.thoughtcrime.securesms.util.SearchUtil.StyleFactory;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.Collections;
-import java.util.List;
import java.util.Locale;
import java.util.Set;
@@ -147,7 +139,9 @@ public class ConversationListItem extends RelativeLayout
this.recipient.addListener(this);
if (highlightSubstring != null) {
- this.fromView.setText(SearchUtil.getHighlightedSpan(locale, () -> new StyleSpan(Typeface.BOLD), recipient.getName(), highlightSubstring));
+ String name = recipient.isLocalNumber() ? getContext().getString(R.string.note_to_self) : recipient.getName();
+
+ this.fromView.setText(SearchUtil.getHighlightedSpan(locale, () -> new StyleSpan(Typeface.BOLD), name, highlightSubstring));
} else {
this.fromView.setText(recipient, unreadCount == 0);
}
@@ -201,7 +195,9 @@ public class ConversationListItem extends RelativeLayout
this.recipient.addListener(this);
- fromView.setText(SearchUtil.getHighlightedSpan(locale, () -> new StyleSpan(Typeface.BOLD), recipient.getName(), highlightSubstring));
+ String name = recipient.isLocalNumber() ? getContext().getString(R.string.note_to_self) : recipient.getName();
+
+ fromView.setText(SearchUtil.getHighlightedSpan(locale, () -> new StyleSpan(Typeface.BOLD), name, highlightSubstring));
subjectView.setText(SearchUtil.getHighlightedSpan(locale, () -> new StyleSpan(Typeface.BOLD), contact.getAddress().toPhoneString(), highlightSubstring));
dateView.setText("");
archivedView.setVisibility(GONE);
diff --git a/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java b/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java
index b01616fe7a..be8a53eab8 100644
--- a/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java
+++ b/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java
@@ -29,6 +29,10 @@ import android.support.v7.widget.Toolbar;
import android.telephony.PhoneNumberUtils;
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
+import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto;
+import org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto;
+import org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto;
+import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
import org.thoughtcrime.securesms.database.GroupDatabase;
import org.thoughtcrime.securesms.jobs.RotateProfileKeyJob;
import org.thoughtcrime.securesms.logging.Log;
@@ -202,14 +206,19 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
}
private void setHeader(@NonNull Recipient recipient) {
- glideRequests.load(recipient.getContactPhoto())
- .fallback(recipient.getFallbackContactPhoto().asCallCard(this))
- .error(recipient.getFallbackContactPhoto().asCallCard(this))
+ ContactPhoto contactPhoto = recipient.isLocalNumber() ? new ProfileContactPhoto(recipient.getAddress(), String.valueOf(TextSecurePreferences.getProfileAvatarId(this)))
+ : recipient.getContactPhoto();
+ FallbackContactPhoto fallbackPhoto = recipient.isLocalNumber() ? new ResourceContactPhoto(R.drawable.ic_profile_default, R.drawable.ic_person_large)
+ : recipient.getFallbackContactPhoto();
+
+ glideRequests.load(contactPhoto)
+ .fallback(fallbackPhoto.asCallCard(this))
+ .error(fallbackPhoto.asCallCard(this))
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(this.avatar);
- if (recipient.getContactPhoto() == null) this.avatar.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
- else this.avatar.setScaleType(ImageView.ScaleType.CENTER_CROP);
+ if (contactPhoto == null) this.avatar.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+ else this.avatar.setScaleType(ImageView.ScaleType.CENTER_CROP);
this.avatar.setBackgroundColor(recipient.getColor().toActionBarColor(this));
this.toolbarLayout.setTitle(recipient.toShortString());
@@ -356,6 +365,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
private void setSummaries(Recipient recipient) {
CheckBoxPreference mutePreference = (CheckBoxPreference) this.findPreference(PREFERENCE_MUTED);
+ Preference customPreference = this.findPreference(PREFERENCE_CUSTOM_NOTIFICATIONS);
Preference ringtoneMessagePreference = this.findPreference(PREFERENCE_MESSAGE_TONE);
Preference ringtoneCallPreference = this.findPreference(PREFERENCE_CALL_TONE);
ListPreference vibrateMessagePreference = (ListPreference) this.findPreference(PREFERENCE_MESSAGE_VIBRATE);
@@ -384,7 +394,19 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
vibrateCallPreference.setSummary(vibrateCallSummary.first);
vibrateCallPreference.setValueIndex(vibrateCallSummary.second);
- if (recipient.isGroupRecipient()) {
+ if (recipient.isLocalNumber()) {
+ mutePreference.setVisible(false);
+ customPreference.setVisible(false);
+ ringtoneMessagePreference.setVisible(false);
+ vibrateMessagePreference.setVisible(false);
+
+ if (identityPreference != null) identityPreference.setVisible(false);
+ if (aboutCategory != null) aboutCategory.setVisible(false);
+ if (aboutDivider != null) aboutDivider.setVisible(false);
+ if (privacyCategory != null) privacyCategory.setVisible(false);
+ if (divider != null) divider.setVisible(false);
+ if (callCategory != null) callCategory.setVisible(false);
+ } if (recipient.isGroupRecipient()) {
if (colorPreference != null) colorPreference.setVisible(false);
if (identityPreference != null) identityPreference.setVisible(false);
if (callCategory != null) callCategory.setVisible(false);
diff --git a/src/org/thoughtcrime/securesms/components/FromTextView.java b/src/org/thoughtcrime/securesms/components/FromTextView.java
index 30c1af3dca..0344fbb8aa 100644
--- a/src/org/thoughtcrime/securesms/components/FromTextView.java
+++ b/src/org/thoughtcrime/securesms/components/FromTextView.java
@@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.ResUtil;
+import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.spans.CenterAlignedRelativeSizeSpan;
public class FromTextView extends EmojiTextView {
@@ -52,7 +53,10 @@ public class FromTextView extends EmojiTextView {
fromSpan.setSpan(new StyleSpan(typeface), 0, builder.length(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
- if (recipient.getName() == null && !TextUtils.isEmpty(recipient.getProfileName())) {
+
+ if (recipient.isLocalNumber()) {
+ builder.append(getContext().getString(R.string.note_to_self));
+ } else if (recipient.getName() == null && !TextUtils.isEmpty(recipient.getProfileName())) {
SpannableString profileName = new SpannableString(" (~" + recipient.getProfileName() + ") ");
profileName.setSpan(new CenterAlignedRelativeSizeSpan(0.75f), 0, profileName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
profileName.setSpan(new TypefaceSpan("sans-serif-light"), 0, profileName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
diff --git a/src/org/thoughtcrime/securesms/contacts/ContactAccessor.java b/src/org/thoughtcrime/securesms/contacts/ContactAccessor.java
index 1551cd3e0f..2910a971e9 100644
--- a/src/org/thoughtcrime/securesms/contacts/ContactAccessor.java
+++ b/src/org/thoughtcrime/securesms/contacts/ContactAccessor.java
@@ -29,9 +29,11 @@ import android.provider.ContactsContract.PhoneLookup;
import android.telephony.PhoneNumberUtils;
import android.text.TextUtils;
+import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.GroupDatabase;
+import org.thoughtcrime.securesms.util.TextSecurePreferences;
import java.util.ArrayList;
import java.util.Collection;
@@ -204,6 +206,12 @@ public class ContactAccessor {
reader.close();
}
+ if (context.getString(R.string.note_to_self).toLowerCase().contains(constraint.toLowerCase()) &&
+ !numberList.contains(TextSecurePreferences.getLocalNumber(context)))
+ {
+ numberList.add(TextSecurePreferences.getLocalNumber(context));
+ }
+
return numberList;
}
diff --git a/src/org/thoughtcrime/securesms/contacts/ContactSelectionListAdapter.java b/src/org/thoughtcrime/securesms/contacts/ContactSelectionListAdapter.java
index b8d0803b7c..3901182356 100644
--- a/src/org/thoughtcrime/securesms/contacts/ContactSelectionListAdapter.java
+++ b/src/org/thoughtcrime/securesms/contacts/ContactSelectionListAdapter.java
@@ -40,6 +40,7 @@ import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration.StickyHeaderAdapter;
+import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import java.util.HashMap;
diff --git a/src/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java b/src/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java
index e6773f9311..d1574fe603 100644
--- a/src/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java
+++ b/src/org/thoughtcrime/securesms/contacts/ContactSelectionListItem.java
@@ -75,6 +75,10 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientM
this.numberView.setTextColor(color);
this.contactPhotoImage.setAvatar(glideRequests, recipient, false);
+ if (!multiSelect && recipient != null && recipient.isLocalNumber()) {
+ name = getContext().getString(R.string.note_to_self);
+ }
+
setText(type, name, number, label);
if (multiSelect) this.checkBox.setVisibility(View.VISIBLE);
diff --git a/src/org/thoughtcrime/securesms/contacts/ContactsDatabase.java b/src/org/thoughtcrime/securesms/contacts/ContactsDatabase.java
index 91a8f8e921..adab0bca51 100644
--- a/src/org/thoughtcrime/securesms/contacts/ContactsDatabase.java
+++ b/src/org/thoughtcrime/securesms/contacts/ContactsDatabase.java
@@ -24,6 +24,8 @@ import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.database.CursorWrapper;
+import android.database.MatrixCursor;
+import android.database.MergeCursor;
import android.net.Uri;
import android.os.Build;
import android.os.RemoteException;
@@ -38,6 +40,7 @@ import android.util.Pair;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.logging.Log;
+import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
@@ -222,6 +225,25 @@ public class ContactsDatabase {
new String[] {CONTACT_MIMETYPE,
"%" + filter + "%", "%" + filter + "%"},
sort);
+
+ if (context.getString(R.string.note_to_self).toLowerCase().contains(filter.toLowerCase())) {
+ Optional self = getSystemContactInfo(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)));
+ boolean shouldAdd = true;
+
+ if (self.isPresent()) {
+ boolean nameMatch = self.get().name != null && self.get().name.toLowerCase().contains(filter.toLowerCase());
+ boolean numberMatch = self.get().number != null && self.get().number.contains(filter);
+
+ shouldAdd = !nameMatch && !numberMatch;
+ }
+
+ if (shouldAdd) {
+ MatrixCursor selfCursor = new MatrixCursor(projection);
+ selfCursor.addRow(new Object[]{ context.getString(R.string.note_to_self), TextSecurePreferences.getLocalNumber(context)});
+
+ cursor = cursor == null ? selfCursor : new MergeCursor(new Cursor[]{ cursor, selfCursor });
+ }
+ }
}
return new ProjectionMappingCursor(cursor, projectionMap,
diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java
index 95de9b70d2..6dcdbeabaa 100644
--- a/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java
+++ b/src/org/thoughtcrime/securesms/conversation/ConversationActivity.java
@@ -652,6 +652,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
inflater.inflate(R.menu.conversation_add_to_contacts, menu);
}
+ if (recipient != null && recipient.isLocalNumber()) {
+ if (isSecureText) menu.findItem(R.id.menu_call_secure).setVisible(false);
+ else menu.findItem(R.id.menu_call_insecure).setVisible(false);
+
+ menu.findItem(R.id.menu_mute_notifications).setVisible(false);
+ }
+
searchViewItem = menu.findItem(R.id.menu_search);
SearchView searchView = (SearchView) searchViewItem.getActionView();
diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationItem.java b/src/org/thoughtcrime/securesms/conversation/ConversationItem.java
index 5b80465d20..2108e67bf6 100644
--- a/src/org/thoughtcrime/securesms/conversation/ConversationItem.java
+++ b/src/org/thoughtcrime/securesms/conversation/ConversationItem.java
@@ -429,7 +429,7 @@ public class ConversationItem extends LinearLayout
@NonNull Recipient conversationRecipient,
boolean isGroupThread)
{
- boolean showControls = !messageRecord.isFailed() && !Util.isOwnNumber(context, conversationRecipient.getAddress());
+ boolean showControls = !messageRecord.isFailed();
if (hasSharedContact(messageRecord)) {
sharedContactStub.get().setVisibility(VISIBLE);
diff --git a/src/org/thoughtcrime/securesms/conversation/ConversationTitleView.java b/src/org/thoughtcrime/securesms/conversation/ConversationTitleView.java
index f2cc33cebf..4e88960e5f 100644
--- a/src/org/thoughtcrime/securesms/conversation/ConversationTitleView.java
+++ b/src/org/thoughtcrime/securesms/conversation/ConversationTitleView.java
@@ -32,6 +32,7 @@ public class ConversationTitleView extends RelativeLayout {
private TextView title;
private TextView subtitle;
private ImageView verified;
+ private View subtitleContainer;
public ConversationTitleView(Context context) {
this(context, null);
@@ -46,12 +47,13 @@ public class ConversationTitleView extends RelativeLayout {
public void onFinishInflate() {
super.onFinishInflate();
- this.back = ViewUtil.findById(this, R.id.up_button);
- this.content = ViewUtil.findById(this, R.id.content);
- this.title = ViewUtil.findById(this, R.id.title);
- this.subtitle = ViewUtil.findById(this, R.id.subtitle);
- this.verified = ViewUtil.findById(this, R.id.verified_indicator);
- this.avatar = ViewUtil.findById(this, R.id.contact_photo_image);
+ this.back = ViewUtil.findById(this, R.id.up_button);
+ this.content = ViewUtil.findById(this, R.id.content);
+ this.title = ViewUtil.findById(this, R.id.title);
+ this.subtitle = ViewUtil.findById(this, R.id.subtitle);
+ this.verified = ViewUtil.findById(this, R.id.verified_indicator);
+ this.subtitleContainer = ViewUtil.findById(this, R.id.subtitle_container);
+ this.avatar = ViewUtil.findById(this, R.id.contact_photo_image);
ViewUtil.setTextViewGravityStart(this.title, getContext());
ViewUtil.setTextViewGravityStart(this.subtitle, getContext());
@@ -102,6 +104,7 @@ public class ConversationTitleView extends RelativeLayout {
private void setRecipientTitle(Recipient recipient) {
if (recipient.isGroupRecipient()) setGroupRecipientTitle(recipient);
+ else if (recipient.isLocalNumber()) setSelfTitle();
else if (TextUtils.isEmpty(recipient.getName())) setNonContactRecipientTitle(recipient);
else setContactRecipientTitle(recipient);
}
@@ -116,11 +119,18 @@ public class ConversationTitleView extends RelativeLayout {
.collect(Collectors.joining(", ")));
this.subtitle.setVisibility(View.VISIBLE);
+ this.subtitleContainer.setVisibility(VISIBLE);
+ }
+
+ private void setSelfTitle() {
+ this.title.setText(R.string.note_to_self);
+ this.subtitleContainer.setVisibility(View.GONE);
}
@SuppressLint("SetTextI18n")
private void setNonContactRecipientTitle(Recipient recipient) {
this.title.setText(recipient.getAddress().serialize());
+ this.subtitleContainer.setVisibility(VISIBLE);
if (TextUtils.isEmpty(recipient.getProfileName())) {
this.subtitle.setText(null);
@@ -138,5 +148,6 @@ public class ConversationTitleView extends RelativeLayout {
else this.subtitle.setText(recipient.getAddress().serialize());
this.subtitle.setVisibility(View.VISIBLE);
+ this.subtitleContainer.setVisibility(VISIBLE);
}
}
diff --git a/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java
index 13e31fffc2..343bdafe8f 100644
--- a/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java
+++ b/src/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java
@@ -61,8 +61,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
private static final int ATTACHMENT_CAPTIONS_FIX = 15;
private static final int PREVIEWS = 16;
private static final int CONVERSATION_SEARCH = 17;
+ private static final int SELF_ATTACHMENT_CLEANUP = 18;
- private static final int DATABASE_VERSION = 17;
+ private static final int DATABASE_VERSION = 18;
private static final String DATABASE_NAME = "signal.db";
private final Context context;
@@ -383,6 +384,22 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
Log.i(TAG, "Indexing finished. Total time: " + (mmsFinished - start) + " ms");
}
+ if (oldVersion < SELF_ATTACHMENT_CLEANUP) {
+ String localNumber = TextSecurePreferences.getLocalNumber(context);
+
+ try (Cursor threadCursor = db.rawQuery("SELECT _id FROM thread WHERE recipient_ids = ?", new String[]{ localNumber })) {
+ if (threadCursor != null && threadCursor.moveToFirst()) {
+ long threadId = threadCursor.getLong(0);
+ ContentValues updateValues = new ContentValues(1);
+
+ updateValues.put("pending_push", 0);
+
+ int count = db.update("part", updateValues, "mid IN (SELECT _id FROM mms WHERE thread_id = ?)", new String[]{ String.valueOf(threadId) });
+ Log.i(TAG, "Updated " + count + " self-sent attachments.");
+ }
+ }
+ }
+
db.setTransactionSuccessful();
} finally {
db.endTransaction();
diff --git a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
index 42899049ab..7deb4f43ea 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushDecryptJob.java
@@ -733,6 +733,12 @@ public class PushDecryptJob extends ContextJob {
message.getMessage().getExpiresInSeconds() * 1000L);
}
+ if (recipients.isLocalNumber()) {
+ SyncMessageId id = new SyncMessageId(recipients.getAddress(), message.getTimestamp());
+ DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCount(id, System.currentTimeMillis());
+ DatabaseFactory.getMmsSmsDatabase(context).incrementReadReceiptCount(id, System.currentTimeMillis());
+ }
+
return threadId;
}
@@ -825,6 +831,12 @@ public class PushDecryptJob extends ContextJob {
.scheduleDeletion(messageId, isGroup, message.getExpirationStartTimestamp(), expiresInMillis);
}
+ if (recipient.isLocalNumber()) {
+ SyncMessageId id = new SyncMessageId(recipient.getAddress(), message.getTimestamp());
+ DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCount(id, System.currentTimeMillis());
+ DatabaseFactory.getMmsSmsDatabase(context).incrementReadReceiptCount(id, System.currentTimeMillis());
+ }
+
return threadId;
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java
index d01e9b9b24..fcbead5371 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java
@@ -11,8 +11,8 @@ import org.thoughtcrime.securesms.attachments.Attachment;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
import org.thoughtcrime.securesms.database.Address;
-import org.thoughtcrime.securesms.database.AttachmentDatabase;
import org.thoughtcrime.securesms.database.DatabaseFactory;
+import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.MmsDatabase;
import org.thoughtcrime.securesms.database.NoSuchMessageException;
import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode;
@@ -20,7 +20,6 @@ import org.thoughtcrime.securesms.dependencies.InjectableType;
import org.thoughtcrime.securesms.jobmanager.ChainParameters;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobmanager.SafeData;
-import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.MmsException;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
@@ -32,10 +31,12 @@ import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
+import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Preview;
+import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
import org.whispersystems.signalservice.api.messages.shared.SharedContact;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
@@ -131,7 +132,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
try {
log(TAG, "Sending message: " + messageId);
-
+
Recipient recipient = message.getRecipient().resolve();
byte[] profileKey = recipient.getProfileKey();
UnidentifiedAccessMode accessMode = recipient.getUnidentifiedAccessMode();
@@ -142,6 +143,12 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
markAttachmentsUploaded(messageId, message.getAttachments());
database.markUnidentified(messageId, unidentified);
+ if (recipient.isLocalNumber()) {
+ SyncMessageId id = new SyncMessageId(recipient.getAddress(), message.getSentTimeMillis());
+ DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCount(id, System.currentTimeMillis());
+ DatabaseFactory.getMmsSmsDatabase(context).incrementReadReceiptCount(id, System.currentTimeMillis());
+ }
+
if (TextSecurePreferences.isUnidentifiedDeliveryEnabled(context)) {
if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN && profileKey == null) {
log(TAG, "Marking recipient as UD-unrestricted following a UD send.");
@@ -215,7 +222,15 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
.asExpirationUpdate(message.isExpirationUpdate())
.build();
- return messageSender.sendMessage(address, UnidentifiedAccessUtil.getAccessFor(context, message.getRecipient()), mediaMessage).getSuccess().isUnidentified();
+ if (address.getNumber().equals(TextSecurePreferences.getLocalNumber(context))) {
+ Optional syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
+ SignalServiceSyncMessage syncMessage = buildSelfSendSyncMessage(context, mediaMessage, syncAccess);
+
+ messageSender.sendMessage(syncMessage, syncAccess);
+ return syncAccess.isPresent();
+ } else {
+ return messageSender.sendMessage(address, UnidentifiedAccessUtil.getAccessFor(context, message.getRecipient()), mediaMessage).getSuccess().isUnidentified();
+ }
} catch (UnregisteredUserException e) {
warn(TAG, e);
throw new InsecureFallbackApprovalException(e);
diff --git a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
index 8461ebfa92..e53865bd2b 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java
@@ -20,7 +20,6 @@ import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.events.PartProgressEvent;
import org.thoughtcrime.securesms.jobmanager.JobParameters;
-import org.thoughtcrime.securesms.linkpreview.LinkPreview;
import org.thoughtcrime.securesms.logging.Log;
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
@@ -34,16 +33,20 @@ import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
+import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Preview;
+import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage;
+import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
import org.whispersystems.signalservice.api.messages.shared.SharedContact;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -280,5 +283,16 @@ public abstract class PushSendJob extends SendJob {
}
}
+ protected SignalServiceSyncMessage buildSelfSendSyncMessage(@NonNull Context context, @NonNull SignalServiceDataMessage message, Optional syncAccess) {
+ String localNumber = TextSecurePreferences.getLocalNumber(context);
+ SentTranscriptMessage transcript = new SentTranscriptMessage(localNumber,
+ message.getTimestamp(),
+ message,
+ message.getExpiresInSeconds(),
+ Collections.singletonMap(localNumber, syncAccess.isPresent()));
+ return SignalServiceSyncMessage.forSentTranscript(transcript);
+ }
+
+
protected abstract void onPushSend() throws Exception;
}
diff --git a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java
index 7a894f8cfb..38dfda7667 100644
--- a/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java
+++ b/src/org/thoughtcrime/securesms/jobs/PushTextSendJob.java
@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.jobs;
import android.content.Context;
import android.support.annotation.NonNull;
+import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode;
import org.thoughtcrime.securesms.jobmanager.SafeData;
@@ -25,6 +26,7 @@ import org.whispersystems.signalservice.api.SignalServiceMessageSender;
import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair;
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
+import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage;
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
@@ -94,6 +96,12 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
database.markAsSent(messageId, true);
database.markUnidentified(messageId, unidentified);
+ if (recipient.isLocalNumber()) {
+ SyncMessageId id = new SyncMessageId(recipient.getAddress(), record.getDateSent());
+ DatabaseFactory.getMmsSmsDatabase(context).incrementDeliveryReceiptCount(id, System.currentTimeMillis());
+ DatabaseFactory.getMmsSmsDatabase(context).incrementReadReceiptCount(id, System.currentTimeMillis());
+ }
+
if (TextSecurePreferences.isUnidentifiedDeliveryEnabled(context)) {
if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN && profileKey == null) {
log(TAG, "Marking recipient as UD-unrestricted following a UD send.");
@@ -166,7 +174,15 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
.asEndSessionMessage(message.isEndSession())
.build();
- return messageSender.sendMessage(address, unidentifiedAccess, textSecureMessage).getSuccess().isUnidentified();
+ if (address.getNumber().equals(TextSecurePreferences.getLocalNumber(context))) {
+ Optional syncAccess = UnidentifiedAccessUtil.getAccessForSync(context);
+ SignalServiceSyncMessage syncMessage = buildSelfSendSyncMessage(context, textSecureMessage, syncAccess);
+
+ messageSender.sendMessage(syncMessage, syncAccess);
+ return syncAccess.isPresent();
+ } else {
+ return messageSender.sendMessage(address, unidentifiedAccess, textSecureMessage).getSuccess().isUnidentified();
+ }
} catch (UnregisteredUserException e) {
warn(TAG, "Failure", e);
throw new InsecureFallbackApprovalException(e);
diff --git a/src/org/thoughtcrime/securesms/recipients/Recipient.java b/src/org/thoughtcrime/securesms/recipients/Recipient.java
index b963acd013..a26e857693 100644
--- a/src/org/thoughtcrime/securesms/recipients/Recipient.java
+++ b/src/org/thoughtcrime/securesms/recipients/Recipient.java
@@ -73,6 +73,7 @@ public class Recipient implements RecipientModifiedListener {
private @Nullable String name;
private @Nullable String customLabel;
private boolean resolving;
+ private boolean isLocalNumber;
private @Nullable Uri systemContactPhoto;
private @Nullable Long groupAvatarId;
@@ -119,15 +120,16 @@ public class Recipient implements RecipientModifiedListener {
@NonNull Optional details,
@NonNull ListenableFutureTask future)
{
- this.address = address;
- this.color = null;
- this.resolving = true;
+ this.address = address;
+ this.color = null;
+ this.resolving = true;
if (stale != null) {
this.name = stale.name;
this.contactUri = stale.contactUri;
this.systemContactPhoto = stale.systemContactPhoto;
this.groupAvatarId = stale.groupAvatarId;
+ this.isLocalNumber = stale.isLocalNumber;
this.color = stale.color;
this.customLabel = stale.customLabel;
this.messageRingtone = stale.messageRingtone;
@@ -155,6 +157,7 @@ public class Recipient implements RecipientModifiedListener {
this.name = details.get().name;
this.systemContactPhoto = details.get().systemContactPhoto;
this.groupAvatarId = details.get().groupAvatarId;
+ this.isLocalNumber = details.get().isLocalNumber;
this.color = details.get().color;
this.messageRingtone = details.get().messageRingtone;
this.callRingtone = details.get().callRingtone;
@@ -186,6 +189,7 @@ public class Recipient implements RecipientModifiedListener {
Recipient.this.contactUri = result.contactUri;
Recipient.this.systemContactPhoto = result.systemContactPhoto;
Recipient.this.groupAvatarId = result.groupAvatarId;
+ Recipient.this.isLocalNumber = result.isLocalNumber;
Recipient.this.color = result.color;
Recipient.this.customLabel = result.customLabel;
Recipient.this.messageRingtone = result.messageRingtone;
@@ -234,6 +238,7 @@ public class Recipient implements RecipientModifiedListener {
this.name = details.name;
this.systemContactPhoto = details.systemContactPhoto;
this.groupAvatarId = details.groupAvatarId;
+ this.isLocalNumber = details.isLocalNumber;
this.color = details.color;
this.customLabel = details.customLabel;
this.messageRingtone = details.messageRingtone;
@@ -257,6 +262,10 @@ public class Recipient implements RecipientModifiedListener {
this.resolving = false;
}
+ public boolean isLocalNumber() {
+ return isLocalNumber;
+ }
+
public synchronized @Nullable Uri getContactUri() {
return this.contactUri;
}
@@ -434,6 +443,7 @@ public class Recipient implements RecipientModifiedListener {
}
public synchronized @NonNull FallbackContactPhoto getFallbackContactPhoto() {
+ if (isLocalNumber) return new ResourceContactPhoto(R.drawable.ic_note_to_self);
if (isResolving()) return new TransparentContactPhoto();
else if (isGroupRecipient()) return new ResourceContactPhoto(R.drawable.ic_group_white_24dp, R.drawable.ic_group_large);
else if (!TextUtils.isEmpty(name)) return new GeneratedContactPhoto(name, R.drawable.ic_profile_default);
@@ -441,7 +451,8 @@ public class Recipient implements RecipientModifiedListener {
}
public synchronized @Nullable ContactPhoto getContactPhoto() {
- if (isGroupRecipient() && groupAvatarId != null) return new GroupRecordContactPhoto(address, groupAvatarId);
+ if (isLocalNumber) return null;
+ else if (isGroupRecipient() && groupAvatarId != null) return new GroupRecordContactPhoto(address, groupAvatarId);
else if (systemContactPhoto != null) return new SystemContactPhoto(address, systemContactPhoto, 0);
else if (profileAvatar != null) return new ProfileContactPhoto(address, profileAvatar);
else return null;
diff --git a/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java b/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java
index bdccf32a56..47aae97c96 100644
--- a/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java
+++ b/src/org/thoughtcrime/securesms/recipients/RecipientProvider.java
@@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessM
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
import org.thoughtcrime.securesms.util.ListenableFutureTask;
import org.thoughtcrime.securesms.util.SoftHashMap;
+import org.thoughtcrime.securesms.util.TextSecurePreferences;
import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
@@ -52,7 +53,7 @@ class RecipientProvider {
private static final ExecutorService asyncRecipientResolver = Util.newSingleThreadedLifoExecutor();
private static final Map STATIC_DETAILS = new HashMap() {{
- put("262966", new RecipientDetails("Amazon", null, false, null, null));
+ put("262966", new RecipientDetails("Amazon", null, false, false, null, null));
}};
@NonNull Recipient getRecipient(@NonNull Context context, @NonNull Address address, @NonNull Optional settings, @NonNull Optional groupRecord, boolean asynchronous) {
@@ -85,7 +86,8 @@ class RecipientProvider {
if (address.isGroup() && settings.isPresent() && groupRecord.isPresent()) {
return Optional.of(getGroupRecipientDetails(context, address, groupRecord, settings, true));
} else if (!address.isGroup() && settings.isPresent()) {
- return Optional.of(new RecipientDetails(null, null, !TextUtils.isEmpty(settings.get().getSystemDisplayName()), settings.get(), null));
+ boolean isLocalNumber = address.serialize().equals(TextSecurePreferences.getLocalNumber(context));
+ return Optional.of(new RecipientDetails(null, null, !TextUtils.isEmpty(settings.get().getSystemDisplayName()), isLocalNumber, settings.get(), null));
}
return Optional.absent();
@@ -114,7 +116,8 @@ class RecipientProvider {
return STATIC_DETAILS.get(address.serialize());
} else {
boolean systemContact = settings.isPresent() && !TextUtils.isEmpty(settings.get().getSystemDisplayName());
- return new RecipientDetails(null, null, systemContact, settings.orNull(), null);
+ boolean isLocalNumber = address.serialize().equals(TextSecurePreferences.getLocalNumber(context));
+ return new RecipientDetails(null, null, systemContact, isLocalNumber, settings.orNull(), null);
}
}
@@ -146,10 +149,10 @@ class RecipientProvider {
avatarId = groupRecord.get().getAvatarId();
}
- return new RecipientDetails(title, avatarId, false, settings.orNull(), members);
+ return new RecipientDetails(title, avatarId, false, false, settings.orNull(), members);
}
- return new RecipientDetails(context.getString(R.string.RecipientProvider_unnamed_group), null, false, settings.orNull(), null);
+ return new RecipientDetails(context.getString(R.string.RecipientProvider_unnamed_group), null, false, false, settings.orNull(), null);
}
static class RecipientDetails {
@@ -175,11 +178,12 @@ class RecipientProvider {
@Nullable final String profileAvatar;
final boolean profileSharing;
final boolean systemContact;
+ final boolean isLocalNumber;
@Nullable final String notificationChannel;
@NonNull final UnidentifiedAccessMode unidentifiedAccessMode;
RecipientDetails(@Nullable String name, @Nullable Long groupAvatarId,
- boolean systemContact, @Nullable RecipientSettings settings,
+ boolean systemContact, boolean isLocalNumber, @Nullable RecipientSettings settings,
@Nullable List participants)
{
this.groupAvatarId = groupAvatarId;
@@ -203,6 +207,7 @@ class RecipientProvider {
this.profileAvatar = settings != null ? settings.getProfileAvatar() : null;
this.profileSharing = settings != null && settings.isProfileSharing();
this.systemContact = systemContact;
+ this.isLocalNumber = isLocalNumber;
this.notificationChannel = settings != null ? settings.getNotificationChannel() : null;
this.unidentifiedAccessMode = settings != null ? settings.getUnidentifiedAccessMode() : UnidentifiedAccessMode.DISABLED;
diff --git a/src/org/thoughtcrime/securesms/sms/MessageSender.java b/src/org/thoughtcrime/securesms/sms/MessageSender.java
index ca3a47a374..c017188fd1 100644
--- a/src/org/thoughtcrime/securesms/sms/MessageSender.java
+++ b/src/org/thoughtcrime/securesms/sms/MessageSender.java
@@ -18,8 +18,12 @@ package org.thoughtcrime.securesms.sms;
import android.content.Context;
import android.support.annotation.NonNull;
+
+import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
+import org.thoughtcrime.securesms.database.MmsSmsDatabase;
+import org.thoughtcrime.securesms.database.NoSuchMessageException;
+import org.thoughtcrime.securesms.database.model.SmsMessageRecord;
import org.thoughtcrime.securesms.logging.Log;
-import android.util.Pair;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.attachments.Attachment;
@@ -31,7 +35,6 @@ import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.SmsDatabase;
import org.thoughtcrime.securesms.database.ThreadDatabase;
import org.thoughtcrime.securesms.database.model.MessageRecord;
-import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
import org.thoughtcrime.securesms.jobmanager.JobManager;
import org.thoughtcrime.securesms.jobs.MmsSendJob;
import org.thoughtcrime.securesms.jobs.PushGroupSendJob;
@@ -44,7 +47,6 @@ import org.thoughtcrime.securesms.push.AccountManagerFactory;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
import org.thoughtcrime.securesms.util.TextSecurePreferences;
-import org.thoughtcrime.securesms.util.Util;
import org.whispersystems.libsignal.util.guava.Optional;
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
@@ -75,7 +77,7 @@ public class MessageSender {
long messageId = database.insertMessageOutbox(allocatedThreadId, message, forceSms, System.currentTimeMillis(), insertListener);
- sendTextMessage(context, recipient, forceSms, keyExchange, messageId, message.getExpiresIn());
+ sendTextMessage(context, recipient, forceSms, keyExchange, messageId);
return allocatedThreadId;
}
@@ -116,28 +118,23 @@ public class MessageSender {
}
public static void resend(Context context, MessageRecord messageRecord) {
- try {
- long messageId = messageRecord.getId();
- boolean forceSms = messageRecord.isForcedSms();
- boolean keyExchange = messageRecord.isKeyExchange();
- long expiresIn = messageRecord.getExpiresIn();
- Recipient recipient = messageRecord.getRecipient();
+ long messageId = messageRecord.getId();
+ boolean forceSms = messageRecord.isForcedSms();
+ boolean keyExchange = messageRecord.isKeyExchange();
+ long expiresIn = messageRecord.getExpiresIn();
+ Recipient recipient = messageRecord.getRecipient();
- if (messageRecord.isMms()) {
- sendMediaMessage(context, recipient, forceSms, messageId, expiresIn);
- } else {
- sendTextMessage(context, recipient, forceSms, keyExchange, messageId, expiresIn);
- }
- } catch (MmsException e) {
- Log.w(TAG, e);
+ if (messageRecord.isMms()) {
+ sendMediaMessage(context, recipient, forceSms, messageId, expiresIn);
+ } else {
+ sendTextMessage(context, recipient, forceSms, keyExchange, messageId);
}
}
private static void sendMediaMessage(Context context, Recipient recipient, boolean forceSms, long messageId, long expiresIn)
- throws MmsException
{
- if (!forceSms && isSelfSend(context, recipient)) {
- sendMediaSelf(context, messageId, expiresIn);
+ if (isLocalSelfSend(context, recipient, forceSms)) {
+ sendLocalMediaSelf(context, messageId);
} else if (isGroupPushSend(recipient)) {
sendGroupPush(context, recipient, messageId, null);
} else if (!forceSms && isPushMediaSend(context, recipient)) {
@@ -149,10 +146,10 @@ public class MessageSender {
private static void sendTextMessage(Context context, Recipient recipient,
boolean forceSms, boolean keyExchange,
- long messageId, long expiresIn)
+ long messageId)
{
- if (!forceSms && isSelfSend(context, recipient)) {
- sendTextSelf(context, messageId, expiresIn);
+ if (isLocalSelfSend(context, recipient, forceSms)) {
+ sendLocalTextSelf(context, messageId);
} else if (!forceSms && isPushTextSend(context, recipient, keyExchange)) {
sendTextPush(context, recipient, messageId);
} else {
@@ -160,38 +157,6 @@ public class MessageSender {
}
}
- private static void sendTextSelf(Context context, long messageId, long expiresIn) {
- SmsDatabase database = DatabaseFactory.getSmsDatabase(context);
-
- database.markAsSent(messageId, true);
-
- Pair messageAndThreadId = database.copyMessageInbox(messageId);
- database.markAsPush(messageAndThreadId.first);
-
- if (expiresIn > 0) {
- ExpiringMessageManager expiringMessageManager = ApplicationContext.getInstance(context).getExpiringMessageManager();
-
- database.markExpireStarted(messageId);
- expiringMessageManager.scheduleDeletion(messageId, false, expiresIn);
- }
- }
-
- private static void sendMediaSelf(Context context, long messageId, long expiresIn)
- throws MmsException
- {
- ExpiringMessageManager expiringMessageManager = ApplicationContext.getInstance(context).getExpiringMessageManager();
- MmsDatabase database = DatabaseFactory.getMmsDatabase(context);
-
- database.markAsSent(messageId, true);
- database.copyMessageInbox(messageId);
- markAttachmentsAsUploaded(messageId, database, DatabaseFactory.getAttachmentDatabase(context));
-
- if (expiresIn > 0) {
- database.markExpireStarted(messageId);
- expiringMessageManager.scheduleDeletion(messageId, true, expiresIn);
- }
- }
-
private static void sendTextPush(Context context, Recipient recipient, long messageId) {
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
jobManager.add(new PushTextSendJob(context, messageId, recipient.getAddress()));
@@ -246,18 +211,6 @@ public class MessageSender {
!recipient.getAddress().isMmsGroup();
}
- private static boolean isSelfSend(Context context, Recipient recipient) {
- if (!TextSecurePreferences.isPushRegistered(context)) {
- return false;
- }
-
- if (recipient.isGroupRecipient()) {
- return false;
- }
-
- return Util.isOwnNumber(context, recipient.getAddress());
- }
-
private static boolean isPushDestination(Context context, Recipient destination) {
if (destination.resolve().getRegistered() == RecipientDatabase.RegisteredState.REGISTERED) {
return true;
@@ -282,15 +235,61 @@ public class MessageSender {
}
}
- private static void markAttachmentsAsUploaded(long mmsId, @NonNull MmsDatabase mmsDatabase, @NonNull AttachmentDatabase attachmentDatabase) {
- try (MmsDatabase.Reader reader = mmsDatabase.readerFor(mmsDatabase.getMessage(mmsId))) {
- MessageRecord message = reader.getNext();
+ private static boolean isLocalSelfSend(@NonNull Context context, @NonNull Recipient recipient, boolean forceSms) {
+ return recipient.isLocalNumber() &&
+ !forceSms &&
+ TextSecurePreferences.isPushRegistered(context) &&
+ !TextSecurePreferences.isMultiDevice(context);
+ }
- if (message != null && message.isMms()) {
- for (Attachment attachment : ((MmsMessageRecord) message).getSlideDeck().asAttachments()) {
- attachmentDatabase.markAttachmentUploaded(mmsId, attachment);
- }
+ private static void sendLocalMediaSelf(Context context, long messageId) {
+ try {
+ ExpiringMessageManager expirationManager = ApplicationContext.getInstance(context).getExpiringMessageManager();
+ AttachmentDatabase attachmentDatabase = DatabaseFactory.getAttachmentDatabase(context);
+ MmsDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context);
+ MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
+ OutgoingMediaMessage message = mmsDatabase.getOutgoingMessage(messageId);
+ SyncMessageId syncId = new SyncMessageId(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)), message.getSentTimeMillis());
+
+ for (Attachment attachment : message.getAttachments()) {
+ attachmentDatabase.markAttachmentUploaded(messageId, attachment);
}
+
+ mmsDatabase.markAsSent(messageId, true);
+ mmsDatabase.markUnidentified(messageId, true);
+
+ mmsSmsDatabase.incrementDeliveryReceiptCount(syncId, System.currentTimeMillis());
+ mmsSmsDatabase.incrementReadReceiptCount(syncId, System.currentTimeMillis());
+
+ if (message.getExpiresIn() > 0 && !message.isExpirationUpdate()) {
+ mmsDatabase.markExpireStarted(messageId);
+ expirationManager.scheduleDeletion(messageId, true, message.getExpiresIn());
+ }
+ } catch (NoSuchMessageException | MmsException e) {
+ Log.w("Failed to update self-sent message.", e);
+ }
+ }
+
+ private static void sendLocalTextSelf(Context context, long messageId) {
+ try {
+ ExpiringMessageManager expirationManager = ApplicationContext.getInstance(context).getExpiringMessageManager();
+ SmsDatabase smsDatabase = DatabaseFactory.getSmsDatabase(context);
+ MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context);
+ SmsMessageRecord message = smsDatabase.getMessage(messageId);
+ SyncMessageId syncId = new SyncMessageId(Address.fromSerialized(TextSecurePreferences.getLocalNumber(context)), message.getDateSent());
+
+ smsDatabase.markAsSent(messageId, true);
+ smsDatabase.markUnidentified(messageId, true);
+
+ mmsSmsDatabase.incrementDeliveryReceiptCount(syncId, System.currentTimeMillis());
+ mmsSmsDatabase.incrementReadReceiptCount(syncId, System.currentTimeMillis());
+
+ if (message.getExpiresIn() > 0) {
+ smsDatabase.markExpireStarted(messageId);
+ expirationManager.scheduleDeletion(message.getId(), message.isMms(), message.getExpiresIn());
+ }
+ } catch (NoSuchMessageException e) {
+ Log.w("Failed to update self-sent message.", e);
}
}
}