mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-30 13:35:18 +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_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>
|
@ -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>
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user