mirror of
https://github.com/oxen-io/session-android.git
synced 2025-02-18 23:18:26 +00:00
Sync self-sends to desktop.
Updated UI to show self-conversations as "Note to Self".
This commit is contained in:
parent
d42c9b5dbc
commit
c2a86fcc74
BIN
res/drawable-hdpi/ic_note_to_self.png
Normal file
BIN
res/drawable-hdpi/ic_note_to_self.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 274 B |
BIN
res/drawable-mdpi/ic_note_to_self.png
Normal file
BIN
res/drawable-mdpi/ic_note_to_self.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 191 B |
BIN
res/drawable-xhdpi/ic_note_to_self.png
Normal file
BIN
res/drawable-xhdpi/ic_note_to_self.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 282 B |
BIN
res/drawable-xxhdpi/ic_note_to_self.png
Normal file
BIN
res/drawable-xxhdpi/ic_note_to_self.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 452 B |
BIN
res/drawable-xxxhdpi/ic_note_to_self.png
Normal file
BIN
res/drawable-xxxhdpi/ic_note_to_self.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 545 B |
@ -20,6 +20,7 @@
|
|||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
|
android:background="?selectableItemBackgroundBorderless"
|
||||||
android:visibility="visible"/>
|
android:visibility="visible"/>
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.AvatarImageView
|
<org.thoughtcrime.securesms.components.AvatarImageView
|
||||||
@ -39,44 +40,47 @@
|
|||||||
tools:src="@drawable/ic_contact_picture"
|
tools:src="@drawable/ic_contact_picture"
|
||||||
android:contentDescription="@string/conversation_list_item_view__contact_photo_image"/>
|
android:contentDescription="@string/conversation_list_item_view__contact_photo_image"/>
|
||||||
|
|
||||||
<RelativeLayout android:id="@+id/content"
|
<LinearLayout
|
||||||
android:layout_width="wrap_content"
|
android:id="@+id/content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_toRightOf="@id/contact_photo_image"
|
android:layout_height="wrap_content"
|
||||||
android:layout_toEndOf="@id/contact_photo_image"
|
android:orientation="vertical"
|
||||||
android:layout_centerVertical="true">
|
android:layout_toRightOf="@id/contact_photo_image"
|
||||||
|
android:layout_toEndOf="@id/contact_photo_image"
|
||||||
|
android:layout_centerVertical="true">
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
<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_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:maxLines="1"
|
android:layout_marginRight="3dp"
|
||||||
android:ellipsize="end"
|
android:layout_marginEnd="3dp"
|
||||||
android:textSize="18dp"
|
android:layout_gravity="bottom"
|
||||||
android:transitionName="recipient_name"
|
android:alpha="0.7"
|
||||||
android:drawablePadding="5dp"
|
android:visibility="gone"/>
|
||||||
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"/>
|
|
||||||
|
|
||||||
<ImageView android:id="@+id/verified_indicator"
|
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||||
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
|
|
||||||
android:id="@+id/subtitle"
|
android:id="@+id/subtitle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
@ -84,14 +88,13 @@
|
|||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:layout_gravity="center_vertical|start"
|
android:layout_gravity="center_vertical|start"
|
||||||
android:gravity="center_vertical"
|
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:textDirection="ltr"
|
||||||
android:textSize="13dp"
|
android:textSize="13dp"
|
||||||
tools:text="(123) 123-1234"
|
tools:text="(123) 123-1234"
|
||||||
style="@style/TextSecure.SubtitleTextStyle"/>
|
style="@style/TextSecure.SubtitleTextStyle"/>
|
||||||
|
|
||||||
</RelativeLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</org.thoughtcrime.securesms.conversation.ConversationTitleView>
|
</org.thoughtcrime.securesms.conversation.ConversationTitleView>
|
@ -6,6 +6,7 @@
|
|||||||
<string name="delete">Delete</string>
|
<string name="delete">Delete</string>
|
||||||
<string name="please_wait">Please wait...</string>
|
<string name="please_wait">Please wait...</string>
|
||||||
<string name="save">Save</string>
|
<string name="save">Save</string>
|
||||||
|
<string name="note_to_self">Note to Self</string>
|
||||||
|
|
||||||
<!-- AbstractNotificationBuilder -->
|
<!-- AbstractNotificationBuilder -->
|
||||||
<string name="AbstractNotificationBuilder_new_message">New message</string>
|
<string name="AbstractNotificationBuilder_new_message">New message</string>
|
||||||
|
@ -24,18 +24,12 @@ import android.os.Build.VERSION;
|
|||||||
import android.os.Build.VERSION_CODES;
|
import android.os.Build.VERSION_CODES;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
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.text.style.StyleSpan;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.annimon.stream.Stream;
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.components.AlertView;
|
import org.thoughtcrime.securesms.components.AlertView;
|
||||||
import org.thoughtcrime.securesms.components.AvatarImageView;
|
import org.thoughtcrime.securesms.components.AvatarImageView;
|
||||||
import org.thoughtcrime.securesms.components.DeliveryStatusView;
|
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.search.model.MessageResult;
|
||||||
import org.thoughtcrime.securesms.util.DateUtils;
|
import org.thoughtcrime.securesms.util.DateUtils;
|
||||||
import org.thoughtcrime.securesms.util.SearchUtil;
|
import org.thoughtcrime.securesms.util.SearchUtil;
|
||||||
import org.thoughtcrime.securesms.util.SearchUtil.StyleFactory;
|
|
||||||
import org.thoughtcrime.securesms.util.ThemeUtil;
|
import org.thoughtcrime.securesms.util.ThemeUtil;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
@ -147,7 +139,9 @@ public class ConversationListItem extends RelativeLayout
|
|||||||
|
|
||||||
this.recipient.addListener(this);
|
this.recipient.addListener(this);
|
||||||
if (highlightSubstring != null) {
|
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 {
|
} else {
|
||||||
this.fromView.setText(recipient, unreadCount == 0);
|
this.fromView.setText(recipient, unreadCount == 0);
|
||||||
}
|
}
|
||||||
@ -201,7 +195,9 @@ public class ConversationListItem extends RelativeLayout
|
|||||||
|
|
||||||
this.recipient.addListener(this);
|
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));
|
subjectView.setText(SearchUtil.getHighlightedSpan(locale, () -> new StyleSpan(Typeface.BOLD), contact.getAddress().toPhoneString(), highlightSubstring));
|
||||||
dateView.setText("");
|
dateView.setText("");
|
||||||
archivedView.setVisibility(GONE);
|
archivedView.setVisibility(GONE);
|
||||||
|
@ -29,6 +29,10 @@ import android.support.v7.widget.Toolbar;
|
|||||||
import android.telephony.PhoneNumberUtils;
|
import android.telephony.PhoneNumberUtils;
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
|
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.database.GroupDatabase;
|
||||||
import org.thoughtcrime.securesms.jobs.RotateProfileKeyJob;
|
import org.thoughtcrime.securesms.jobs.RotateProfileKeyJob;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
@ -202,14 +206,19 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setHeader(@NonNull Recipient recipient) {
|
private void setHeader(@NonNull Recipient recipient) {
|
||||||
glideRequests.load(recipient.getContactPhoto())
|
ContactPhoto contactPhoto = recipient.isLocalNumber() ? new ProfileContactPhoto(recipient.getAddress(), String.valueOf(TextSecurePreferences.getProfileAvatarId(this)))
|
||||||
.fallback(recipient.getFallbackContactPhoto().asCallCard(this))
|
: recipient.getContactPhoto();
|
||||||
.error(recipient.getFallbackContactPhoto().asCallCard(this))
|
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)
|
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
.into(this.avatar);
|
.into(this.avatar);
|
||||||
|
|
||||||
if (recipient.getContactPhoto() == null) this.avatar.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
|
if (contactPhoto == null) this.avatar.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
|
||||||
else this.avatar.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
else this.avatar.setScaleType(ImageView.ScaleType.CENTER_CROP);
|
||||||
|
|
||||||
this.avatar.setBackgroundColor(recipient.getColor().toActionBarColor(this));
|
this.avatar.setBackgroundColor(recipient.getColor().toActionBarColor(this));
|
||||||
this.toolbarLayout.setTitle(recipient.toShortString());
|
this.toolbarLayout.setTitle(recipient.toShortString());
|
||||||
@ -356,6 +365,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
|||||||
|
|
||||||
private void setSummaries(Recipient recipient) {
|
private void setSummaries(Recipient recipient) {
|
||||||
CheckBoxPreference mutePreference = (CheckBoxPreference) this.findPreference(PREFERENCE_MUTED);
|
CheckBoxPreference mutePreference = (CheckBoxPreference) this.findPreference(PREFERENCE_MUTED);
|
||||||
|
Preference customPreference = this.findPreference(PREFERENCE_CUSTOM_NOTIFICATIONS);
|
||||||
Preference ringtoneMessagePreference = this.findPreference(PREFERENCE_MESSAGE_TONE);
|
Preference ringtoneMessagePreference = this.findPreference(PREFERENCE_MESSAGE_TONE);
|
||||||
Preference ringtoneCallPreference = this.findPreference(PREFERENCE_CALL_TONE);
|
Preference ringtoneCallPreference = this.findPreference(PREFERENCE_CALL_TONE);
|
||||||
ListPreference vibrateMessagePreference = (ListPreference) this.findPreference(PREFERENCE_MESSAGE_VIBRATE);
|
ListPreference vibrateMessagePreference = (ListPreference) this.findPreference(PREFERENCE_MESSAGE_VIBRATE);
|
||||||
@ -384,7 +394,19 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
|
|||||||
vibrateCallPreference.setSummary(vibrateCallSummary.first);
|
vibrateCallPreference.setSummary(vibrateCallSummary.first);
|
||||||
vibrateCallPreference.setValueIndex(vibrateCallSummary.second);
|
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 (colorPreference != null) colorPreference.setVisible(false);
|
||||||
if (identityPreference != null) identityPreference.setVisible(false);
|
if (identityPreference != null) identityPreference.setVisible(false);
|
||||||
if (callCategory != null) callCategory.setVisible(false);
|
if (callCategory != null) callCategory.setVisible(false);
|
||||||
|
@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.R;
|
|||||||
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
|
import org.thoughtcrime.securesms.components.emoji.EmojiTextView;
|
||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.util.ResUtil;
|
import org.thoughtcrime.securesms.util.ResUtil;
|
||||||
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.spans.CenterAlignedRelativeSizeSpan;
|
import org.thoughtcrime.securesms.util.spans.CenterAlignedRelativeSizeSpan;
|
||||||
|
|
||||||
public class FromTextView extends EmojiTextView {
|
public class FromTextView extends EmojiTextView {
|
||||||
@ -52,7 +53,10 @@ public class FromTextView extends EmojiTextView {
|
|||||||
fromSpan.setSpan(new StyleSpan(typeface), 0, builder.length(),
|
fromSpan.setSpan(new StyleSpan(typeface), 0, builder.length(),
|
||||||
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
|
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() + ") ");
|
SpannableString profileName = new SpannableString(" (~" + recipient.getProfileName() + ") ");
|
||||||
profileName.setSpan(new CenterAlignedRelativeSizeSpan(0.75f), 0, profileName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
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);
|
profileName.setSpan(new TypefaceSpan("sans-serif-light"), 0, profileName.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
@ -29,9 +29,11 @@ import android.provider.ContactsContract.PhoneLookup;
|
|||||||
import android.telephony.PhoneNumberUtils;
|
import android.telephony.PhoneNumberUtils;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
import org.thoughtcrime.securesms.database.Address;
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.database.GroupDatabase;
|
import org.thoughtcrime.securesms.database.GroupDatabase;
|
||||||
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -204,6 +206,12 @@ public class ContactAccessor {
|
|||||||
reader.close();
|
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;
|
return numberList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,6 +40,7 @@ import org.thoughtcrime.securesms.database.Address;
|
|||||||
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
|
||||||
import org.thoughtcrime.securesms.mms.GlideRequests;
|
import org.thoughtcrime.securesms.mms.GlideRequests;
|
||||||
import org.thoughtcrime.securesms.util.StickyHeaderDecoration.StickyHeaderAdapter;
|
import org.thoughtcrime.securesms.util.StickyHeaderDecoration.StickyHeaderAdapter;
|
||||||
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
@ -75,6 +75,10 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientM
|
|||||||
this.numberView.setTextColor(color);
|
this.numberView.setTextColor(color);
|
||||||
this.contactPhotoImage.setAvatar(glideRequests, recipient, false);
|
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);
|
setText(type, name, number, label);
|
||||||
|
|
||||||
if (multiSelect) this.checkBox.setVisibility(View.VISIBLE);
|
if (multiSelect) this.checkBox.setVisibility(View.VISIBLE);
|
||||||
|
@ -24,6 +24,8 @@ import android.content.Context;
|
|||||||
import android.content.OperationApplicationException;
|
import android.content.OperationApplicationException;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.CursorWrapper;
|
import android.database.CursorWrapper;
|
||||||
|
import android.database.MatrixCursor;
|
||||||
|
import android.database.MergeCursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
@ -38,6 +40,7 @@ import android.util.Pair;
|
|||||||
import org.thoughtcrime.securesms.R;
|
import org.thoughtcrime.securesms.R;
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
import org.thoughtcrime.securesms.database.Address;
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
|
|
||||||
@ -222,6 +225,25 @@ public class ContactsDatabase {
|
|||||||
new String[] {CONTACT_MIMETYPE,
|
new String[] {CONTACT_MIMETYPE,
|
||||||
"%" + filter + "%", "%" + filter + "%"},
|
"%" + filter + "%", "%" + filter + "%"},
|
||||||
sort);
|
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,
|
return new ProjectionMappingCursor(cursor, projectionMap,
|
||||||
|
@ -652,6 +652,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
|
|||||||
inflater.inflate(R.menu.conversation_add_to_contacts, menu);
|
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);
|
searchViewItem = menu.findItem(R.id.menu_search);
|
||||||
|
|
||||||
SearchView searchView = (SearchView) searchViewItem.getActionView();
|
SearchView searchView = (SearchView) searchViewItem.getActionView();
|
||||||
|
@ -429,7 +429,7 @@ public class ConversationItem extends LinearLayout
|
|||||||
@NonNull Recipient conversationRecipient,
|
@NonNull Recipient conversationRecipient,
|
||||||
boolean isGroupThread)
|
boolean isGroupThread)
|
||||||
{
|
{
|
||||||
boolean showControls = !messageRecord.isFailed() && !Util.isOwnNumber(context, conversationRecipient.getAddress());
|
boolean showControls = !messageRecord.isFailed();
|
||||||
|
|
||||||
if (hasSharedContact(messageRecord)) {
|
if (hasSharedContact(messageRecord)) {
|
||||||
sharedContactStub.get().setVisibility(VISIBLE);
|
sharedContactStub.get().setVisibility(VISIBLE);
|
||||||
|
@ -32,6 +32,7 @@ public class ConversationTitleView extends RelativeLayout {
|
|||||||
private TextView title;
|
private TextView title;
|
||||||
private TextView subtitle;
|
private TextView subtitle;
|
||||||
private ImageView verified;
|
private ImageView verified;
|
||||||
|
private View subtitleContainer;
|
||||||
|
|
||||||
public ConversationTitleView(Context context) {
|
public ConversationTitleView(Context context) {
|
||||||
this(context, null);
|
this(context, null);
|
||||||
@ -46,12 +47,13 @@ public class ConversationTitleView extends RelativeLayout {
|
|||||||
public void onFinishInflate() {
|
public void onFinishInflate() {
|
||||||
super.onFinishInflate();
|
super.onFinishInflate();
|
||||||
|
|
||||||
this.back = ViewUtil.findById(this, R.id.up_button);
|
this.back = ViewUtil.findById(this, R.id.up_button);
|
||||||
this.content = ViewUtil.findById(this, R.id.content);
|
this.content = ViewUtil.findById(this, R.id.content);
|
||||||
this.title = ViewUtil.findById(this, R.id.title);
|
this.title = ViewUtil.findById(this, R.id.title);
|
||||||
this.subtitle = ViewUtil.findById(this, R.id.subtitle);
|
this.subtitle = ViewUtil.findById(this, R.id.subtitle);
|
||||||
this.verified = ViewUtil.findById(this, R.id.verified_indicator);
|
this.verified = ViewUtil.findById(this, R.id.verified_indicator);
|
||||||
this.avatar = ViewUtil.findById(this, R.id.contact_photo_image);
|
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.title, getContext());
|
||||||
ViewUtil.setTextViewGravityStart(this.subtitle, getContext());
|
ViewUtil.setTextViewGravityStart(this.subtitle, getContext());
|
||||||
@ -102,6 +104,7 @@ public class ConversationTitleView extends RelativeLayout {
|
|||||||
|
|
||||||
private void setRecipientTitle(Recipient recipient) {
|
private void setRecipientTitle(Recipient recipient) {
|
||||||
if (recipient.isGroupRecipient()) setGroupRecipientTitle(recipient);
|
if (recipient.isGroupRecipient()) setGroupRecipientTitle(recipient);
|
||||||
|
else if (recipient.isLocalNumber()) setSelfTitle();
|
||||||
else if (TextUtils.isEmpty(recipient.getName())) setNonContactRecipientTitle(recipient);
|
else if (TextUtils.isEmpty(recipient.getName())) setNonContactRecipientTitle(recipient);
|
||||||
else setContactRecipientTitle(recipient);
|
else setContactRecipientTitle(recipient);
|
||||||
}
|
}
|
||||||
@ -116,11 +119,18 @@ public class ConversationTitleView extends RelativeLayout {
|
|||||||
.collect(Collectors.joining(", ")));
|
.collect(Collectors.joining(", ")));
|
||||||
|
|
||||||
this.subtitle.setVisibility(View.VISIBLE);
|
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")
|
@SuppressLint("SetTextI18n")
|
||||||
private void setNonContactRecipientTitle(Recipient recipient) {
|
private void setNonContactRecipientTitle(Recipient recipient) {
|
||||||
this.title.setText(recipient.getAddress().serialize());
|
this.title.setText(recipient.getAddress().serialize());
|
||||||
|
this.subtitleContainer.setVisibility(VISIBLE);
|
||||||
|
|
||||||
if (TextUtils.isEmpty(recipient.getProfileName())) {
|
if (TextUtils.isEmpty(recipient.getProfileName())) {
|
||||||
this.subtitle.setText(null);
|
this.subtitle.setText(null);
|
||||||
@ -138,5 +148,6 @@ public class ConversationTitleView extends RelativeLayout {
|
|||||||
else this.subtitle.setText(recipient.getAddress().serialize());
|
else this.subtitle.setText(recipient.getAddress().serialize());
|
||||||
|
|
||||||
this.subtitle.setVisibility(View.VISIBLE);
|
this.subtitle.setVisibility(View.VISIBLE);
|
||||||
|
this.subtitleContainer.setVisibility(VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -61,8 +61,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||||||
private static final int ATTACHMENT_CAPTIONS_FIX = 15;
|
private static final int ATTACHMENT_CAPTIONS_FIX = 15;
|
||||||
private static final int PREVIEWS = 16;
|
private static final int PREVIEWS = 16;
|
||||||
private static final int CONVERSATION_SEARCH = 17;
|
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 static final String DATABASE_NAME = "signal.db";
|
||||||
|
|
||||||
private final Context context;
|
private final Context context;
|
||||||
@ -383,6 +384,22 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper {
|
|||||||
Log.i(TAG, "Indexing finished. Total time: " + (mmsFinished - start) + " ms");
|
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();
|
db.setTransactionSuccessful();
|
||||||
} finally {
|
} finally {
|
||||||
db.endTransaction();
|
db.endTransaction();
|
||||||
|
@ -733,6 +733,12 @@ public class PushDecryptJob extends ContextJob {
|
|||||||
message.getMessage().getExpiresInSeconds() * 1000L);
|
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;
|
return threadId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -825,6 +831,12 @@ public class PushDecryptJob extends ContextJob {
|
|||||||
.scheduleDeletion(messageId, isGroup, message.getExpirationStartTimestamp(), expiresInMillis);
|
.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;
|
return threadId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,8 +11,8 @@ import org.thoughtcrime.securesms.attachments.Attachment;
|
|||||||
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
|
||||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||||
import org.thoughtcrime.securesms.database.Address;
|
import org.thoughtcrime.securesms.database.Address;
|
||||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
|
||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
|
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
|
||||||
import org.thoughtcrime.securesms.database.MmsDatabase;
|
import org.thoughtcrime.securesms.database.MmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||||
import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode;
|
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.ChainParameters;
|
||||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.mms.MmsException;
|
import org.thoughtcrime.securesms.mms.MmsException;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
||||||
@ -32,10 +31,12 @@ import org.thoughtcrime.securesms.transport.UndeliverableMessageException;
|
|||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceMessageSender;
|
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.crypto.UntrustedIdentityException;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachment;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Preview;
|
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.messages.shared.SharedContact;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
||||||
@ -131,7 +132,7 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
log(TAG, "Sending message: " + messageId);
|
log(TAG, "Sending message: " + messageId);
|
||||||
|
|
||||||
Recipient recipient = message.getRecipient().resolve();
|
Recipient recipient = message.getRecipient().resolve();
|
||||||
byte[] profileKey = recipient.getProfileKey();
|
byte[] profileKey = recipient.getProfileKey();
|
||||||
UnidentifiedAccessMode accessMode = recipient.getUnidentifiedAccessMode();
|
UnidentifiedAccessMode accessMode = recipient.getUnidentifiedAccessMode();
|
||||||
@ -142,6 +143,12 @@ public class PushMediaSendJob extends PushSendJob implements InjectableType {
|
|||||||
markAttachmentsUploaded(messageId, message.getAttachments());
|
markAttachmentsUploaded(messageId, message.getAttachments());
|
||||||
database.markUnidentified(messageId, unidentified);
|
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 (TextSecurePreferences.isUnidentifiedDeliveryEnabled(context)) {
|
||||||
if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN && profileKey == null) {
|
if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN && profileKey == null) {
|
||||||
log(TAG, "Marking recipient as UD-unrestricted following a UD send.");
|
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())
|
.asExpirationUpdate(message.isExpirationUpdate())
|
||||||
.build();
|
.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) {
|
} catch (UnregisteredUserException e) {
|
||||||
warn(TAG, e);
|
warn(TAG, e);
|
||||||
throw new InsecureFallbackApprovalException(e);
|
throw new InsecureFallbackApprovalException(e);
|
||||||
|
@ -20,7 +20,6 @@ import org.thoughtcrime.securesms.database.Address;
|
|||||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||||
import org.thoughtcrime.securesms.events.PartProgressEvent;
|
import org.thoughtcrime.securesms.events.PartProgressEvent;
|
||||||
import org.thoughtcrime.securesms.jobmanager.JobParameters;
|
import org.thoughtcrime.securesms.jobmanager.JobParameters;
|
||||||
import org.thoughtcrime.securesms.linkpreview.LinkPreview;
|
|
||||||
import org.thoughtcrime.securesms.logging.Log;
|
import org.thoughtcrime.securesms.logging.Log;
|
||||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader;
|
||||||
import org.thoughtcrime.securesms.mms.OutgoingMediaMessage;
|
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.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
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.SignalServiceAttachment;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Preview;
|
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.messages.shared.SharedContact;
|
||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
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;
|
protected abstract void onPushSend() throws Exception;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.jobs;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
import org.thoughtcrime.securesms.database.MessagingDatabase.SyncMessageId;
|
||||||
import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode;
|
import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessMode;
|
||||||
import org.thoughtcrime.securesms.jobmanager.SafeData;
|
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.UnidentifiedAccessPair;
|
||||||
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException;
|
||||||
import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage;
|
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.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
||||||
|
|
||||||
@ -94,6 +96,12 @@ public class PushTextSendJob extends PushSendJob implements InjectableType {
|
|||||||
database.markAsSent(messageId, true);
|
database.markAsSent(messageId, true);
|
||||||
database.markUnidentified(messageId, unidentified);
|
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 (TextSecurePreferences.isUnidentifiedDeliveryEnabled(context)) {
|
||||||
if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN && profileKey == null) {
|
if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN && profileKey == null) {
|
||||||
log(TAG, "Marking recipient as UD-unrestricted following a UD send.");
|
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())
|
.asEndSessionMessage(message.isEndSession())
|
||||||
.build();
|
.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) {
|
} catch (UnregisteredUserException e) {
|
||||||
warn(TAG, "Failure", e);
|
warn(TAG, "Failure", e);
|
||||||
throw new InsecureFallbackApprovalException(e);
|
throw new InsecureFallbackApprovalException(e);
|
||||||
|
@ -73,6 +73,7 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
private @Nullable String name;
|
private @Nullable String name;
|
||||||
private @Nullable String customLabel;
|
private @Nullable String customLabel;
|
||||||
private boolean resolving;
|
private boolean resolving;
|
||||||
|
private boolean isLocalNumber;
|
||||||
|
|
||||||
private @Nullable Uri systemContactPhoto;
|
private @Nullable Uri systemContactPhoto;
|
||||||
private @Nullable Long groupAvatarId;
|
private @Nullable Long groupAvatarId;
|
||||||
@ -119,15 +120,16 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
@NonNull Optional<RecipientDetails> details,
|
@NonNull Optional<RecipientDetails> details,
|
||||||
@NonNull ListenableFutureTask<RecipientDetails> future)
|
@NonNull ListenableFutureTask<RecipientDetails> future)
|
||||||
{
|
{
|
||||||
this.address = address;
|
this.address = address;
|
||||||
this.color = null;
|
this.color = null;
|
||||||
this.resolving = true;
|
this.resolving = true;
|
||||||
|
|
||||||
if (stale != null) {
|
if (stale != null) {
|
||||||
this.name = stale.name;
|
this.name = stale.name;
|
||||||
this.contactUri = stale.contactUri;
|
this.contactUri = stale.contactUri;
|
||||||
this.systemContactPhoto = stale.systemContactPhoto;
|
this.systemContactPhoto = stale.systemContactPhoto;
|
||||||
this.groupAvatarId = stale.groupAvatarId;
|
this.groupAvatarId = stale.groupAvatarId;
|
||||||
|
this.isLocalNumber = stale.isLocalNumber;
|
||||||
this.color = stale.color;
|
this.color = stale.color;
|
||||||
this.customLabel = stale.customLabel;
|
this.customLabel = stale.customLabel;
|
||||||
this.messageRingtone = stale.messageRingtone;
|
this.messageRingtone = stale.messageRingtone;
|
||||||
@ -155,6 +157,7 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
this.name = details.get().name;
|
this.name = details.get().name;
|
||||||
this.systemContactPhoto = details.get().systemContactPhoto;
|
this.systemContactPhoto = details.get().systemContactPhoto;
|
||||||
this.groupAvatarId = details.get().groupAvatarId;
|
this.groupAvatarId = details.get().groupAvatarId;
|
||||||
|
this.isLocalNumber = details.get().isLocalNumber;
|
||||||
this.color = details.get().color;
|
this.color = details.get().color;
|
||||||
this.messageRingtone = details.get().messageRingtone;
|
this.messageRingtone = details.get().messageRingtone;
|
||||||
this.callRingtone = details.get().callRingtone;
|
this.callRingtone = details.get().callRingtone;
|
||||||
@ -186,6 +189,7 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
Recipient.this.contactUri = result.contactUri;
|
Recipient.this.contactUri = result.contactUri;
|
||||||
Recipient.this.systemContactPhoto = result.systemContactPhoto;
|
Recipient.this.systemContactPhoto = result.systemContactPhoto;
|
||||||
Recipient.this.groupAvatarId = result.groupAvatarId;
|
Recipient.this.groupAvatarId = result.groupAvatarId;
|
||||||
|
Recipient.this.isLocalNumber = result.isLocalNumber;
|
||||||
Recipient.this.color = result.color;
|
Recipient.this.color = result.color;
|
||||||
Recipient.this.customLabel = result.customLabel;
|
Recipient.this.customLabel = result.customLabel;
|
||||||
Recipient.this.messageRingtone = result.messageRingtone;
|
Recipient.this.messageRingtone = result.messageRingtone;
|
||||||
@ -234,6 +238,7 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
this.name = details.name;
|
this.name = details.name;
|
||||||
this.systemContactPhoto = details.systemContactPhoto;
|
this.systemContactPhoto = details.systemContactPhoto;
|
||||||
this.groupAvatarId = details.groupAvatarId;
|
this.groupAvatarId = details.groupAvatarId;
|
||||||
|
this.isLocalNumber = details.isLocalNumber;
|
||||||
this.color = details.color;
|
this.color = details.color;
|
||||||
this.customLabel = details.customLabel;
|
this.customLabel = details.customLabel;
|
||||||
this.messageRingtone = details.messageRingtone;
|
this.messageRingtone = details.messageRingtone;
|
||||||
@ -257,6 +262,10 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
this.resolving = false;
|
this.resolving = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isLocalNumber() {
|
||||||
|
return isLocalNumber;
|
||||||
|
}
|
||||||
|
|
||||||
public synchronized @Nullable Uri getContactUri() {
|
public synchronized @Nullable Uri getContactUri() {
|
||||||
return this.contactUri;
|
return this.contactUri;
|
||||||
}
|
}
|
||||||
@ -434,6 +443,7 @@ public class Recipient implements RecipientModifiedListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized @NonNull FallbackContactPhoto getFallbackContactPhoto() {
|
public synchronized @NonNull FallbackContactPhoto getFallbackContactPhoto() {
|
||||||
|
if (isLocalNumber) return new ResourceContactPhoto(R.drawable.ic_note_to_self);
|
||||||
if (isResolving()) return new TransparentContactPhoto();
|
if (isResolving()) return new TransparentContactPhoto();
|
||||||
else if (isGroupRecipient()) return new ResourceContactPhoto(R.drawable.ic_group_white_24dp, R.drawable.ic_group_large);
|
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);
|
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() {
|
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 (systemContactPhoto != null) return new SystemContactPhoto(address, systemContactPhoto, 0);
|
||||||
else if (profileAvatar != null) return new ProfileContactPhoto(address, profileAvatar);
|
else if (profileAvatar != null) return new ProfileContactPhoto(address, profileAvatar);
|
||||||
else return null;
|
else return null;
|
||||||
|
@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase.UnidentifiedAccessM
|
|||||||
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
|
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
|
||||||
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
import org.thoughtcrime.securesms.util.ListenableFutureTask;
|
||||||
import org.thoughtcrime.securesms.util.SoftHashMap;
|
import org.thoughtcrime.securesms.util.SoftHashMap;
|
||||||
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
import org.thoughtcrime.securesms.util.Util;
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
|
|
||||||
@ -52,7 +53,7 @@ class RecipientProvider {
|
|||||||
private static final ExecutorService asyncRecipientResolver = Util.newSingleThreadedLifoExecutor();
|
private static final ExecutorService asyncRecipientResolver = Util.newSingleThreadedLifoExecutor();
|
||||||
|
|
||||||
private static final Map<String, RecipientDetails> STATIC_DETAILS = new HashMap<String, RecipientDetails>() {{
|
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) {
|
@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()) {
|
if (address.isGroup() && settings.isPresent() && groupRecord.isPresent()) {
|
||||||
return Optional.of(getGroupRecipientDetails(context, address, groupRecord, settings, true));
|
return Optional.of(getGroupRecipientDetails(context, address, groupRecord, settings, true));
|
||||||
} else if (!address.isGroup() && settings.isPresent()) {
|
} 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();
|
return Optional.absent();
|
||||||
@ -114,7 +116,8 @@ class RecipientProvider {
|
|||||||
return STATIC_DETAILS.get(address.serialize());
|
return STATIC_DETAILS.get(address.serialize());
|
||||||
} else {
|
} else {
|
||||||
boolean systemContact = settings.isPresent() && !TextUtils.isEmpty(settings.get().getSystemDisplayName());
|
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();
|
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 {
|
static class RecipientDetails {
|
||||||
@ -175,11 +178,12 @@ class RecipientProvider {
|
|||||||
@Nullable final String profileAvatar;
|
@Nullable final String profileAvatar;
|
||||||
final boolean profileSharing;
|
final boolean profileSharing;
|
||||||
final boolean systemContact;
|
final boolean systemContact;
|
||||||
|
final boolean isLocalNumber;
|
||||||
@Nullable final String notificationChannel;
|
@Nullable final String notificationChannel;
|
||||||
@NonNull final UnidentifiedAccessMode unidentifiedAccessMode;
|
@NonNull final UnidentifiedAccessMode unidentifiedAccessMode;
|
||||||
|
|
||||||
RecipientDetails(@Nullable String name, @Nullable Long groupAvatarId,
|
RecipientDetails(@Nullable String name, @Nullable Long groupAvatarId,
|
||||||
boolean systemContact, @Nullable RecipientSettings settings,
|
boolean systemContact, boolean isLocalNumber, @Nullable RecipientSettings settings,
|
||||||
@Nullable List<Recipient> participants)
|
@Nullable List<Recipient> participants)
|
||||||
{
|
{
|
||||||
this.groupAvatarId = groupAvatarId;
|
this.groupAvatarId = groupAvatarId;
|
||||||
@ -203,6 +207,7 @@ class RecipientProvider {
|
|||||||
this.profileAvatar = settings != null ? settings.getProfileAvatar() : null;
|
this.profileAvatar = settings != null ? settings.getProfileAvatar() : null;
|
||||||
this.profileSharing = settings != null && settings.isProfileSharing();
|
this.profileSharing = settings != null && settings.isProfileSharing();
|
||||||
this.systemContact = systemContact;
|
this.systemContact = systemContact;
|
||||||
|
this.isLocalNumber = isLocalNumber;
|
||||||
this.notificationChannel = settings != null ? settings.getNotificationChannel() : null;
|
this.notificationChannel = settings != null ? settings.getNotificationChannel() : null;
|
||||||
this.unidentifiedAccessMode = settings != null ? settings.getUnidentifiedAccessMode() : UnidentifiedAccessMode.DISABLED;
|
this.unidentifiedAccessMode = settings != null ? settings.getUnidentifiedAccessMode() : UnidentifiedAccessMode.DISABLED;
|
||||||
|
|
||||||
|
@ -18,8 +18,12 @@ package org.thoughtcrime.securesms.sms;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.support.annotation.NonNull;
|
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 org.thoughtcrime.securesms.logging.Log;
|
||||||
import android.util.Pair;
|
|
||||||
|
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
import org.thoughtcrime.securesms.attachments.Attachment;
|
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.SmsDatabase;
|
||||||
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
import org.thoughtcrime.securesms.database.ThreadDatabase;
|
||||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
|
||||||
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
import org.thoughtcrime.securesms.jobmanager.JobManager;
|
||||||
import org.thoughtcrime.securesms.jobs.MmsSendJob;
|
import org.thoughtcrime.securesms.jobs.MmsSendJob;
|
||||||
import org.thoughtcrime.securesms.jobs.PushGroupSendJob;
|
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.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
import org.thoughtcrime.securesms.service.ExpiringMessageManager;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
import org.thoughtcrime.securesms.util.Util;
|
|
||||||
import org.whispersystems.libsignal.util.guava.Optional;
|
import org.whispersystems.libsignal.util.guava.Optional;
|
||||||
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
import org.whispersystems.signalservice.api.SignalServiceAccountManager;
|
||||||
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
|
import org.whispersystems.signalservice.api.push.ContactTokenDetails;
|
||||||
@ -75,7 +77,7 @@ public class MessageSender {
|
|||||||
|
|
||||||
long messageId = database.insertMessageOutbox(allocatedThreadId, message, forceSms, System.currentTimeMillis(), insertListener);
|
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;
|
return allocatedThreadId;
|
||||||
}
|
}
|
||||||
@ -116,28 +118,23 @@ public class MessageSender {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void resend(Context context, MessageRecord messageRecord) {
|
public static void resend(Context context, MessageRecord messageRecord) {
|
||||||
try {
|
long messageId = messageRecord.getId();
|
||||||
long messageId = messageRecord.getId();
|
boolean forceSms = messageRecord.isForcedSms();
|
||||||
boolean forceSms = messageRecord.isForcedSms();
|
boolean keyExchange = messageRecord.isKeyExchange();
|
||||||
boolean keyExchange = messageRecord.isKeyExchange();
|
long expiresIn = messageRecord.getExpiresIn();
|
||||||
long expiresIn = messageRecord.getExpiresIn();
|
Recipient recipient = messageRecord.getRecipient();
|
||||||
Recipient recipient = messageRecord.getRecipient();
|
|
||||||
|
|
||||||
if (messageRecord.isMms()) {
|
if (messageRecord.isMms()) {
|
||||||
sendMediaMessage(context, recipient, forceSms, messageId, expiresIn);
|
sendMediaMessage(context, recipient, forceSms, messageId, expiresIn);
|
||||||
} else {
|
} else {
|
||||||
sendTextMessage(context, recipient, forceSms, keyExchange, messageId, expiresIn);
|
sendTextMessage(context, recipient, forceSms, keyExchange, messageId);
|
||||||
}
|
|
||||||
} catch (MmsException e) {
|
|
||||||
Log.w(TAG, e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void sendMediaMessage(Context context, Recipient recipient, boolean forceSms, long messageId, long expiresIn)
|
private static void sendMediaMessage(Context context, Recipient recipient, boolean forceSms, long messageId, long expiresIn)
|
||||||
throws MmsException
|
|
||||||
{
|
{
|
||||||
if (!forceSms && isSelfSend(context, recipient)) {
|
if (isLocalSelfSend(context, recipient, forceSms)) {
|
||||||
sendMediaSelf(context, messageId, expiresIn);
|
sendLocalMediaSelf(context, messageId);
|
||||||
} else if (isGroupPushSend(recipient)) {
|
} else if (isGroupPushSend(recipient)) {
|
||||||
sendGroupPush(context, recipient, messageId, null);
|
sendGroupPush(context, recipient, messageId, null);
|
||||||
} else if (!forceSms && isPushMediaSend(context, recipient)) {
|
} else if (!forceSms && isPushMediaSend(context, recipient)) {
|
||||||
@ -149,10 +146,10 @@ public class MessageSender {
|
|||||||
|
|
||||||
private static void sendTextMessage(Context context, Recipient recipient,
|
private static void sendTextMessage(Context context, Recipient recipient,
|
||||||
boolean forceSms, boolean keyExchange,
|
boolean forceSms, boolean keyExchange,
|
||||||
long messageId, long expiresIn)
|
long messageId)
|
||||||
{
|
{
|
||||||
if (!forceSms && isSelfSend(context, recipient)) {
|
if (isLocalSelfSend(context, recipient, forceSms)) {
|
||||||
sendTextSelf(context, messageId, expiresIn);
|
sendLocalTextSelf(context, messageId);
|
||||||
} else if (!forceSms && isPushTextSend(context, recipient, keyExchange)) {
|
} else if (!forceSms && isPushTextSend(context, recipient, keyExchange)) {
|
||||||
sendTextPush(context, recipient, messageId);
|
sendTextPush(context, recipient, messageId);
|
||||||
} else {
|
} 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) {
|
private static void sendTextPush(Context context, Recipient recipient, long messageId) {
|
||||||
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
|
JobManager jobManager = ApplicationContext.getInstance(context).getJobManager();
|
||||||
jobManager.add(new PushTextSendJob(context, messageId, recipient.getAddress()));
|
jobManager.add(new PushTextSendJob(context, messageId, recipient.getAddress()));
|
||||||
@ -246,18 +211,6 @@ public class MessageSender {
|
|||||||
!recipient.getAddress().isMmsGroup();
|
!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) {
|
private static boolean isPushDestination(Context context, Recipient destination) {
|
||||||
if (destination.resolve().getRegistered() == RecipientDatabase.RegisteredState.REGISTERED) {
|
if (destination.resolve().getRegistered() == RecipientDatabase.RegisteredState.REGISTERED) {
|
||||||
return true;
|
return true;
|
||||||
@ -282,15 +235,61 @@ public class MessageSender {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void markAttachmentsAsUploaded(long mmsId, @NonNull MmsDatabase mmsDatabase, @NonNull AttachmentDatabase attachmentDatabase) {
|
private static boolean isLocalSelfSend(@NonNull Context context, @NonNull Recipient recipient, boolean forceSms) {
|
||||||
try (MmsDatabase.Reader reader = mmsDatabase.readerFor(mmsDatabase.getMessage(mmsId))) {
|
return recipient.isLocalNumber() &&
|
||||||
MessageRecord message = reader.getNext();
|
!forceSms &&
|
||||||
|
TextSecurePreferences.isPushRegistered(context) &&
|
||||||
|
!TextSecurePreferences.isMultiDevice(context);
|
||||||
|
}
|
||||||
|
|
||||||
if (message != null && message.isMms()) {
|
private static void sendLocalMediaSelf(Context context, long messageId) {
|
||||||
for (Attachment attachment : ((MmsMessageRecord) message).getSlideDeck().asAttachments()) {
|
try {
|
||||||
attachmentDatabase.markAttachmentUploaded(mmsId, attachment);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user