Sync self-sends to desktop.

Updated UI to show self-conversations as "Note to Self".
master
Greyson Parrelli 2019-01-13 23:30:54 -08:00
parent d42c9b5dbc
commit c2a86fcc74
25 changed files with 320 additions and 152 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 191 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 545 B

View File

@ -20,6 +20,7 @@
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:background="?selectableItemBackgroundBorderless"
android:visibility="visible"/>
<org.thoughtcrime.securesms.components.AvatarImageView
@ -39,44 +40,47 @@
tools:src="@drawable/ic_contact_picture"
android:contentDescription="@string/conversation_list_item_view__contact_photo_image"/>
<RelativeLayout android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/contact_photo_image"
android:layout_toEndOf="@id/contact_photo_image"
android:layout_centerVertical="true">
<LinearLayout
android:id="@+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_toRightOf="@id/contact_photo_image"
android:layout_toEndOf="@id/contact_photo_image"
android:layout_centerVertical="true">
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/title"
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:textSize="18dp"
android:transitionName="recipient_name"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:layout_gravity="center_vertical"
style="@style/TextSecure.TitleTextStyle"
tools:ignore="UnusedAttribute"/>
<LinearLayout
android:id="@+id/subtitle_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/verified_indicator"
android:src="@drawable/ic_check_circle_white_18dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:textSize="18dp"
android:transitionName="recipient_name"
android:drawablePadding="5dp"
android:gravity="center_vertical"
android:layout_gravity="center_vertical"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
style="@style/TextSecure.TitleTextStyle"
tools:ignore="UnusedAttribute"/>
android:layout_marginRight="3dp"
android:layout_marginEnd="3dp"
android:layout_gravity="bottom"
android:alpha="0.7"
android:visibility="gone"/>
<ImageView android:id="@+id/verified_indicator"
android:src="@drawable/ic_check_circle_white_18dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="3dp"
android:layout_marginEnd="3dp"
android:layout_gravity="bottom"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_below="@id/title"
android:alpha="0.7"
android:visibility="gone"/>
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
android:id="@+id/subtitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@ -84,14 +88,13 @@
android:ellipsize="end"
android:layout_gravity="center_vertical|start"
android:gravity="center_vertical"
android:layout_toRightOf="@id/verified_indicator"
android:layout_toEndOf="@id/verified_indicator"
android:layout_below="@id/title"
android:textDirection="ltr"
android:textSize="13dp"
tools:text="(123) 123-1234"
style="@style/TextSecure.SubtitleTextStyle"/>
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</org.thoughtcrime.securesms.conversation.ConversationTitleView>

View File

@ -6,6 +6,7 @@
<string name="delete">Delete</string>
<string name="please_wait">Please wait...</string>
<string name="save">Save</string>
<string name="note_to_self">Note to Self</string>
<!-- AbstractNotificationBuilder -->
<string name="AbstractNotificationBuilder_new_message">New message</string>

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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<SystemContactInfo> 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,

View File

@ -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();

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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<UnidentifiedAccessPair> 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);

View File

@ -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<UnidentifiedAccessPair> 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;
}

View File

@ -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<UnidentifiedAccessPair> 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);

View File

@ -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<RecipientDetails> details,
@NonNull ListenableFutureTask<RecipientDetails> 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;

View File

@ -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<String, RecipientDetails> STATIC_DETAILS = new HashMap<String, RecipientDetails>() {{
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<RecipientSettings> settings, @NonNull Optional<GroupRecord> 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<Recipient> 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;

View File

@ -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<Long, Long> 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);
}
}
}