Move to defined from_recipient_id and to_recipient_id columns on message table.
This commit is contained in:
parent
d079f85eca
commit
279ad7945e
86 changed files with 944 additions and 719 deletions
|
@ -84,7 +84,7 @@ class DatabaseConsistencyTest {
|
|||
.joinToString(separator = " ")
|
||||
.replace(Regex.fromLiteral("( "), "(")
|
||||
.replace(Regex.fromLiteral(" )"), ")")
|
||||
.replace(Regex.fromLiteral("CREATE TABLE \"call\""), "CREATE TABLE call") // solves a specific weirdness with inconsequential quotes
|
||||
.replace(Regex("CREATE TABLE \"([a-z]+)\""), "CREATE TABLE $1") // for some reason SQLite will wrap table names in quotes for upgraded tables. This unwraps them.
|
||||
}
|
||||
|
||||
private class InMemoryTestHelper(private val application: Application) : SQLiteOpenHelper(application, null, null, 1) {
|
||||
|
|
|
@ -693,9 +693,9 @@ class RecipientTableTest_getAndPossiblyMerge {
|
|||
val sms2: MessageRecord = SignalDatabase.messages.getMessageRecord(smsId2)!!
|
||||
val sms3: MessageRecord = SignalDatabase.messages.getMessageRecord(smsId3)!!
|
||||
|
||||
assertEquals(retrievedId, sms1.recipient.id)
|
||||
assertEquals(retrievedId, sms2.recipient.id)
|
||||
assertEquals(retrievedId, sms3.recipient.id)
|
||||
assertEquals(retrievedId, sms1.fromRecipient.id)
|
||||
assertEquals(retrievedId, sms2.fromRecipient.id)
|
||||
assertEquals(retrievedId, sms3.fromRecipient.id)
|
||||
|
||||
assertEquals(retrievedThreadId, sms1.threadId)
|
||||
assertEquals(retrievedThreadId, sms2.threadId)
|
||||
|
@ -706,9 +706,9 @@ class RecipientTableTest_getAndPossiblyMerge {
|
|||
val mms2: MessageRecord = SignalDatabase.messages.getMessageRecord(mmsId2)!!
|
||||
val mms3: MessageRecord = SignalDatabase.messages.getMessageRecord(mmsId3)!!
|
||||
|
||||
assertEquals(retrievedId, mms1.recipient.id)
|
||||
assertEquals(retrievedId, mms2.recipient.id)
|
||||
assertEquals(retrievedId, mms3.recipient.id)
|
||||
assertEquals(retrievedId, mms1.fromRecipient.id)
|
||||
assertEquals(retrievedId, mms2.fromRecipient.id)
|
||||
assertEquals(retrievedId, mms3.fromRecipient.id)
|
||||
|
||||
assertEquals(retrievedThreadId, mms1.threadId)
|
||||
assertEquals(retrievedThreadId, mms2.threadId)
|
||||
|
@ -1035,7 +1035,7 @@ class RecipientTableTest_getAndPossiblyMerge {
|
|||
return SignalDatabase.rawDatabase
|
||||
.select(MessageTable.BODY)
|
||||
.from(MessageTable.TABLE_NAME)
|
||||
.where("${MessageTable.RECIPIENT_ID} = ? AND ${MessageTable.TYPE} = ?", recipientId, MessageTypes.THREAD_MERGE_TYPE)
|
||||
.where("${MessageTable.FROM_RECIPIENT_ID} = ? AND ${MessageTable.TYPE} = ?", recipientId, MessageTypes.THREAD_MERGE_TYPE)
|
||||
.orderBy("${MessageTable.DATE_RECEIVED} DESC")
|
||||
.limit(1)
|
||||
.run()
|
||||
|
@ -1053,7 +1053,7 @@ class RecipientTableTest_getAndPossiblyMerge {
|
|||
return SignalDatabase.rawDatabase
|
||||
.select(MessageTable.BODY)
|
||||
.from(MessageTable.TABLE_NAME)
|
||||
.where("${MessageTable.RECIPIENT_ID} = ? AND ${MessageTable.TYPE} = ?", recipientId, MessageTypes.SESSION_SWITCHOVER_TYPE)
|
||||
.where("${MessageTable.FROM_RECIPIENT_ID} = ? AND ${MessageTable.TYPE} = ?", recipientId, MessageTypes.SESSION_SWITCHOVER_TYPE)
|
||||
.orderBy("${MessageTable.DATE_RECEIVED} DESC")
|
||||
.limit(1)
|
||||
.run()
|
||||
|
|
|
@ -611,7 +611,7 @@ public class FullBackupExporter extends FullBackupBase {
|
|||
}
|
||||
|
||||
private static boolean isForNonExpiringMmsMessage(@NonNull SQLiteDatabase db, long mmsId) {
|
||||
String[] columns = new String[] { MessageTable.RECIPIENT_ID, MessageTable.EXPIRES_IN, MessageTable.VIEW_ONCE };
|
||||
String[] columns = new String[] { MessageTable.EXPIRES_IN, MessageTable.VIEW_ONCE };
|
||||
String where = MessageTable.ID + " = ?";
|
||||
String[] args = new String[] { String.valueOf(mmsId) };
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ class GiftMessageView @JvmOverloads constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun setGiftBadge(glideRequests: GlideRequests, giftBadge: GiftBadge, isOutgoing: Boolean, callback: Callback, recipient: Recipient) {
|
||||
fun setGiftBadge(glideRequests: GlideRequests, giftBadge: GiftBadge, isOutgoing: Boolean, callback: Callback, fromRecipient: Recipient, toRecipient: Recipient) {
|
||||
descriptionView.text = giftBadge.formatExpiry(context)
|
||||
actionView.icon = null
|
||||
actionView.setOnClickListener { callback.onViewGiftBadgeClicked() }
|
||||
|
@ -58,9 +58,9 @@ class GiftMessageView @JvmOverloads constructor(
|
|||
|
||||
if (isOutgoing) {
|
||||
actionView.setText(R.string.GiftMessageView__view)
|
||||
titleView.text = context.getString(R.string.GiftMessageView__donation_on_behalf_of_s, recipient.getDisplayName(context))
|
||||
titleView.text = context.getString(R.string.GiftMessageView__donation_on_behalf_of_s, toRecipient.getDisplayName(context))
|
||||
} else {
|
||||
titleView.text = context.getString(R.string.GiftMessageView__s_donated_to_signal_on, recipient.getShortDisplayName(context))
|
||||
titleView.text = context.getString(R.string.GiftMessageView__s_donated_to_signal_on, fromRecipient.getShortDisplayName(context))
|
||||
when (giftBadge.redemptionState) {
|
||||
GiftBadge.RedemptionState.REDEEMED -> {
|
||||
stopAnimationIfNeeded()
|
||||
|
|
|
@ -31,7 +31,7 @@ object Gifts {
|
|||
expiresIn: Long
|
||||
): OutgoingMessage {
|
||||
return OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = recipient,
|
||||
body = Base64.encodeBytes(giftBadge.toByteArray()),
|
||||
isSecure = true,
|
||||
sentTimeMillis = sentTimestamp,
|
||||
|
|
|
@ -62,7 +62,7 @@ class ViewReceivedGiftBottomSheet : DSLSettingsBottomSheetFragment() {
|
|||
fun show(fragmentManager: FragmentManager, messageRecord: MmsMessageRecord) {
|
||||
ViewReceivedGiftBottomSheet().apply {
|
||||
arguments = Bundle().apply {
|
||||
putParcelable(ARG_SENT_FROM, messageRecord.recipient.id)
|
||||
putParcelable(ARG_SENT_FROM, messageRecord.fromRecipient.id)
|
||||
putByteArray(ARG_GIFT_BADGE, messageRecord.giftBadge!!.toByteArray())
|
||||
putLong(ARG_MESSAGE_ID, messageRecord.id)
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ class ViewSentGiftBottomSheet : DSLSettingsBottomSheetFragment() {
|
|||
fun show(fragmentManager: FragmentManager, messageRecord: MmsMessageRecord) {
|
||||
ViewSentGiftBottomSheet().apply {
|
||||
arguments = Bundle().apply {
|
||||
putParcelable(ARG_SENT_TO, messageRecord.recipient.id)
|
||||
putParcelable(ARG_SENT_TO, messageRecord.toRecipient.id)
|
||||
putByteArray(ARG_GIFT_BADGE, messageRecord.giftBadge!!.toByteArray())
|
||||
}
|
||||
show(fragmentManager, BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG)
|
||||
|
|
|
@ -306,7 +306,7 @@ public class ConversationItemFooter extends ConstraintLayout {
|
|||
int errorMsg;
|
||||
if (messageRecord.hasFailedWithNetworkFailures()) {
|
||||
errorMsg = R.string.ConversationItem_error_network_not_delivered;
|
||||
} else if (messageRecord.getRecipient().isPushGroup() && messageRecord.isIdentityMismatchFailure()) {
|
||||
} else if (messageRecord.getToRecipient().isPushGroup() && messageRecord.isIdentityMismatchFailure()) {
|
||||
errorMsg = R.string.ConversationItem_error_partially_not_delivered;
|
||||
} else {
|
||||
errorMsg = R.string.ConversationItem_error_not_sent_tap_for_details;
|
||||
|
@ -386,7 +386,7 @@ public class ConversationItemFooter extends ConstraintLayout {
|
|||
long newMessageId = buildMessageId(messageRecord);
|
||||
|
||||
if (previousMessageId == newMessageId && deliveryStatusView.isPending() && !messageRecord.isPending()) {
|
||||
if (messageRecord.getRecipient().isGroup()) {
|
||||
if (messageRecord.getToRecipient().isGroup()) {
|
||||
SignalLocalMetrics.GroupMessageSend.onUiUpdated(messageRecord.getId());
|
||||
} else {
|
||||
SignalLocalMetrics.IndividualMessageSend.onUiUpdated(messageRecord.getId());
|
||||
|
@ -429,7 +429,7 @@ public class ConversationItemFooter extends ConstraintLayout {
|
|||
if (mmsMessageRecord.getSlideDeck().getAudioSlide() != null) {
|
||||
showAudioDurationViews();
|
||||
|
||||
if (messageRecord.getViewedReceiptCount() > 0 || (messageRecord.isOutgoing() && Objects.equals(messageRecord.getRecipient(), Recipient.self()))) {
|
||||
if (messageRecord.getViewedReceiptCount() > 0 || (messageRecord.isOutgoing() && Objects.equals(messageRecord.getToRecipient(), Recipient.self()))) {
|
||||
revealDot.setProgress(1f);
|
||||
} else {
|
||||
revealDot.setProgress(0f);
|
||||
|
|
|
@ -86,7 +86,7 @@ class VoiceNoteMediaItemFactory {
|
|||
|
||||
Recipient threadRecipient = Objects.requireNonNull(SignalDatabase.threads()
|
||||
.getRecipientForThreadId(messageRecord.getThreadId()));
|
||||
Recipient sender = messageRecord.isOutgoing() ? Recipient.self() : messageRecord.getIndividualRecipient();
|
||||
Recipient sender = messageRecord.getFromRecipient();
|
||||
Recipient avatarRecipient = threadRecipient.isGroup() ? threadRecipient : sender;
|
||||
AudioSlide audioSlide = ((MmsMessageRecord) messageRecord).getSlideDeck().getAudioSlide();
|
||||
|
||||
|
|
|
@ -1088,7 +1088,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
|||
}
|
||||
|
||||
private static boolean isNoteToSelfDelete(Set<MessageRecord> messageRecords) {
|
||||
return messageRecords.stream().allMatch(messageRecord -> messageRecord.isOutgoing() && messageRecord.getRecipient().isSelf());
|
||||
return messageRecords.stream().allMatch(messageRecord -> messageRecord.isOutgoing() && messageRecord.getToRecipient().isSelf());
|
||||
}
|
||||
|
||||
private void handleDeleteForEveryone(Set<MessageRecord> messageRecords) {
|
||||
|
@ -1436,7 +1436,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
|||
SimpleTask.run(getLifecycle(), () -> {
|
||||
return SignalDatabase.messages().getMessagePositionInConversation(threadId,
|
||||
messageRecord.getDateReceived(),
|
||||
messageRecord.isOutgoing() ? Recipient.self().getId() : messageRecord.getRecipient().getId());
|
||||
messageRecord.getFromRecipient().getId());
|
||||
}, p -> moveToPosition(p + (isTypingIndicatorShowing() ? 1 : 0), () -> {
|
||||
Toast.makeText(getContext(), R.string.ConversationFragment_failed_to_open_message, Toast.LENGTH_SHORT).show();
|
||||
}));
|
||||
|
@ -1791,7 +1791,7 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
|||
|
||||
ApplicationDependencies.getViewOnceMessageManager().scheduleIfNecessary();
|
||||
|
||||
ApplicationDependencies.getJobManager().add(new MultiDeviceViewOnceOpenJob(new MessageTable.SyncMessageId(messageRecord.getIndividualRecipient().getId(), messageRecord.getDateSent())));
|
||||
ApplicationDependencies.getJobManager().add(new MultiDeviceViewOnceOpenJob(new MessageTable.SyncMessageId(messageRecord.getToRecipient().getId(), messageRecord.getDateSent())));
|
||||
|
||||
return tempUri;
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -189,7 +189,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
private Optional<MessageRecord> nextMessageRecord;
|
||||
private Locale locale;
|
||||
private boolean groupThread;
|
||||
private LiveRecipient recipient;
|
||||
private LiveRecipient author;
|
||||
private GlideRequests glideRequests;
|
||||
private Optional<MessageRecord> previousMessage;
|
||||
private ConversationItemDisplayMode displayMode;
|
||||
|
@ -363,7 +363,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
@NonNull Colorizer colorizer,
|
||||
@NonNull ConversationItemDisplayMode displayMode)
|
||||
{
|
||||
if (this.recipient != null) this.recipient.removeForeverObserver(this);
|
||||
if (this.author != null) this.author.removeForeverObserver(this);
|
||||
if (this.conversationRecipient != null) this.conversationRecipient.removeForeverObserver(this);
|
||||
|
||||
lastYDownRelativeToThis = 0;
|
||||
|
@ -378,28 +378,28 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
this.batchSelected = batchSelected;
|
||||
this.conversationRecipient = conversationRecipient.live();
|
||||
this.groupThread = conversationRecipient.isGroup();
|
||||
this.recipient = messageRecord.getIndividualRecipient().live();
|
||||
this.author = messageRecord.getFromRecipient().live();
|
||||
this.canPlayContent = false;
|
||||
this.mediaItem = null;
|
||||
this.colorizer = colorizer;
|
||||
this.displayMode = displayMode;
|
||||
this.previousMessage = previousMessageRecord;
|
||||
|
||||
this.recipient.observeForever(this);
|
||||
this.author.observeForever(this);
|
||||
this.conversationRecipient.observeForever(this);
|
||||
|
||||
setGutterSizes(messageRecord, groupThread);
|
||||
setMessageShape(messageRecord, previousMessageRecord, nextMessageRecord, groupThread);
|
||||
setMediaAttributes(messageRecord, previousMessageRecord, nextMessageRecord, groupThread, hasWallpaper, isMessageRequestAccepted, allowedToPlayInline);
|
||||
setBodyText(messageRecord, searchQuery, isMessageRequestAccepted);
|
||||
setBubbleState(messageRecord, messageRecord.getRecipient(), hasWallpaper, colorizer);
|
||||
setBubbleState(messageRecord, messageRecord.getFromRecipient(), hasWallpaper, colorizer);
|
||||
setInteractionState(conversationMessage, pulse);
|
||||
setStatusIcons(messageRecord, hasWallpaper);
|
||||
setContactPhoto(recipient.get());
|
||||
setGroupMessageStatus(messageRecord, recipient.get());
|
||||
setContactPhoto(author.get());
|
||||
setGroupMessageStatus(messageRecord, author.get());
|
||||
setGroupAuthorColor(messageRecord, hasWallpaper, colorizer);
|
||||
setAuthor(messageRecord, previousMessageRecord, nextMessageRecord, groupThread, hasWallpaper);
|
||||
setQuote(messageRecord, previousMessageRecord, nextMessageRecord, groupThread, messageRecord.getRecipient().getChatColors());
|
||||
setQuote(messageRecord, previousMessageRecord, nextMessageRecord, groupThread);
|
||||
setMessageSpacing(context, messageRecord, previousMessageRecord, nextMessageRecord, groupThread);
|
||||
setReactions(messageRecord);
|
||||
setFooter(messageRecord, nextMessageRecord, locale, groupThread, hasWallpaper);
|
||||
|
@ -627,7 +627,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
}
|
||||
}
|
||||
|
||||
if (recipient.getId().equals(modified.getId())) {
|
||||
if (author.getId().equals(modified.getId())) {
|
||||
setContactPhoto(modified);
|
||||
setGroupMessageStatus(messageRecord, modified);
|
||||
}
|
||||
|
@ -669,8 +669,8 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
|
||||
@Override
|
||||
public void unbind() {
|
||||
if (recipient != null) {
|
||||
recipient.removeForeverObserver(this);
|
||||
if (author != null) {
|
||||
author.removeForeverObserver(this);
|
||||
}
|
||||
if (conversationRecipient != null) {
|
||||
conversationRecipient.removeForeverObserver(this);
|
||||
|
@ -1299,7 +1299,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
paymentViewStub.setVisibility(View.GONE);
|
||||
|
||||
MmsMessageRecord mmsMessageRecord = (MmsMessageRecord) messageRecord;
|
||||
giftViewStub.get().setGiftBadge(glideRequests, Objects.requireNonNull(mmsMessageRecord.getGiftBadge()), messageRecord.isOutgoing(), giftMessageViewCallback, messageRecord.getRecipient());
|
||||
giftViewStub.get().setGiftBadge(glideRequests, Objects.requireNonNull(mmsMessageRecord.getGiftBadge()), messageRecord.isOutgoing(), giftMessageViewCallback, messageRecord.getFromRecipient(), messageRecord.getToRecipient());
|
||||
giftViewStub.get().setVisibility(VISIBLE);
|
||||
|
||||
footer.setVisibility(VISIBLE);
|
||||
|
@ -1316,7 +1316,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
MediaMmsMessageRecord mediaMmsMessageRecord = (MediaMmsMessageRecord) messageRecord;
|
||||
|
||||
paymentViewStub.setVisibility(View.VISIBLE);
|
||||
paymentViewStub.get().bindPayment(messageRecord.getIndividualRecipient(), Objects.requireNonNull(mediaMmsMessageRecord.getPayment()), colorizer);
|
||||
paymentViewStub.get().bindPayment(messageRecord.getFromRecipient(), Objects.requireNonNull(mediaMmsMessageRecord.getPayment()), colorizer);
|
||||
|
||||
footer.setVisibility(VISIBLE);
|
||||
} else {
|
||||
|
@ -1538,7 +1538,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
}
|
||||
}
|
||||
|
||||
private void setQuote(@NonNull MessageRecord current, @NonNull Optional<MessageRecord> previous, @NonNull Optional<MessageRecord> next, boolean isGroupThread, @NonNull ChatColors chatColors) {
|
||||
private void setQuote(@NonNull MessageRecord current, @NonNull Optional<MessageRecord> previous, @NonNull Optional<MessageRecord> next, boolean isGroupThread) {
|
||||
boolean startOfCluster = isStartOfMessageCluster(current, previous, isGroupThread);
|
||||
if (hasQuote(messageRecord)) {
|
||||
if (quoteView == null) {
|
||||
|
@ -1773,7 +1773,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
|
||||
private void setGroupAuthorColor(@NonNull MessageRecord messageRecord, boolean hasWallpaper, @NonNull Colorizer colorizer) {
|
||||
if (groupSender != null) {
|
||||
groupSender.setTextColor(colorizer.getIncomingGroupSenderColor(getContext(), messageRecord.getIndividualRecipient()));
|
||||
groupSender.setTextColor(colorizer.getIncomingGroupSenderColor(getContext(), messageRecord.getFromRecipient()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1782,7 +1782,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
if (isGroupThread && !current.isOutgoing()) {
|
||||
contactPhotoHolder.setVisibility(VISIBLE);
|
||||
|
||||
if (!previous.isPresent() || previous.get().isUpdate() || !current.getRecipient().equals(previous.get().getRecipient()) ||
|
||||
if (!previous.isPresent() || previous.get().isUpdate() || !current.getFromRecipient().equals(previous.get().getFromRecipient()) ||
|
||||
!DateUtils.isSameDay(previous.get().getTimestamp(), current.getTimestamp()) || !isWithinClusteringTime(current, previous.get()))
|
||||
{
|
||||
groupSenderHolder.setVisibility(VISIBLE);
|
||||
|
@ -1797,7 +1797,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
groupSenderHolder.setVisibility(GONE);
|
||||
}
|
||||
|
||||
if (!next.isPresent() || next.get().isUpdate() || !current.getRecipient().equals(next.get().getRecipient()) || !isWithinClusteringTime(current, next.get())) {
|
||||
if (!next.isPresent() || next.get().isUpdate() || !current.getFromRecipient().equals(next.get().getFromRecipient()) || !isWithinClusteringTime(current, next.get())) {
|
||||
contactPhoto.setVisibility(VISIBLE);
|
||||
badgeImageView.setVisibility(VISIBLE);
|
||||
} else {
|
||||
|
@ -1897,7 +1897,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
private boolean isStartOfMessageCluster(@NonNull MessageRecord current, @NonNull Optional<MessageRecord> previous, boolean isGroupThread) {
|
||||
if (isGroupThread) {
|
||||
return !previous.isPresent() || previous.get().isUpdate() || !DateUtils.isSameDay(current.getTimestamp(), previous.get().getTimestamp()) ||
|
||||
!current.getRecipient().equals(previous.get().getRecipient()) || !isWithinClusteringTime(current, previous.get()) || MessageRecordUtil.isScheduled(current);
|
||||
!current.getFromRecipient().equals(previous.get().getFromRecipient()) || !isWithinClusteringTime(current, previous.get()) || MessageRecordUtil.isScheduled(current);
|
||||
} else {
|
||||
return !previous.isPresent() || previous.get().isUpdate() || !DateUtils.isSameDay(current.getTimestamp(), previous.get().getTimestamp()) ||
|
||||
current.isOutgoing() != previous.get().isOutgoing() || previous.get().isSecure() != current.isSecure() || !isWithinClusteringTime(current, previous.get()) ||
|
||||
|
@ -1908,7 +1908,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
private boolean isEndOfMessageCluster(@NonNull MessageRecord current, @NonNull Optional<MessageRecord> next, boolean isGroupThread) {
|
||||
if (isGroupThread) {
|
||||
return !next.isPresent() || next.get().isUpdate() || !DateUtils.isSameDay(current.getTimestamp(), next.get().getTimestamp()) ||
|
||||
!current.getRecipient().equals(next.get().getRecipient()) || !current.getReactions().isEmpty() || !isWithinClusteringTime(current, next.get()) ||
|
||||
!current.getFromRecipient().equals(next.get().getFromRecipient()) || !current.getReactions().isEmpty() || !isWithinClusteringTime(current, next.get()) ||
|
||||
MessageRecordUtil.isScheduled(current);
|
||||
} else {
|
||||
return !next.isPresent() || next.get().isUpdate() || !DateUtils.isSameDay(current.getTimestamp(), next.get().getTimestamp()) ||
|
||||
|
@ -2416,13 +2416,13 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
|
||||
if (slide instanceof ImageSlide) {
|
||||
failedMessage = messageRecord.isOutgoing() ? context.getString(R.string.ConversationItem_cant_download_image_you_will_need_to_send_it_again)
|
||||
: context.getString(R.string.ConversationItem_cant_download_image_s_will_need_to_send_it_again, messageRecord.getIndividualRecipient().getShortDisplayName(context));
|
||||
: context.getString(R.string.ConversationItem_cant_download_image_s_will_need_to_send_it_again, messageRecord.getFromRecipient().getShortDisplayName(context));
|
||||
} else if (slide instanceof VideoSlide) {
|
||||
failedMessage = messageRecord.isOutgoing() ? context.getString(R.string.ConversationItem_cant_download_video_you_will_need_to_send_it_again)
|
||||
: context.getString(R.string.ConversationItem_cant_download_video_s_will_need_to_send_it_again, messageRecord.getIndividualRecipient().getShortDisplayName(context));
|
||||
: context.getString(R.string.ConversationItem_cant_download_video_s_will_need_to_send_it_again, messageRecord.getFromRecipient().getShortDisplayName(context));
|
||||
} else {
|
||||
failedMessage = messageRecord.isOutgoing() ? context.getString(R.string.ConversationItem_cant_download_message_you_will_need_to_send_it_again)
|
||||
: context.getString(R.string.ConversationItem_cant_download_message_s_will_need_to_send_it_again, messageRecord.getIndividualRecipient().getShortDisplayName(context));
|
||||
: context.getString(R.string.ConversationItem_cant_download_message_s_will_need_to_send_it_again, messageRecord.getFromRecipient().getShortDisplayName(context));
|
||||
}
|
||||
|
||||
new MaterialAlertDialogBuilder(getContext())
|
||||
|
@ -2479,7 +2479,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
}
|
||||
} else if (!messageRecord.isOutgoing() && messageRecord.isIdentityMismatchFailure()) {
|
||||
if (eventListener != null) {
|
||||
eventListener.onIncomingIdentityMismatchClicked(messageRecord.getIndividualRecipient().getId());
|
||||
eventListener.onIncomingIdentityMismatchClicked(messageRecord.getFromRecipient().getId());
|
||||
}
|
||||
} else if (messageRecord.isPendingInsecureSmsFallback()) {
|
||||
handleMessageApproval();
|
||||
|
@ -2605,7 +2605,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo
|
|||
messageRecord.getId());
|
||||
} else {
|
||||
ApplicationDependencies.getJobManager().add(new SmsSendJob(messageRecord.getId(),
|
||||
messageRecord.getIndividualRecipient()));
|
||||
messageRecord.getToRecipient()));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -3997,13 +3997,7 @@ public class ConversationParentFragment extends Fragment
|
|||
|
||||
MessageRecord messageRecord = conversationMessage.getMessageRecord();
|
||||
|
||||
Recipient author;
|
||||
|
||||
if (messageRecord.isOutgoing()) {
|
||||
author = Recipient.self();
|
||||
} else {
|
||||
author = messageRecord.getIndividualRecipient();
|
||||
}
|
||||
Recipient author = messageRecord.getFromRecipient();
|
||||
|
||||
if (messageRecord.isMms() && !((MmsMessageRecord) messageRecord).getSharedContacts().isEmpty()) {
|
||||
Contact contact = ((MmsMessageRecord) messageRecord).getSharedContacts().get(0);
|
||||
|
|
|
@ -157,10 +157,10 @@ public final class ConversationUpdateItem extends FrameLayout
|
|||
this.conversationRecipient = conversationRecipient;
|
||||
this.isMessageRequestAccepted = isMessageRequestAccepted;
|
||||
|
||||
senderObserver.observe(lifecycleOwner, messageRecord.getIndividualRecipient());
|
||||
senderObserver.observe(lifecycleOwner, messageRecord.getFromRecipient());
|
||||
|
||||
if (conversationRecipient.isActiveGroup() &&
|
||||
(messageRecord.isGroupCall() || messageRecord.isCollapsedGroupV2JoinUpdate() || messageRecord.isGroupV2JoinRequest(messageRecord.getIndividualRecipient().getServiceId().orElse(null)))) {
|
||||
(messageRecord.isGroupCall() || messageRecord.isCollapsedGroupV2JoinUpdate() || messageRecord.isGroupV2JoinRequest(messageRecord.getFromRecipient().getServiceId().orElse(null)))) {
|
||||
groupObserver.observe(lifecycleOwner, conversationRecipient);
|
||||
groupData.observe(lifecycleOwner, conversationRecipient);
|
||||
} else {
|
||||
|
@ -437,7 +437,7 @@ public final class ConversationUpdateItem extends FrameLayout
|
|||
actionButton.setVisibility(VISIBLE);
|
||||
actionButton.setOnClickListener(v -> {
|
||||
if (batchSelected.isEmpty() && eventListener != null) {
|
||||
eventListener.onSafetyNumberLearnMoreClicked(conversationMessage.getMessageRecord().getIndividualRecipient());
|
||||
eventListener.onSafetyNumberLearnMoreClicked(conversationMessage.getMessageRecord().getFromRecipient());
|
||||
}
|
||||
});
|
||||
} else if (conversationMessage.getMessageRecord().isGroupCall()) {
|
||||
|
@ -507,15 +507,15 @@ public final class ConversationUpdateItem extends FrameLayout
|
|||
actionButton.setVisibility(VISIBLE);
|
||||
actionButton.setOnClickListener(v -> {
|
||||
if (batchSelected.isEmpty() && eventListener != null) {
|
||||
eventListener.onBadDecryptLearnMoreClicked(conversationMessage.getMessageRecord().getRecipient().getId());
|
||||
eventListener.onBadDecryptLearnMoreClicked(conversationMessage.getMessageRecord().getFromRecipient().getId());
|
||||
}
|
||||
});
|
||||
} else if (conversationMessage.getMessageRecord().isChangeNumber() && conversationMessage.getMessageRecord().getIndividualRecipient().isSystemContact()) {
|
||||
} else if (conversationMessage.getMessageRecord().isChangeNumber() && conversationMessage.getMessageRecord().getFromRecipient().isSystemContact()) {
|
||||
actionButton.setText(R.string.ConversationUpdateItem_update_contact);
|
||||
actionButton.setVisibility(VISIBLE);
|
||||
actionButton.setOnClickListener(v -> {
|
||||
if (batchSelected.isEmpty() && eventListener != null) {
|
||||
eventListener.onChangeNumberUpdateContact(conversationMessage.getMessageRecord().getIndividualRecipient());
|
||||
eventListener.onChangeNumberUpdateContact(conversationMessage.getMessageRecord().getFromRecipient());
|
||||
}
|
||||
});
|
||||
} else if (shouldShowBlockRequestAction(conversationMessage.getMessageRecord())) {
|
||||
|
@ -523,7 +523,7 @@ public final class ConversationUpdateItem extends FrameLayout
|
|||
actionButton.setVisibility(VISIBLE);
|
||||
actionButton.setOnClickListener(v -> {
|
||||
if (batchSelected.isEmpty() && eventListener != null) {
|
||||
eventListener.onBlockJoinRequest(conversationMessage.getMessageRecord().getIndividualRecipient());
|
||||
eventListener.onBlockJoinRequest(conversationMessage.getMessageRecord().getFromRecipient());
|
||||
}
|
||||
});
|
||||
} else if (conversationMessage.getMessageRecord().isBoostRequest()) {
|
||||
|
@ -557,7 +557,7 @@ public final class ConversationUpdateItem extends FrameLayout
|
|||
actionButton.setVisibility(VISIBLE);
|
||||
actionButton.setOnClickListener(v -> {
|
||||
if (batchSelected.isEmpty() && eventListener != null) {
|
||||
eventListener.onSendPaymentClicked(conversationMessage.getMessageRecord().getIndividualRecipient().getId());
|
||||
eventListener.onSendPaymentClicked(conversationMessage.getMessageRecord().getFromRecipient().getId());
|
||||
}
|
||||
});
|
||||
} else{
|
||||
|
@ -567,7 +567,7 @@ public final class ConversationUpdateItem extends FrameLayout
|
|||
}
|
||||
|
||||
private boolean shouldShowBlockRequestAction(MessageRecord messageRecord) {
|
||||
Recipient toBlock = messageRecord.getIndividualRecipient();
|
||||
Recipient toBlock = messageRecord.getFromRecipient();
|
||||
|
||||
if (!toBlock.hasServiceId() || !groupData.isSelfAdmin() || groupData.isBanned(toBlock) || groupData.isFullMember(toBlock)) {
|
||||
return false;
|
||||
|
|
|
@ -191,15 +191,15 @@ final class MenuState {
|
|||
boolean isDisplayingMessageRequest,
|
||||
boolean isNonAdminInAnnouncementGroup)
|
||||
{
|
||||
return !actionMessage &&
|
||||
!isNonAdminInAnnouncementGroup &&
|
||||
!messageRecord.isRemoteDelete() &&
|
||||
!messageRecord.isPending() &&
|
||||
!messageRecord.isFailed() &&
|
||||
!isDisplayingMessageRequest &&
|
||||
messageRecord.isSecure() &&
|
||||
return !actionMessage &&
|
||||
!isNonAdminInAnnouncementGroup &&
|
||||
!messageRecord.isRemoteDelete() &&
|
||||
!messageRecord.isPending() &&
|
||||
!messageRecord.isFailed() &&
|
||||
!isDisplayingMessageRequest &&
|
||||
messageRecord.isSecure() &&
|
||||
(!conversationRecipient.isGroup() || conversationRecipient.isActiveGroup()) &&
|
||||
!messageRecord.getRecipient().isBlocked() &&
|
||||
!messageRecord.getFromRecipient().isBlocked() &&
|
||||
!conversationRecipient.isReleaseNotes();
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,6 @@ import org.signal.libsignal.protocol.SignalProtocolAddress;
|
|||
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock;
|
||||
import org.thoughtcrime.securesms.crypto.storage.SignalIdentityKeyStore;
|
||||
import org.thoughtcrime.securesms.database.IdentityTable;
|
||||
import org.thoughtcrime.securesms.database.MessageTable;
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch;
|
||||
|
@ -203,7 +202,7 @@ public final class SafetyNumberChangeRepository {
|
|||
if (messageRecord.isMms()) {
|
||||
SignalDatabase.messages().removeMismatchedIdentity(messageRecord.getId(), id, identityKey);
|
||||
|
||||
if (messageRecord.getRecipient().isDistributionList() || messageRecord.getRecipient().isPushGroup()) {
|
||||
if (messageRecord.getToRecipient().isDistributionList() || messageRecord.getToRecipient().isPushGroup()) {
|
||||
resendIds.add(id);
|
||||
} else {
|
||||
MessageSender.resend(context, messageRecord);
|
||||
|
@ -216,7 +215,7 @@ public final class SafetyNumberChangeRepository {
|
|||
}
|
||||
|
||||
if (Util.hasItems(resendIds)) {
|
||||
if (messageRecord.getRecipient().isPushGroup()) {
|
||||
if (messageRecord.getToRecipient().isPushGroup()) {
|
||||
MessageSender.resendGroupMessage(context, messageRecord, resendIds);
|
||||
} else {
|
||||
MessageSender.resendDistributionList(context, messageRecord, resendIds);
|
||||
|
|
|
@ -88,7 +88,7 @@ class CallTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTabl
|
|||
val messageType: Long = Call.getMessageType(type, direction, event)
|
||||
|
||||
writableDatabase.withinTransaction {
|
||||
val result = SignalDatabase.messages.insertCallLog(peer, messageType, timestamp)
|
||||
val result = SignalDatabase.messages.insertCallLog(peer, messageType, timestamp, direction == Direction.OUTGOING)
|
||||
|
||||
val values = contentValuesOf(
|
||||
CALL_ID to callId,
|
||||
|
|
|
@ -9,35 +9,30 @@ import org.thoughtcrime.securesms.util.LRUCache;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class EarlyReceiptCache {
|
||||
public class EarlyDeliveryReceiptCache {
|
||||
|
||||
private static final String TAG = Log.tag(EarlyReceiptCache.class);
|
||||
private static final String TAG = Log.tag(EarlyDeliveryReceiptCache.class);
|
||||
|
||||
private final LRUCache<Long, Map<RecipientId, Receipt>> cache = new LRUCache<>(100);
|
||||
private final String name;
|
||||
|
||||
public EarlyReceiptCache(@NonNull String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public synchronized void increment(long timestamp, @NonNull RecipientId origin, long receiptTimestamp) {
|
||||
Map<RecipientId, Receipt> receipts = cache.get(timestamp);
|
||||
public synchronized void increment(long targetTimestamp, @NonNull RecipientId receiptAuthor, long receiptSentTimestamp) {
|
||||
Map<RecipientId, Receipt> receipts = cache.get(targetTimestamp);
|
||||
|
||||
if (receipts == null) {
|
||||
receipts = new HashMap<>();
|
||||
}
|
||||
|
||||
Receipt receipt = receipts.get(origin);
|
||||
Receipt receipt = receipts.get(receiptAuthor);
|
||||
|
||||
if (receipt != null) {
|
||||
receipt.count++;
|
||||
receipt.timestamp = receiptTimestamp;
|
||||
receipt.timestamp = receiptSentTimestamp;
|
||||
} else {
|
||||
receipt = new Receipt(1, receiptTimestamp);
|
||||
receipt = new Receipt(1, receiptSentTimestamp);
|
||||
}
|
||||
receipts.put(origin, receipt);
|
||||
receipts.put(receiptAuthor, receipt);
|
||||
|
||||
cache.put(timestamp, receipts);
|
||||
cache.put(targetTimestamp, receipts);
|
||||
}
|
||||
|
||||
public synchronized Map<RecipientId, Receipt> remove(long timestamp) {
|
||||
|
@ -45,7 +40,7 @@ public class EarlyReceiptCache {
|
|||
return receipts != null ? receipts : new HashMap<>();
|
||||
}
|
||||
|
||||
public class Receipt {
|
||||
public static class Receipt {
|
||||
private long count;
|
||||
private long timestamp;
|
||||
|
|
@ -1275,7 +1275,7 @@ class GroupTable(context: Context?, databaseHelper: SignalDatabase?) : DatabaseT
|
|||
SELECT ${MessageTable.TABLE_NAME}.${MessageTable.DATE_RECEIVED}
|
||||
FROM ${MessageTable.TABLE_NAME}
|
||||
WHERE
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID} = ${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} AND
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.FROM_RECIPIENT_ID} = ${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} AND
|
||||
${MessageTable.STORY_TYPE} > 1
|
||||
ORDER BY ${MessageTable.TABLE_NAME}.${MessageTable.DATE_RECEIVED} DESC
|
||||
LIMIT 1
|
||||
|
|
|
@ -54,7 +54,7 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
|
|||
${MessageTable.TABLE_NAME}.${MessageTable.DATE_RECEIVED},
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.DATE_SERVER},
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.THREAD_ID},
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID},
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.FROM_RECIPIENT_ID},
|
||||
${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} as $THREAD_RECIPIENT_ID
|
||||
FROM
|
||||
${AttachmentTable.TABLE_NAME}
|
||||
|
@ -78,7 +78,7 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
|
|||
)
|
||||
) AND
|
||||
${AttachmentTable.STICKER_PACK_ID} IS NULL AND
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID} > 0 AND
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.FROM_RECIPIENT_ID} > 0 AND
|
||||
$THREAD_RECIPIENT_ID > 0
|
||||
""".toSingleLine()
|
||||
|
||||
|
@ -204,7 +204,7 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
|
|||
|
||||
return MediaRecord(
|
||||
attachment = if (attachments.isNotEmpty()) attachments[0] else null,
|
||||
recipientId = RecipientId.from(cursor.requireLong(MessageTable.RECIPIENT_ID)),
|
||||
recipientId = RecipientId.from(cursor.requireLong(MessageTable.FROM_RECIPIENT_ID)),
|
||||
threadId = cursor.requireLong(MessageTable.THREAD_ID),
|
||||
threadRecipientId = RecipientId.from(cursor.requireLong(THREAD_RECIPIENT_ID)),
|
||||
date = if (MessageTypes.isPushType(cursor.requireLong(MessageTable.TYPE))) {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -63,7 +63,7 @@ class SearchTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
private const val MESSAGES_QUERY = """
|
||||
SELECT
|
||||
${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} AS $CONVERSATION_RECIPIENT,
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID} AS $MESSAGE_RECIPIENT,
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.FROM_RECIPIENT_ID} AS $MESSAGE_RECIPIENT,
|
||||
snippet($FTS_TABLE_NAME, -1, '', '', '$SNIPPET_WRAP', 7) AS $SNIPPET,
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.DATE_RECEIVED},
|
||||
$FTS_TABLE_NAME.$THREAD_ID,
|
||||
|
@ -86,7 +86,7 @@ class SearchTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
private const val MESSAGES_FOR_THREAD_QUERY = """
|
||||
SELECT
|
||||
${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} AS $CONVERSATION_RECIPIENT,
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID} AS $MESSAGE_RECIPIENT,
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.FROM_RECIPIENT_ID} AS $MESSAGE_RECIPIENT,
|
||||
snippet($FTS_TABLE_NAME, -1, '', '', '$SNIPPET_WRAP', 7) AS $SNIPPET,
|
||||
${MessageTable.TABLE_NAME}.${MessageTable.DATE_RECEIVED},
|
||||
$FTS_TABLE_NAME.$THREAD_ID,
|
||||
|
|
|
@ -171,14 +171,14 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
|
|||
}
|
||||
}
|
||||
|
||||
fun getStoryMessagesFor(syncMessageId: MessageTable.SyncMessageId): Set<MessageId> {
|
||||
fun getStoryMessagesFor(recipientId: RecipientId, sentTimestamp: Long): Set<MessageId> {
|
||||
val messageIds = mutableSetOf<MessageId>()
|
||||
|
||||
readableDatabase.query(
|
||||
TABLE_NAME,
|
||||
arrayOf(MESSAGE_ID),
|
||||
"$RECIPIENT_ID = ? AND $SENT_TIMESTAMP = ?",
|
||||
SqlUtil.buildArgs(syncMessageId.recipientId, syncMessageId.timetamp),
|
||||
SqlUtil.buildArgs(recipientId, sentTimestamp),
|
||||
null,
|
||||
null,
|
||||
null
|
||||
|
@ -270,7 +270,7 @@ class StorySendTable(context: Context, databaseHelper: SignalDatabase) : Databas
|
|||
val query = """
|
||||
SELECT ${MessageTable.TABLE_NAME}.${MessageTable.ID} as $MESSAGE_ID, ${DistributionListTables.DISTRIBUTION_ID}
|
||||
FROM ${MessageTable.TABLE_NAME}
|
||||
INNER JOIN ${DistributionListTables.LIST_TABLE_NAME} ON ${DistributionListTables.LIST_TABLE_NAME}.${DistributionListTables.RECIPIENT_ID} = ${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID}
|
||||
INNER JOIN ${DistributionListTables.LIST_TABLE_NAME} ON ${DistributionListTables.LIST_TABLE_NAME}.${DistributionListTables.RECIPIENT_ID} = ${MessageTable.TABLE_NAME}.${MessageTable.TO_RECIPIENT_ID}
|
||||
WHERE ${MessageTable.DATE_SENT} = $sentTimestamp AND ${DistributionListTables.DISTRIBUTION_ID} IS NOT NULL
|
||||
""".trimIndent()
|
||||
|
||||
|
|
|
@ -91,11 +91,11 @@ public final class ThreadBodyUtil {
|
|||
|
||||
private static @NonNull String getGiftSummary(@NonNull Context context, @NonNull MessageRecord messageRecord) {
|
||||
if (messageRecord.isOutgoing()) {
|
||||
return context.getString(R.string.ThreadRecord__you_donated_for_s, messageRecord.getRecipient().getShortDisplayName(context));
|
||||
return context.getString(R.string.ThreadRecord__you_donated_for_s, messageRecord.getToRecipient().getShortDisplayName(context));
|
||||
} else if (messageRecord.getViewedReceiptCount() > 0) {
|
||||
return context.getString(R.string.ThreadRecord__you_redeemed_a_badge);
|
||||
} else {
|
||||
return context.getString(R.string.ThreadRecord__s_donated_for_you, messageRecord.getRecipient().getShortDisplayName(context));
|
||||
return context.getString(R.string.ThreadRecord__s_donated_for_you, messageRecord.getFromRecipient().getShortDisplayName(context));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ public final class ThreadBodyUtil {
|
|||
if (messageRecord.isOutgoing()) {
|
||||
return context.getString(R.string.ThreadRecord_you_sent_request);
|
||||
} else {
|
||||
return context.getString(R.string.ThreadRecord_wants_you_to_activate_payments, messageRecord.getRecipient().getShortDisplayName(context));
|
||||
return context.getString(R.string.ThreadRecord_wants_you_to_activate_payments, messageRecord.getFromRecipient().getShortDisplayName(context));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,7 +119,7 @@ public final class ThreadBodyUtil {
|
|||
if (messageRecord.isOutgoing()) {
|
||||
return context.getString(R.string.ThreadRecord_you_activated_payments);
|
||||
} else {
|
||||
return context.getString(R.string.ThreadRecord_can_accept_payments, messageRecord.getRecipient().getShortDisplayName(context));
|
||||
return context.getString(R.string.ThreadRecord_can_accept_payments, messageRecord.getFromRecipient().getShortDisplayName(context));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1359,6 +1359,11 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
}
|
||||
|
||||
private fun update(threadId: Long, unarchive: Boolean, allowDeletion: Boolean, notifyListeners: Boolean): Boolean {
|
||||
if (threadId == -1L) {
|
||||
Log.d(TAG, "Skipping update for threadId -1")
|
||||
return false
|
||||
}
|
||||
|
||||
val meaningfulMessages = messages.hasMeaningfulMessage(threadId)
|
||||
|
||||
val isPinned = getPinnedThreadIds().contains(threadId)
|
||||
|
@ -1581,10 +1586,10 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
}
|
||||
|
||||
private fun getExtrasFor(record: MessageRecord, body: ThreadBody): Extra? {
|
||||
val threadRecipient = if (record.isOutgoing) record.recipient else getRecipientForThreadId(record.threadId)
|
||||
val threadRecipient = getRecipientForThreadId(record.threadId)
|
||||
val messageRequestAccepted = RecipientUtil.isMessageRequestAccepted(record.threadId, threadRecipient)
|
||||
val isHidden = threadRecipient?.isHidden ?: false
|
||||
val individualRecipientId = record.individualRecipient.id
|
||||
val authorId = record.fromRecipient.id
|
||||
|
||||
if (!messageRequestAccepted && threadRecipient != null) {
|
||||
if (threadRecipient.isPushGroup) {
|
||||
|
@ -1594,46 +1599,46 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
|
|||
val from = RecipientId.from(ServiceId.from(inviteAddState.addedOrInvitedBy))
|
||||
return if (inviteAddState.isInvited) {
|
||||
Log.i(TAG, "GV2 invite message request from $from")
|
||||
Extra.forGroupV2invite(from, individualRecipientId)
|
||||
Extra.forGroupV2invite(from, authorId)
|
||||
} else {
|
||||
Log.i(TAG, "GV2 message request from $from")
|
||||
Extra.forGroupMessageRequest(from, individualRecipientId)
|
||||
Extra.forGroupMessageRequest(from, authorId)
|
||||
}
|
||||
}
|
||||
|
||||
Log.w(TAG, "Falling back to unknown message request state for GV2 message")
|
||||
return Extra.forMessageRequest(individualRecipientId)
|
||||
return Extra.forMessageRequest(authorId)
|
||||
} else {
|
||||
val recipientId = messages.getGroupAddedBy(record.threadId)
|
||||
if (recipientId != null) {
|
||||
return Extra.forGroupMessageRequest(recipientId, individualRecipientId)
|
||||
return Extra.forGroupMessageRequest(recipientId, authorId)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Extra.forMessageRequest(individualRecipientId, isHidden)
|
||||
return Extra.forMessageRequest(authorId, isHidden)
|
||||
}
|
||||
}
|
||||
|
||||
val extras: Extra? = if (record.isScheduled()) {
|
||||
Extra.forScheduledMessage(individualRecipientId)
|
||||
Extra.forScheduledMessage(authorId)
|
||||
} else if (record.isRemoteDelete) {
|
||||
Extra.forRemoteDelete(individualRecipientId)
|
||||
Extra.forRemoteDelete(authorId)
|
||||
} else if (record.isViewOnce) {
|
||||
Extra.forViewOnce(individualRecipientId)
|
||||
Extra.forViewOnce(authorId)
|
||||
} else if (record.isMms && (record as MmsMessageRecord).slideDeck.stickerSlide != null) {
|
||||
val slide: StickerSlide = record.slideDeck.stickerSlide!!
|
||||
Extra.forSticker(slide.emoji, individualRecipientId)
|
||||
Extra.forSticker(slide.emoji, authorId)
|
||||
} else if (record.isMms && (record as MmsMessageRecord).slideDeck.slides.size > 1) {
|
||||
Extra.forAlbum(individualRecipientId)
|
||||
Extra.forAlbum(authorId)
|
||||
} else if (threadRecipient != null && threadRecipient.isGroup) {
|
||||
Extra.forDefault(individualRecipientId)
|
||||
Extra.forDefault(authorId)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
return if (record.messageRanges != null) {
|
||||
val bodyRanges = record.requireMessageRanges().adjustBodyRanges(body.bodyAdjustments)!!
|
||||
extras?.copy(bodyRanges = bodyRanges.serialize()) ?: Extra.forBodyRanges(bodyRanges, individualRecipientId)
|
||||
extras?.copy(bodyRanges = bodyRanges.serialize()) ?: Extra.forBodyRanges(bodyRanges, authorId)
|
||||
} else {
|
||||
extras
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.thoughtcrime.securesms.database.helpers.migration.V181_ThreadTableFor
|
|||
import org.thoughtcrime.securesms.database.helpers.migration.V182_CallTableMigration
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V183_CallLinkTableMigration
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V184_CallLinkReplaceIndexMigration
|
||||
import org.thoughtcrime.securesms.database.helpers.migration.V185_MessageRecipientsMigration
|
||||
|
||||
/**
|
||||
* Contains all of the database migrations for [SignalDatabase]. Broken into a separate file for cleanliness.
|
||||
|
@ -48,7 +49,7 @@ object SignalDatabaseMigrations {
|
|||
|
||||
val TAG: String = Log.tag(SignalDatabaseMigrations.javaClass)
|
||||
|
||||
const val DATABASE_VERSION = 184
|
||||
const val DATABASE_VERSION = 185
|
||||
|
||||
@JvmStatic
|
||||
fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
|
@ -195,6 +196,10 @@ object SignalDatabaseMigrations {
|
|||
if (oldVersion < 184) {
|
||||
V184_CallLinkReplaceIndexMigration.migrate(context, db, oldVersion, newVersion)
|
||||
}
|
||||
|
||||
if (oldVersion < 185) {
|
||||
V185_MessageRecipientsMigration.migrate(context, db, oldVersion, newVersion)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
|
|
|
@ -0,0 +1,285 @@
|
|||
package org.thoughtcrime.securesms.database.helpers.migration
|
||||
|
||||
import android.app.Application
|
||||
import android.preference.PreferenceManager
|
||||
import net.zetetic.database.sqlcipher.SQLiteDatabase
|
||||
import org.signal.core.util.SqlUtil
|
||||
import org.signal.core.util.Stopwatch
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.signal.core.util.readToList
|
||||
import org.signal.core.util.readToSingleInt
|
||||
import org.signal.core.util.readToSingleObject
|
||||
import org.signal.core.util.requireLong
|
||||
import org.signal.core.util.requireNonNullString
|
||||
import org.signal.core.util.requireString
|
||||
import org.signal.core.util.toSingleLine
|
||||
import org.thoughtcrime.securesms.database.KeyValueDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.whispersystems.signalservice.api.push.ACI
|
||||
|
||||
/**
|
||||
* Our current column setup for knowing is the the sender/receiver of a message is both confusing and non-optimal from a performance perspective.
|
||||
* This moves to a world where instead of tracking a single recipient, we track two: a sender and receiver.
|
||||
*/
|
||||
object V185_MessageRecipientsMigration : SignalDatabaseMigration {
|
||||
|
||||
private val TAG = Log.tag(V185_MessageRecipientsMigration::class.java)
|
||||
|
||||
private val outgoingClause = "(" + listOf(21, 23, 22, 24, 25, 26, 2, 11)
|
||||
.map { "type & ${0x1F} = $it" }
|
||||
.joinToString(separator = " OR ") + ")"
|
||||
|
||||
override fun migrate(context: Application, db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
|
||||
val stopwatch = Stopwatch("migration")
|
||||
|
||||
val selfId: RecipientId? = getSelfId(db)
|
||||
|
||||
if (selfId == null) {
|
||||
val messageCount = db.rawQuery("SELECT COUNT(*) FROM message").readToSingleInt()
|
||||
if (messageCount == 0) {
|
||||
Log.i(TAG, "Could not find ourselves in the DB! Assuming this is an install that hasn't been registered yet.")
|
||||
} else {
|
||||
throw IllegalStateException("Could not find ourselves in the recipient table, but messages exist in the message table!")
|
||||
}
|
||||
}
|
||||
|
||||
stopwatch.split("get-self")
|
||||
|
||||
val dependentItems: List<SqlItem> = getAllDependentItems(db, "message")
|
||||
|
||||
dependentItems.forEach { item ->
|
||||
val sql = "DROP ${item.type} IF EXISTS ${item.name}"
|
||||
Log.d(TAG, "Executing: $sql")
|
||||
db.execSQL(sql)
|
||||
}
|
||||
|
||||
stopwatch.split("drop-dependents")
|
||||
|
||||
db.execSQL(
|
||||
"""
|
||||
CREATE TABLE message_tmp (
|
||||
_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
date_sent INTEGER NOT NULL,
|
||||
date_received INTEGER NOT NULL,
|
||||
date_server INTEGER DEFAULT -1,
|
||||
thread_id INTEGER NOT NULL REFERENCES thread (_id) ON DELETE CASCADE,
|
||||
from_recipient_id INTEGER NOT NULL REFERENCES recipient (_id) ON DELETE CASCADE,
|
||||
from_device_id INTEGER,
|
||||
to_recipient_id INTEGER NOT NULL REFERENCES recipient (_id) ON DELETE CASCADE,
|
||||
type INTEGER NOT NULL,
|
||||
body TEXT,
|
||||
read INTEGER DEFAULT 0,
|
||||
ct_l TEXT,
|
||||
exp INTEGER,
|
||||
m_type INTEGER,
|
||||
m_size INTEGER,
|
||||
st INTEGER,
|
||||
tr_id TEXT,
|
||||
subscription_id INTEGER DEFAULT -1,
|
||||
receipt_timestamp INTEGER DEFAULT -1,
|
||||
delivery_receipt_count INTEGER DEFAULT 0,
|
||||
read_receipt_count INTEGER DEFAULT 0,
|
||||
viewed_receipt_count INTEGER DEFAULT 0,
|
||||
mismatched_identities TEXT DEFAULT NULL,
|
||||
network_failures TEXT DEFAULT NULL,
|
||||
expires_in INTEGER DEFAULT 0,
|
||||
expire_started INTEGER DEFAULT 0,
|
||||
notified INTEGER DEFAULT 0,
|
||||
quote_id INTEGER DEFAULT 0,
|
||||
quote_author INTEGER DEFAULT 0,
|
||||
quote_body TEXT DEFAULT NULL,
|
||||
quote_missing INTEGER DEFAULT 0,
|
||||
quote_mentions BLOB DEFAULT NULL,
|
||||
quote_type INTEGER DEFAULT 0,
|
||||
shared_contacts TEXT DEFAULT NULL,
|
||||
unidentified INTEGER DEFAULT 0,
|
||||
link_previews TEXT DEFAULT NULL,
|
||||
view_once INTEGER DEFAULT 0,
|
||||
reactions_unread INTEGER DEFAULT 0,
|
||||
reactions_last_seen INTEGER DEFAULT -1,
|
||||
remote_deleted INTEGER DEFAULT 0,
|
||||
mentions_self INTEGER DEFAULT 0,
|
||||
notified_timestamp INTEGER DEFAULT 0,
|
||||
server_guid TEXT DEFAULT NULL,
|
||||
message_ranges BLOB DEFAULT NULL,
|
||||
story_type INTEGER DEFAULT 0,
|
||||
parent_story_id INTEGER DEFAULT 0,
|
||||
export_state BLOB DEFAULT NULL,
|
||||
exported INTEGER DEFAULT 0,
|
||||
scheduled_date INTEGER DEFAULT -1
|
||||
)
|
||||
"""
|
||||
)
|
||||
stopwatch.split("create-table")
|
||||
|
||||
db.execSQL(
|
||||
"""
|
||||
INSERT INTO message_tmp
|
||||
SELECT
|
||||
_id,
|
||||
date_sent,
|
||||
date_received,
|
||||
date_server,
|
||||
thread_id,
|
||||
recipient_id,
|
||||
recipient_device_id,
|
||||
recipient_id,
|
||||
type,
|
||||
body,
|
||||
read,
|
||||
ct_l,
|
||||
exp,
|
||||
m_type,
|
||||
m_size,
|
||||
st,
|
||||
tr_id,
|
||||
subscription_id,
|
||||
receipt_timestamp,
|
||||
delivery_receipt_count,
|
||||
read_receipt_count,
|
||||
viewed_receipt_count,
|
||||
mismatched_identities,
|
||||
network_failures,
|
||||
expires_in,
|
||||
expire_started,
|
||||
notified,
|
||||
quote_id,
|
||||
quote_author,
|
||||
quote_body,
|
||||
quote_missing,
|
||||
quote_mentions,
|
||||
quote_type,
|
||||
shared_contacts,
|
||||
unidentified,
|
||||
link_previews,
|
||||
view_once,
|
||||
reactions_unread,
|
||||
reactions_last_seen,
|
||||
remote_deleted,
|
||||
mentions_self,
|
||||
notified_timestamp,
|
||||
server_guid,
|
||||
message_ranges,
|
||||
story_type,
|
||||
parent_story_id,
|
||||
export_state,
|
||||
exported,
|
||||
scheduled_date
|
||||
FROM message
|
||||
"""
|
||||
)
|
||||
stopwatch.split("copy-data")
|
||||
|
||||
// Previously, the recipient_id on an outgoing message represented who it was going to (an individual or group).
|
||||
// So if a message is outgoing, we'll set to = from, then from = self
|
||||
if (selfId != null) {
|
||||
db.execSQL(
|
||||
"""
|
||||
UPDATE message_tmp
|
||||
SET
|
||||
to_recipient_id = from_recipient_id,
|
||||
from_recipient_id = ${selfId.toLong()},
|
||||
from_device_id = 1
|
||||
WHERE $outgoingClause
|
||||
""".toSingleLine()
|
||||
)
|
||||
}
|
||||
stopwatch.split("update-data")
|
||||
|
||||
db.execSQL("DROP TABLE message")
|
||||
stopwatch.split("drop-old-table")
|
||||
|
||||
db.execSQL("ALTER TABLE message_tmp RENAME TO message")
|
||||
stopwatch.split("rename-table")
|
||||
|
||||
dependentItems.forEach { item ->
|
||||
val sql = when (item.name) {
|
||||
"mms_date_sent_index" -> "CREATE INDEX message_date_sent_from_to_thread_index ON message (date_sent, from_recipient_id, to_recipient_id, thread_id)"
|
||||
else -> item.createStatement.replace(Regex.fromLiteral("CREATE INDEX mms_"), "CREATE INDEX message_")
|
||||
}
|
||||
Log.d(TAG, "Executing: $sql")
|
||||
db.execSQL(sql)
|
||||
}
|
||||
stopwatch.split("recreate-dependents")
|
||||
|
||||
db.execSQL("PRAGMA foreign_key_check")
|
||||
stopwatch.split("fk-check")
|
||||
|
||||
stopwatch.stop(TAG)
|
||||
}
|
||||
|
||||
private fun getSelfId(db: SQLiteDatabase): RecipientId? {
|
||||
val idByAci: RecipientId? = getLocalAci(ApplicationDependencies.getApplication())?.let { aci ->
|
||||
db.rawQuery("SELECT _id FROM recipient WHERE uuid = ?", SqlUtil.buildArgs(aci))
|
||||
.readToSingleObject { RecipientId.from(it.requireLong("_id")) }
|
||||
}
|
||||
|
||||
if (idByAci != null) {
|
||||
return idByAci
|
||||
}
|
||||
|
||||
Log.w(TAG, "Failed to find by ACI! Will try by E164.")
|
||||
|
||||
val idByE164: RecipientId? = getLocalE164(ApplicationDependencies.getApplication())?.let { e164 ->
|
||||
db.rawQuery("SELECT _id FROM recipient WHERE phone = ?", SqlUtil.buildArgs(e164))
|
||||
.readToSingleObject { RecipientId.from(it.requireLong("_id")) }
|
||||
}
|
||||
|
||||
if (idByE164 == null) {
|
||||
Log.w(TAG, "Also failed to find by E164!")
|
||||
}
|
||||
|
||||
return idByE164
|
||||
}
|
||||
|
||||
private fun getLocalAci(context: Application): ACI? {
|
||||
if (KeyValueDatabase.exists(context)) {
|
||||
val keyValueDatabase = KeyValueDatabase.getInstance(context).readableDatabase
|
||||
keyValueDatabase.query("key_value", arrayOf("value"), "key = ?", SqlUtil.buildArgs("account.aci"), null, null, null).use { cursor ->
|
||||
return if (cursor.moveToFirst()) {
|
||||
ACI.parseOrNull(cursor.requireString("value"))
|
||||
} else {
|
||||
Log.w(TAG, "ACI not present in KV database!")
|
||||
null
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "Pre-KV database -- searching for ACI in shared prefs.")
|
||||
return ACI.parseOrNull(PreferenceManager.getDefaultSharedPreferences(context).getString("pref_local_uuid", null))
|
||||
}
|
||||
}
|
||||
|
||||
private fun getLocalE164(context: Application): String? {
|
||||
if (KeyValueDatabase.exists(context)) {
|
||||
val keyValueDatabase = KeyValueDatabase.getInstance(context).readableDatabase
|
||||
keyValueDatabase.query("key_value", arrayOf("value"), "key = ?", SqlUtil.buildArgs("account.e164"), null, null, null).use { cursor ->
|
||||
return if (cursor.moveToFirst()) {
|
||||
cursor.requireString("value")
|
||||
} else {
|
||||
Log.w(TAG, "E164 not present in KV database!")
|
||||
null
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.w(TAG, "Pre-KV database -- searching for E164 in shared prefs.")
|
||||
return PreferenceManager.getDefaultSharedPreferences(context).getString("pref_local_number", null)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getAllDependentItems(db: SQLiteDatabase, tableName: String): List<SqlItem> {
|
||||
return db.rawQuery("SELECT type, name, sql FROM sqlite_schema WHERE tbl_name='$tableName' AND type != 'table'").readToList { cursor ->
|
||||
SqlItem(
|
||||
type = cursor.requireNonNullString("type"),
|
||||
name = cursor.requireNonNullString("name"),
|
||||
createStatement = cursor.requireNonNullString("sql")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class SqlItem(
|
||||
val type: String,
|
||||
val name: String,
|
||||
val createStatement: String
|
||||
)
|
||||
}
|
|
@ -39,7 +39,8 @@ public abstract class DisplayRecord {
|
|||
|
||||
protected final long type;
|
||||
|
||||
private final Recipient recipient;
|
||||
private final Recipient fromRecipient;
|
||||
private final Recipient toRecipient;
|
||||
private final long dateSent;
|
||||
private final long dateReceived;
|
||||
private final long threadId;
|
||||
|
@ -49,12 +50,13 @@ public abstract class DisplayRecord {
|
|||
private final int readReceiptCount;
|
||||
private final int viewReceiptCount;
|
||||
|
||||
DisplayRecord(String body, Recipient recipient, long dateSent,
|
||||
DisplayRecord(String body, Recipient fromRecipient, Recipient toRecipient, long dateSent,
|
||||
long dateReceived, long threadId, int deliveryStatus, int deliveryReceiptCount,
|
||||
long type, int readReceiptCount, int viewReceiptCount)
|
||||
{
|
||||
this.threadId = threadId;
|
||||
this.recipient = recipient;
|
||||
this.fromRecipient = fromRecipient;
|
||||
this.toRecipient = toRecipient;
|
||||
this.dateSent = dateSent;
|
||||
this.dateReceived = dateReceived;
|
||||
this.type = type;
|
||||
|
@ -97,8 +99,12 @@ public abstract class DisplayRecord {
|
|||
|
||||
public abstract SpannableString getDisplayBody(@NonNull Context context);
|
||||
|
||||
public Recipient getRecipient() {
|
||||
return recipient.live().get();
|
||||
public Recipient getFromRecipient() {
|
||||
return fromRecipient.live().get();
|
||||
}
|
||||
|
||||
public Recipient getToRecipient() {
|
||||
return toRecipient.live().get();
|
||||
}
|
||||
|
||||
public long getDateSent() {
|
||||
|
|
|
@ -27,15 +27,15 @@ public class InMemoryMessageRecord extends MessageRecord {
|
|||
|
||||
private InMemoryMessageRecord(long id,
|
||||
String body,
|
||||
Recipient conversationRecipient,
|
||||
Recipient author,
|
||||
long threadId,
|
||||
long type)
|
||||
{
|
||||
super(id,
|
||||
body,
|
||||
conversationRecipient,
|
||||
conversationRecipient,
|
||||
author,
|
||||
1,
|
||||
author,
|
||||
System.currentTimeMillis(),
|
||||
System.currentTimeMillis(),
|
||||
System.currentTimeMillis(),
|
||||
|
@ -170,8 +170,8 @@ public class InMemoryMessageRecord extends MessageRecord {
|
|||
* Useful for create an empty message record when one is needed.
|
||||
*/
|
||||
public static final class ForceConversationBubble extends InMemoryMessageRecord {
|
||||
public ForceConversationBubble(Recipient conversationRecipient, long threadId) {
|
||||
super(FORCE_BUBBLE_ID, "", conversationRecipient, threadId, 0);
|
||||
public ForceConversationBubble(Recipient author, long threadId) {
|
||||
super(FORCE_BUBBLE_ID, "", author, threadId, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,9 +72,9 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
|
|||
private final long scheduledDate;
|
||||
|
||||
public MediaMmsMessageRecord(long id,
|
||||
Recipient conversationRecipient,
|
||||
Recipient individualRecipient,
|
||||
int recipientDeviceId,
|
||||
Recipient fromRecipient,
|
||||
int fromDeviceId,
|
||||
Recipient toRecipient,
|
||||
long dateSent,
|
||||
long dateReceived,
|
||||
long dateServer,
|
||||
|
@ -108,7 +108,7 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
|
|||
@Nullable CallTable.Call call,
|
||||
long scheduledDate)
|
||||
{
|
||||
super(id, body, conversationRecipient, individualRecipient, recipientDeviceId, dateSent,
|
||||
super(id, body, fromRecipient, fromDeviceId, toRecipient, dateSent,
|
||||
dateReceived, dateServer, threadId, Status.STATUS_NONE, deliveryReceiptCount, mailbox, mismatches, failures,
|
||||
subscriptionId, expiresIn, expireStarted, viewOnce, slideDeck,
|
||||
readReceiptCount, quote, contacts, linkPreviews, unidentified, reactions, remoteDelete, notifiedTimestamp, viewedReceiptCount, receiptTimestamp,
|
||||
|
@ -205,14 +205,14 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
|
|||
}
|
||||
|
||||
public @NonNull MediaMmsMessageRecord withReactions(@NonNull List<ReactionRecord> reactions) {
|
||||
return new MediaMmsMessageRecord(getId(), getRecipient(), getIndividualRecipient(), getRecipientDeviceId(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
|
||||
return new MediaMmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
|
||||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
|
||||
getReadReceiptCount(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), reactions, isRemoteDelete(), mentionsSelf,
|
||||
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate());
|
||||
}
|
||||
|
||||
public @NonNull MediaMmsMessageRecord withoutQuote() {
|
||||
return new MediaMmsMessageRecord(getId(), getRecipient(), getIndividualRecipient(), getRecipientDeviceId(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
|
||||
return new MediaMmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
|
||||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
|
||||
getReadReceiptCount(), null, getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
|
||||
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate());
|
||||
|
@ -233,14 +233,14 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
|
|||
List<DatabaseAttachment> slideAttachments = attachments.stream().filter(a -> !contactAttachments.contains(a)).filter(a -> !linkPreviewAttachments.contains(a)).collect(Collectors.toList());
|
||||
SlideDeck slideDeck = MessageTable.MmsReader.buildSlideDeck(context, slideAttachments);
|
||||
|
||||
return new MediaMmsMessageRecord(getId(), getRecipient(), getIndividualRecipient(), getRecipientDeviceId(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), slideDeck,
|
||||
return new MediaMmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), slideDeck,
|
||||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
|
||||
getReadReceiptCount(), quote, contacts, linkPreviews, isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
|
||||
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), getCall(), getScheduledDate());
|
||||
}
|
||||
|
||||
public @NonNull MediaMmsMessageRecord withPayment(@NonNull Payment payment) {
|
||||
return new MediaMmsMessageRecord(getId(), getRecipient(), getIndividualRecipient(), getRecipientDeviceId(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
|
||||
return new MediaMmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
|
||||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
|
||||
getReadReceiptCount(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
|
||||
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), payment, getCall(), getScheduledDate());
|
||||
|
@ -248,7 +248,7 @@ public class MediaMmsMessageRecord extends MmsMessageRecord {
|
|||
|
||||
|
||||
public @NonNull MediaMmsMessageRecord withCall(@Nullable CallTable.Call call) {
|
||||
return new MediaMmsMessageRecord(getId(), getRecipient(), getIndividualRecipient(), getRecipientDeviceId(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
|
||||
return new MediaMmsMessageRecord(getId(), getFromRecipient(), getFromDeviceId(), getToRecipient(), getDateSent(), getDateReceived(), getServerTimestamp(), getDeliveryReceiptCount(), getThreadId(), getBody(), getSlideDeck(),
|
||||
getType(), getIdentityKeyMismatches(), getNetworkFailures(), getSubscriptionId(), getExpiresIn(), getExpireStarted(), isViewOnce(),
|
||||
getReadReceiptCount(), getQuote(), getSharedContacts(), getLinkPreviews(), isUnidentified(), getReactions(), isRemoteDelete(), mentionsSelf,
|
||||
getNotifiedTimestamp(), getViewedReceiptCount(), getReceiptTimestamp(), getMessageRanges(), getStoryType(), getParentStoryId(), getGiftBadge(), getPayment(), call, getScheduledDate());
|
||||
|
|
|
@ -89,9 +89,8 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
|
||||
private static final String TAG = Log.tag(MessageRecord.class);
|
||||
|
||||
private final Recipient individualRecipient;
|
||||
private final int recipientDeviceId;
|
||||
private final long id;
|
||||
private final int authorDeviceId;
|
||||
private final Set<IdentityKeyMismatch> mismatches;
|
||||
private final Set<NetworkFailure> networkFailures;
|
||||
private final int subscriptionId;
|
||||
|
@ -106,8 +105,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
|
||||
protected Boolean isJumboji = null;
|
||||
|
||||
MessageRecord(long id, String body, Recipient conversationRecipient,
|
||||
Recipient individualRecipient, int recipientDeviceId,
|
||||
MessageRecord(long id, String body, Recipient fromRecipient, int fromDeviceId, Recipient toRecipient,
|
||||
long dateSent, long dateReceived, long dateServer, long threadId,
|
||||
int deliveryStatus, int deliveryReceiptCount, long type,
|
||||
Set<IdentityKeyMismatch> mismatches,
|
||||
|
@ -117,12 +115,11 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
@NonNull List<ReactionRecord> reactions, boolean remoteDelete, long notifiedTimestamp,
|
||||
int viewedReceiptCount, long receiptTimestamp)
|
||||
{
|
||||
super(body, conversationRecipient, dateSent, dateReceived,
|
||||
super(body, fromRecipient, toRecipient, dateSent, dateReceived,
|
||||
threadId, deliveryStatus, deliveryReceiptCount, type,
|
||||
readReceiptCount, viewedReceiptCount);
|
||||
this.id = id;
|
||||
this.individualRecipient = individualRecipient;
|
||||
this.recipientDeviceId = recipientDeviceId;
|
||||
this.authorDeviceId = fromDeviceId;
|
||||
this.mismatches = mismatches;
|
||||
this.networkFailures = networkFailures;
|
||||
this.subscriptionId = subscriptionId;
|
||||
|
@ -171,11 +168,11 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
} else if (isGroupUpdate() && isOutgoing()) {
|
||||
return staticUpdateDescription(context.getString(R.string.MessageRecord_you_updated_group), R.drawable.ic_update_group_16);
|
||||
} else if (isGroupUpdate()) {
|
||||
return fromRecipient(getIndividualRecipient(), r -> GroupUtil.getNonV2GroupDescription(context, getBody()).toString(r), R.drawable.ic_update_group_16);
|
||||
return fromRecipient(getFromRecipient(), r -> GroupUtil.getNonV2GroupDescription(context, getBody()).toString(r), R.drawable.ic_update_group_16);
|
||||
} else if (isGroupQuit() && isOutgoing()) {
|
||||
return staticUpdateDescription(context.getString(R.string.MessageRecord_left_group), R.drawable.ic_update_group_leave_16);
|
||||
} else if (isGroupQuit()) {
|
||||
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.ConversationItem_group_action_left, r.getDisplayName(context)), R.drawable.ic_update_group_leave_16);
|
||||
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.ConversationItem_group_action_left, r.getDisplayName(context)), R.drawable.ic_update_group_leave_16);
|
||||
} else if (isIncomingAudioCall()) {
|
||||
return staticUpdateDescription(context.getString(R.string.MessageRecord_call_message_with_date, context.getString(R.string.MessageRecord_incoming_voice_call), getCallDateString(context)), R.drawable.ic_update_audio_call_incoming_16);
|
||||
} else if (isIncomingVideoCall()) {
|
||||
|
@ -191,47 +188,47 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
} else if (isGroupCall()) {
|
||||
return getGroupCallUpdateDescription(context, getBody(), true);
|
||||
} else if (isJoined()) {
|
||||
return staticUpdateDescription(context.getString(R.string.MessageRecord_s_joined_signal, getIndividualRecipient().getDisplayName(context)), R.drawable.ic_update_group_add_16);
|
||||
return staticUpdateDescription(context.getString(R.string.MessageRecord_s_joined_signal, getFromRecipient().getDisplayName(context)), R.drawable.ic_update_group_add_16);
|
||||
} else if (isExpirationTimerUpdate()) {
|
||||
int seconds = (int)(getExpiresIn() / 1000);
|
||||
if (seconds <= 0) {
|
||||
return isOutgoing() ? staticUpdateDescription(context.getString(R.string.MessageRecord_you_disabled_disappearing_messages), R.drawable.ic_update_timer_disabled_16)
|
||||
: fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, r.getDisplayName(context)), R.drawable.ic_update_timer_disabled_16);
|
||||
: fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_s_disabled_disappearing_messages, r.getDisplayName(context)), R.drawable.ic_update_timer_disabled_16);
|
||||
}
|
||||
String time = ExpirationUtil.getExpirationDisplayValue(context, seconds);
|
||||
return isOutgoing() ? staticUpdateDescription(context.getString(R.string.MessageRecord_you_set_disappearing_message_time_to_s, time), R.drawable.ic_update_timer_16)
|
||||
: fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, r.getDisplayName(context), time), R.drawable.ic_update_timer_16);
|
||||
: fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_s_set_disappearing_message_time_to_s, r.getDisplayName(context), time), R.drawable.ic_update_timer_16);
|
||||
} else if (isIdentityUpdate()) {
|
||||
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, r.getDisplayName(context)), R.drawable.ic_update_safety_number_16);
|
||||
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, r.getDisplayName(context)), R.drawable.ic_update_safety_number_16);
|
||||
} else if (isIdentityVerified()) {
|
||||
if (isOutgoing()) return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_verified, r.getDisplayName(context)), R.drawable.ic_update_verified_16);
|
||||
else return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_verified_from_another_device, r.getDisplayName(context)), R.drawable.ic_update_verified_16);
|
||||
if (isOutgoing()) return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_verified, r.getDisplayName(context)), R.drawable.ic_update_verified_16);
|
||||
else return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_verified_from_another_device, r.getDisplayName(context)), R.drawable.ic_update_verified_16);
|
||||
} else if (isIdentityDefault()) {
|
||||
if (isOutgoing()) return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||
else return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified_from_another_device, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||
if (isOutgoing()) return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||
else return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_you_marked_your_safety_number_with_s_unverified_from_another_device, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||
} else if (isProfileChange()) {
|
||||
return staticUpdateDescription(getProfileChangeDescription(context), R.drawable.ic_update_profile_16);
|
||||
} else if (isChangeNumber()) {
|
||||
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_changed_their_phone_number, r.getDisplayName(context)), R.drawable.ic_phone_16);
|
||||
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_s_changed_their_phone_number, r.getDisplayName(context)), R.drawable.ic_phone_16);
|
||||
} else if (isBoostRequest()) {
|
||||
return staticUpdateDescription(context.getString(R.string.MessageRecord_like_this_new_feature_help_support_signal_with_a_one_time_donation), 0);
|
||||
} else if (isEndSession()) {
|
||||
if (isOutgoing()) return staticUpdateDescription(context.getString(R.string.SmsMessageRecord_secure_session_reset), R.drawable.ic_update_info_16);
|
||||
else return fromRecipient(getIndividualRecipient(), r-> context.getString(R.string.SmsMessageRecord_secure_session_reset_s, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||
else return fromRecipient(getFromRecipient(), r-> context.getString(R.string.SmsMessageRecord_secure_session_reset_s, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||
} else if (isGroupV1MigrationEvent()) {
|
||||
return getGroupMigrationEventDescription(context);
|
||||
} else if (isChatSessionRefresh()) {
|
||||
return staticUpdateDescription(context.getString(R.string.MessageRecord_chat_session_refreshed), R.drawable.ic_refresh_16);
|
||||
} else if (isBadDecryptType()) {
|
||||
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_a_message_from_s_couldnt_be_delivered, r.getDisplayName(context)), R.drawable.ic_error_outline_14);
|
||||
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_a_message_from_s_couldnt_be_delivered, r.getDisplayName(context)), R.drawable.ic_error_outline_14);
|
||||
} else if (isThreadMergeEventType()) {
|
||||
try {
|
||||
ThreadMergeEvent event = ThreadMergeEvent.parseFrom(Base64.decodeOrThrow(getBody()));
|
||||
|
||||
if (event.getPreviousE164().isEmpty()) {
|
||||
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_your_message_history_with_s_and_another_chat_has_been_merged, r.getDisplayName(context)), R.drawable.ic_thread_merge_16);
|
||||
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_your_message_history_with_s_and_another_chat_has_been_merged, r.getDisplayName(context)), R.drawable.ic_thread_merge_16);
|
||||
} else {
|
||||
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_your_message_history_with_s_and_their_number_s_has_been_merged, r.getDisplayName(context), PhoneNumberFormatter.prettyPrint(event.getPreviousE164())), R.drawable.ic_thread_merge_16);
|
||||
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_your_message_history_with_s_and_their_number_s_has_been_merged, r.getDisplayName(context), PhoneNumberFormatter.prettyPrint(event.getPreviousE164())), R.drawable.ic_thread_merge_16);
|
||||
}
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw new AssertionError(e);
|
||||
|
@ -241,9 +238,9 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
SessionSwitchoverEvent event = SessionSwitchoverEvent.parseFrom(Base64.decodeOrThrow(getBody()));
|
||||
|
||||
if (event.getE164().isEmpty()) {
|
||||
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, r.getDisplayName(context)), R.drawable.ic_update_safety_number_16);
|
||||
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_your_safety_number_with_s_has_changed, r.getDisplayName(context)), R.drawable.ic_update_safety_number_16);
|
||||
} else {
|
||||
return fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_s_belongs_to_s, PhoneNumberFormatter.prettyPrint(r.requireE164()), r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||
return fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_s_belongs_to_s, PhoneNumberFormatter.prettyPrint(r.requireE164()), r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||
}
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
throw new AssertionError(e);
|
||||
|
@ -251,13 +248,13 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
} else if (isSmsExportType()) {
|
||||
int messageResource = SignalStore.misc().getSmsExportPhase().isSmsSupported() ? R.string.MessageRecord__you_will_no_longer_be_able_to_send_sms_messages_from_signal_soon
|
||||
: R.string.MessageRecord__you_can_no_longer_send_sms_messages_in_signal;
|
||||
return fromRecipient(getIndividualRecipient(), r -> context.getString(messageResource, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||
return fromRecipient(getFromRecipient(), r -> context.getString(messageResource, r.getDisplayName(context)), R.drawable.ic_update_info_16);
|
||||
} else if (isPaymentsRequestToActivate()) {
|
||||
return isOutgoing() ? fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_you_sent_request, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments)
|
||||
: fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_wants_you_to_activate_payments, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments);
|
||||
return isOutgoing() ? fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_you_sent_request, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments)
|
||||
: fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_wants_you_to_activate_payments, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments);
|
||||
} else if (isPaymentsActivated()) {
|
||||
return isOutgoing() ? staticUpdateDescription(context.getString(R.string.MessageRecord_you_activated_payments), R.drawable.ic_card_activate_payments)
|
||||
: fromRecipient(getIndividualRecipient(), r -> context.getString(R.string.MessageRecord_can_accept_payments, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments);
|
||||
: fromRecipient(getFromRecipient(), r -> context.getString(R.string.MessageRecord_can_accept_payments, r.getShortDisplayName(context)), R.drawable.ic_card_activate_payments);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -383,11 +380,11 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
ProfileChangeDetails profileChangeDetails = ProfileChangeDetails.parseFrom(decoded);
|
||||
|
||||
if (profileChangeDetails.hasProfileNameChange()) {
|
||||
String displayName = getIndividualRecipient().getDisplayName(context);
|
||||
String displayName = getFromRecipient().getDisplayName(context);
|
||||
String newName = StringUtil.isolateBidi(ProfileName.fromSerialized(profileChangeDetails.getProfileNameChange().getNew()).toString());
|
||||
String previousName = StringUtil.isolateBidi(ProfileName.fromSerialized(profileChangeDetails.getProfileNameChange().getPrevious()).toString());
|
||||
|
||||
if (getIndividualRecipient().isSystemContact()) {
|
||||
if (getFromRecipient().isSystemContact()) {
|
||||
return context.getString(R.string.MessageRecord_changed_their_profile_name_from_to, displayName, previousName, newName);
|
||||
} else {
|
||||
return context.getString(R.string.MessageRecord_changed_their_profile_name_to, previousName, newName);
|
||||
|
@ -397,7 +394,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
Log.w(TAG, "Profile name change details could not be read", e);
|
||||
}
|
||||
|
||||
return context.getString(R.string.MessageRecord_changed_their_profile, getIndividualRecipient().getDisplayName(context));
|
||||
return context.getString(R.string.MessageRecord_changed_their_profile, getFromRecipient().getDisplayName(context));
|
||||
}
|
||||
|
||||
private UpdateDescription getGroupMigrationEventDescription(@NonNull Context context) {
|
||||
|
@ -600,12 +597,8 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
return false;
|
||||
}
|
||||
|
||||
public Recipient getIndividualRecipient() {
|
||||
return individualRecipient.live().get();
|
||||
}
|
||||
|
||||
public int getRecipientDeviceId() {
|
||||
return recipientDeviceId;
|
||||
public int getFromDeviceId() {
|
||||
return authorDeviceId;
|
||||
}
|
||||
|
||||
public long getType() {
|
||||
|
@ -625,7 +618,7 @@ public abstract class MessageRecord extends DisplayRecord {
|
|||
}
|
||||
|
||||
public boolean hasFailedWithNetworkFailures() {
|
||||
return isFailed() && ((getRecipient().isPushGroup() && hasNetworkFailures()) || !isIdentityMismatchFailure());
|
||||
return isFailed() && ((getToRecipient().isPushGroup() && hasNetworkFailures()) || !isIdentityMismatchFailure());
|
||||
}
|
||||
|
||||
public boolean isChatSessionRefresh() {
|
||||
|
|
|
@ -29,8 +29,7 @@ public abstract class MmsMessageRecord extends MessageRecord {
|
|||
|
||||
private final boolean viewOnce;
|
||||
|
||||
MmsMessageRecord(long id, String body, Recipient conversationRecipient,
|
||||
Recipient individualRecipient, int recipientDeviceId, long dateSent,
|
||||
MmsMessageRecord(long id, String body, Recipient fromRecipient, int fromDeviceId, Recipient toRecipient, long dateSent,
|
||||
long dateReceived, long dateServer, long threadId, int deliveryStatus, int deliveryReceiptCount,
|
||||
long type, Set<IdentityKeyMismatch> mismatches,
|
||||
Set<NetworkFailure> networkFailures, int subscriptionId, long expiresIn,
|
||||
|
@ -42,7 +41,7 @@ public abstract class MmsMessageRecord extends MessageRecord {
|
|||
int viewedReceiptCount, long receiptTimestamp, @NonNull StoryType storyType,
|
||||
@Nullable ParentStoryId parentStoryId, @Nullable GiftBadge giftBadge)
|
||||
{
|
||||
super(id, body, conversationRecipient, individualRecipient, recipientDeviceId,
|
||||
super(id, body, fromRecipient, fromDeviceId, toRecipient,
|
||||
dateSent, dateReceived, dateServer, threadId, deliveryStatus, deliveryReceiptCount,
|
||||
type, mismatches, networkFailures, subscriptionId, expiresIn, expireStarted, readReceiptCount,
|
||||
unidentified, reactions, remoteDelete, notifiedTimestamp, viewedReceiptCount, receiptTimestamp);
|
||||
|
|
|
@ -48,8 +48,7 @@ public class NotificationMmsMessageRecord extends MmsMessageRecord {
|
|||
private final int status;
|
||||
private final byte[] transactionId;
|
||||
|
||||
public NotificationMmsMessageRecord(long id, Recipient conversationRecipient,
|
||||
Recipient individualRecipient, int recipientDeviceId,
|
||||
public NotificationMmsMessageRecord(long id, Recipient fromRecipient, int fromDeviceId, Recipient toRecipient,
|
||||
long dateSent, long dateReceived, int deliveryReceiptCount,
|
||||
long threadId, byte[] contentLocation, long messageSize,
|
||||
long expiry, int status, byte[] transactionId, long mailbox,
|
||||
|
@ -57,7 +56,7 @@ public class NotificationMmsMessageRecord extends MmsMessageRecord {
|
|||
int viewedReceiptCount, long receiptTimestamp, @NonNull StoryType storyType,
|
||||
@Nullable ParentStoryId parentStoryId, @Nullable GiftBadge giftBadge)
|
||||
{
|
||||
super(id, "", conversationRecipient, individualRecipient, recipientDeviceId,
|
||||
super(id, "", fromRecipient, fromDeviceId, toRecipient,
|
||||
dateSent, dateReceived, -1, threadId, Status.STATUS_NONE, deliveryReceiptCount, mailbox,
|
||||
new HashSet<>(), new HashSet<>(), subscriptionId,
|
||||
0, 0, false, slideDeck, readReceiptCount, null, Collections.emptyList(), Collections.emptyList(), false,
|
||||
|
|
|
@ -115,7 +115,7 @@ class SignalSmsExportReader(
|
|||
} else if (threadRecipient != null) {
|
||||
setOf(threadRecipient.smsExportAddress())
|
||||
} else {
|
||||
setOf(record.individualRecipient.smsExportAddress())
|
||||
setOf(record.toRecipient.smsExportAddress())
|
||||
}
|
||||
|
||||
val parts: MutableList<ExportableMessage.Mms.Part> = mutableListOf()
|
||||
|
@ -138,7 +138,7 @@ class SignalSmsExportReader(
|
|||
}
|
||||
}
|
||||
|
||||
val sender: String = if (record.isOutgoing) Recipient.self().smsExportAddress() else record.individualRecipient.smsExportAddress()
|
||||
val sender: String = if (record.isOutgoing) Recipient.self().smsExportAddress() else record.fromRecipient.smsExportAddress()
|
||||
|
||||
return ExportableMessage.Mms(
|
||||
id = MessageId(record.id),
|
||||
|
|
|
@ -1290,7 +1290,7 @@ final class GroupManagerV2 {
|
|||
long threadId = MessageSender.send(context, outgoingMessage, -1, MessageSender.SendType.SIGNAL, null, null);
|
||||
return new RecipientAndThread(groupRecipient, threadId);
|
||||
} else {
|
||||
long threadId = SignalDatabase.threads().getOrCreateValidThreadId(outgoingMessage.getRecipient(), -1, outgoingMessage.getDistributionType());
|
||||
long threadId = SignalDatabase.threads().getOrCreateValidThreadId(outgoingMessage.getThreadRecipient(), -1, outgoingMessage.getDistributionType());
|
||||
try {
|
||||
long messageId = SignalDatabase.messages().insertMessageOutbox(outgoingMessage, threadId, false, null);
|
||||
SignalDatabase.messages().markAsSent(messageId, true);
|
||||
|
|
|
@ -12,7 +12,6 @@ import org.signal.core.util.logging.Log;
|
|||
import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil;
|
||||
import org.thoughtcrime.securesms.database.MessageTable;
|
||||
import org.thoughtcrime.securesms.database.MessageTable.SyncMessageId;
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException;
|
||||
import org.thoughtcrime.securesms.database.PaymentTable;
|
||||
import org.thoughtcrime.securesms.database.RecipientTable.UnidentifiedAccessMode;
|
||||
|
@ -151,11 +150,11 @@ public class IndividualSendJob extends PushSendJob {
|
|||
}
|
||||
|
||||
try {
|
||||
log(TAG, String.valueOf(message.getSentTimeMillis()), "Sending message: " + messageId + ", Recipient: " + message.getRecipient().getId() + ", Thread: " + threadId + ", Attachments: " + buildAttachmentString(message.getAttachments()));
|
||||
log(TAG, String.valueOf(message.getSentTimeMillis()), "Sending message: " + messageId + ", Recipient: " + message.getThreadRecipient().getId() + ", Thread: " + threadId + ", Attachments: " + buildAttachmentString(message.getAttachments()));
|
||||
|
||||
RecipientUtil.shareProfileIfFirstSecureMessage(message.getRecipient());
|
||||
RecipientUtil.shareProfileIfFirstSecureMessage(message.getThreadRecipient());
|
||||
|
||||
Recipient recipient = message.getRecipient().fresh();
|
||||
Recipient recipient = message.getThreadRecipient().fresh();
|
||||
byte[] profileKey = recipient.getProfileKey();
|
||||
UnidentifiedAccessMode accessMode = recipient.getUnidentifiedAccessMode();
|
||||
|
||||
|
@ -166,10 +165,9 @@ public class IndividualSendJob extends PushSendJob {
|
|||
database.markUnidentified(messageId, unidentified);
|
||||
|
||||
if (recipient.isSelf()) {
|
||||
SyncMessageId id = new SyncMessageId(recipient.getId(), message.getSentTimeMillis());
|
||||
SignalDatabase.messages().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementReadReceiptCount(id, System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementViewedReceiptCount(id, System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementDeliveryReceiptCount(message.getSentTimeMillis(), recipient.getId(), System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementReadReceiptCount(message.getSentTimeMillis(), recipient.getId(), System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementViewedReceiptCount(message.getSentTimeMillis(), recipient.getId(), System.currentTimeMillis());
|
||||
}
|
||||
|
||||
if (unidentified && accessMode == UnidentifiedAccessMode.UNKNOWN && profileKey == null) {
|
||||
|
@ -219,14 +217,14 @@ public class IndividualSendJob extends PushSendJob {
|
|||
private boolean deliver(OutgoingMessage message)
|
||||
throws IOException, InsecureFallbackApprovalException, UntrustedIdentityException, UndeliverableMessageException
|
||||
{
|
||||
if (message.getRecipient() == null) {
|
||||
if (message.getThreadRecipient() == null) {
|
||||
throw new UndeliverableMessageException("No destination address.");
|
||||
}
|
||||
|
||||
try {
|
||||
rotateSenderCertificateIfNecessary();
|
||||
|
||||
Recipient messageRecipient = message.getRecipient().fresh();
|
||||
Recipient messageRecipient = message.getThreadRecipient().fresh();
|
||||
|
||||
if (messageRecipient.isUnregistered()) {
|
||||
throw new UndeliverableMessageException(messageRecipient.getId() + " not registered!");
|
||||
|
@ -262,7 +260,7 @@ public class IndividualSendJob extends PushSendJob {
|
|||
if (message.getParentStoryId() != null) {
|
||||
try {
|
||||
MessageRecord storyRecord = SignalDatabase.messages().getMessageRecord(message.getParentStoryId().asMessageId().getId());
|
||||
Recipient storyRecipient = storyRecord.isOutgoing() ? Recipient.self() : storyRecord.getRecipient();
|
||||
Recipient storyRecipient = storyRecord.getFromRecipient();
|
||||
|
||||
SignalServiceDataMessage.StoryContext storyContext = new SignalServiceDataMessage.StoryContext(storyRecipient.requireServiceId(), storyRecord.getDateSent());
|
||||
mediaMessageBuilder.withStoryContext(storyContext);
|
||||
|
|
|
@ -240,8 +240,8 @@ public final class MmsSendJob extends SendJob {
|
|||
req.setFrom(new EncodedStringValue(SignalStore.account().getE164()));
|
||||
}
|
||||
|
||||
if (message.getRecipient().isMmsGroup()) {
|
||||
List<Recipient> members = SignalDatabase.groups().getGroupMembers(message.getRecipient().requireGroupId(), GroupTable.MemberSet.FULL_MEMBERS_EXCLUDING_SELF);
|
||||
if (message.getThreadRecipient().isMmsGroup()) {
|
||||
List<Recipient> members = SignalDatabase.groups().getGroupMembers(message.getThreadRecipient().requireGroupId(), GroupTable.MemberSet.FULL_MEMBERS_EXCLUDING_SELF);
|
||||
|
||||
for (Recipient member : members) {
|
||||
if (!member.hasSmsAddress()) {
|
||||
|
@ -255,11 +255,11 @@ public final class MmsSendJob extends SendJob {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if (!message.getRecipient().hasSmsAddress()) {
|
||||
throw new UndeliverableMessageException("Recipient did not have an SMS address! " + message.getRecipient().getId());
|
||||
if (!message.getThreadRecipient().hasSmsAddress()) {
|
||||
throw new UndeliverableMessageException("Recipient did not have an SMS address! " + message.getThreadRecipient().getId());
|
||||
}
|
||||
|
||||
req.addTo(new EncodedStringValue(message.getRecipient().requireSmsAddress()));
|
||||
req.addTo(new EncodedStringValue(message.getThreadRecipient().requireSmsAddress()));
|
||||
}
|
||||
|
||||
req.setDate(System.currentTimeMillis() / 1000);
|
||||
|
|
|
@ -154,14 +154,14 @@ public final class PushDistributionListSendJob extends PushSendJob {
|
|||
return;
|
||||
}
|
||||
|
||||
Recipient listRecipient = message.getRecipient().resolve();
|
||||
Recipient listRecipient = message.getThreadRecipient().resolve();
|
||||
|
||||
if (!listRecipient.isDistributionList()) {
|
||||
throw new MmsException("Message recipient isn't a distribution list!");
|
||||
}
|
||||
|
||||
try {
|
||||
log(TAG, String.valueOf(message.getSentTimeMillis()), "Sending message: " + messageId + ", Recipient: " + message.getRecipient().getId() + ", Attachments: " + buildAttachmentString(message.getAttachments()));
|
||||
log(TAG, String.valueOf(message.getSentTimeMillis()), "Sending message: " + messageId + ", Recipient: " + message.getThreadRecipient().getId() + ", Attachments: " + buildAttachmentString(message.getAttachments()));
|
||||
|
||||
List<Recipient> targets;
|
||||
List<RecipientId> skipped = Collections.emptyList();
|
||||
|
@ -221,7 +221,7 @@ public final class PushDistributionListSendJob extends PushSendJob {
|
|||
|
||||
Log.d(TAG, "[" + messageId + "] Sending a story message with a manifest of size " + manifestCollection.size());
|
||||
|
||||
return GroupSendUtil.sendStoryMessage(context, message.getRecipient().requireDistributionListId(), destinations, isRecipientUpdate, new MessageId(messageId), message.getSentTimeMillis(), storyMessage, manifestCollection);
|
||||
return GroupSendUtil.sendStoryMessage(context, message.getThreadRecipient().requireDistributionListId(), destinations, isRecipientUpdate, new MessageId(messageId), message.getSentTimeMillis(), storyMessage, manifestCollection);
|
||||
} catch (ServerRejectedException e) {
|
||||
throw new UndeliverableMessageException(e);
|
||||
}
|
||||
|
|
|
@ -190,7 +190,7 @@ public final class PushGroupSendJob extends PushSendJob {
|
|||
return;
|
||||
}
|
||||
|
||||
Recipient groupRecipient = message.getRecipient().resolve();
|
||||
Recipient groupRecipient = message.getThreadRecipient().resolve();
|
||||
|
||||
if (!groupRecipient.isPushGroup()) {
|
||||
throw new MmsException("Message recipient isn't a group!");
|
||||
|
@ -205,7 +205,7 @@ public final class PushGroupSendJob extends PushSendJob {
|
|||
}
|
||||
|
||||
try {
|
||||
log(TAG, String.valueOf(message.getSentTimeMillis()), "Sending message: " + messageId + ", Recipient: " + message.getRecipient().getId() + ", Thread: " + threadId + ", Attachments: " + buildAttachmentString(message.getAttachments()));
|
||||
log(TAG, String.valueOf(message.getSentTimeMillis()), "Sending message: " + messageId + ", Recipient: " + message.getThreadRecipient().getId() + ", Thread: " + threadId + ", Attachments: " + buildAttachmentString(message.getAttachments()));
|
||||
|
||||
if (!groupRecipient.resolve().isProfileSharing() && !database.isGroupQuitMessage(messageId)) {
|
||||
RecipientUtil.shareProfileIfFirstSecureMessage(groupRecipient);
|
||||
|
@ -348,13 +348,13 @@ public final class PushGroupSendJob extends PushSendJob {
|
|||
if (message.getParentStoryId() != null) {
|
||||
try {
|
||||
MessageRecord storyRecord = SignalDatabase.messages().getMessageRecord(message.getParentStoryId().asMessageId().getId());
|
||||
Recipient recipient = storyRecord.isOutgoing() ? Recipient.self() : storyRecord.getIndividualRecipient();
|
||||
Recipient storyAuthor = storyRecord.getFromRecipient();
|
||||
|
||||
destinations = destinations.stream()
|
||||
.filter(r -> r.getStoriesCapability() == Recipient.Capability.SUPPORTED)
|
||||
.collect(java.util.stream.Collectors.toList());
|
||||
|
||||
SignalServiceDataMessage.StoryContext storyContext = new SignalServiceDataMessage.StoryContext(recipient.requireServiceId(), storyRecord.getDateSent());
|
||||
SignalServiceDataMessage.StoryContext storyContext = new SignalServiceDataMessage.StoryContext(storyAuthor.requireServiceId(), storyRecord.getDateSent());
|
||||
groupMessageBuilder.withStoryContext(storyContext);
|
||||
|
||||
Optional<SignalServiceDataMessage.Reaction> reaction = getStoryReactionFor(message, storyContext);
|
||||
|
|
|
@ -139,7 +139,7 @@ public class ReactionSendJob extends BaseJob {
|
|||
ReactionTable reactionTable = SignalDatabase.reactions();
|
||||
MessageRecord message = SignalDatabase.messages().getMessageRecord(messageId.getId());
|
||||
|
||||
Recipient targetAuthor = message.isOutgoing() ? Recipient.self() : message.getIndividualRecipient();
|
||||
Recipient targetAuthor = message.getFromRecipient();
|
||||
long targetSentTimestamp = message.getDateSent();
|
||||
|
||||
if (targetAuthor.getId().equals(SignalStore.releaseChannelValues().getReleaseChannelRecipientId())) {
|
||||
|
|
|
@ -151,7 +151,7 @@ public class RemoteDeleteSendJob extends BaseJob {
|
|||
List<RecipientId> skipped = Stream.of(SetUtil.difference(possible, eligible)).map(Recipient::getId).toList();
|
||||
|
||||
boolean isForStory = message.isMms() && (((MmsMessageRecord) message).getStoryType().isStory() || ((MmsMessageRecord) message).getParentStoryId() != null);
|
||||
DistributionListId distributionListId = isForStory ? message.getRecipient().getDistributionListId().orElse(null) : null;
|
||||
DistributionListId distributionListId = isForStory ? message.getToRecipient().getDistributionListId().orElse(null) : null;
|
||||
|
||||
GroupSendJobHelper.SendResult sendResult = deliver(conversationRecipient, eligible, targetSentTimestamp, isForStory, distributionListId);
|
||||
|
||||
|
@ -167,7 +167,7 @@ public class RemoteDeleteSendJob extends BaseJob {
|
|||
|
||||
Log.i(TAG, "Completed now: " + sendResult.completed.size() + ", Skipped: " + totalSkips.size() + ", Remaining: " + recipients.size());
|
||||
|
||||
if (totalSkips.size() > 0 && message.getRecipient().isGroup()) {
|
||||
if (totalSkips.size() > 0 && message.getToRecipient().isGroup()) {
|
||||
SignalDatabase.groupReceipts().setSkipped(totalSkips, messageId);
|
||||
}
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ public class SmsReceiveJob extends BaseJob {
|
|||
}
|
||||
}
|
||||
|
||||
if (message.isPresent() && SignalStore.account().getE164() != null && message.get().getSender().equals(Recipient.self().getId())) {
|
||||
if (message.isPresent() && SignalStore.account().getE164() != null && message.get().getAuthorId().equals(Recipient.self().getId())) {
|
||||
Log.w(TAG, "Received an SMS from ourselves! Ignoring.");
|
||||
} else if (message.isPresent() && !isBlocked(message.get())) {
|
||||
Optional<InsertResult> insertResult = storeMessage(message.get());
|
||||
|
@ -145,8 +145,8 @@ public class SmsReceiveJob extends BaseJob {
|
|||
}
|
||||
|
||||
private boolean isBlocked(IncomingTextMessage message) {
|
||||
if (message.getSender() != null) {
|
||||
Recipient recipient = Recipient.resolved(message.getSender());
|
||||
if (message.getAuthorId() != null) {
|
||||
Recipient recipient = Recipient.resolved(message.getAuthorId());
|
||||
return recipient.isBlocked();
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ public class SmsReceiveJob extends BaseJob {
|
|||
}
|
||||
|
||||
private static Notification buildPreRegistrationNotification(@NonNull Context context, @NonNull IncomingTextMessage message) {
|
||||
Recipient sender = Recipient.resolved(message.getSender());
|
||||
Recipient sender = Recipient.resolved(message.getAuthorId());
|
||||
|
||||
return new NotificationCompat.Builder(context, NotificationChannels.getInstance().getMessagesChannel())
|
||||
.setStyle(new NotificationCompat.MessagingStyle(new Person.Builder()
|
||||
|
|
|
@ -89,8 +89,8 @@ public class SmsSendJob extends SendJob {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!record.getRecipient().hasSmsAddress()) {
|
||||
throw new UndeliverableMessageException("Recipient didn't have an SMS address! " + record.getRecipient().getId());
|
||||
if (!record.getToRecipient().hasSmsAddress()) {
|
||||
throw new UndeliverableMessageException("Recipient didn't have an SMS address! " + record.getToRecipient().getId());
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -100,7 +100,7 @@ public class SmsSendJob extends SendJob {
|
|||
} catch (UndeliverableMessageException ude) {
|
||||
warn(TAG, ude);
|
||||
SignalDatabase.messages().markAsSentFailed(record.getId());
|
||||
ApplicationDependencies.getMessageNotifier().notifyMessageDeliveryFailed(context, record.getRecipient(), ConversationId.fromMessageRecord(record));
|
||||
ApplicationDependencies.getMessageNotifier().notifyMessageDeliveryFailed(context, record.getToRecipient(), ConversationId.fromMessageRecord(record));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,7 +131,7 @@ public class SmsSendJob extends SendJob {
|
|||
throw new UndeliverableMessageException("Trying to send a secure SMS?");
|
||||
}
|
||||
|
||||
String recipient = message.getIndividualRecipient().requireSmsAddress();
|
||||
String recipient = message.getToRecipient().requireSmsAddress();
|
||||
|
||||
// See issue #1516 for bug report, and discussion on commits related to #4833 for problems
|
||||
// related to the original fix to #1516. This still may not be a correct fix if networks allow
|
||||
|
|
|
@ -110,15 +110,15 @@ public class SmsSentJob extends BaseJob {
|
|||
if (isMultipart) {
|
||||
Log.w(TAG, "Service connectivity problem, but not retrying due to multipart");
|
||||
database.markAsSentFailed(messageId);
|
||||
ApplicationDependencies.getMessageNotifier().notifyMessageDeliveryFailed(context, record.getRecipient(), ConversationId.forConversation(record.getThreadId()));
|
||||
ApplicationDependencies.getMessageNotifier().notifyMessageDeliveryFailed(context, record.getToRecipient(), ConversationId.forConversation(record.getThreadId()));
|
||||
} else {
|
||||
Log.w(TAG, "Service connectivity problem, requeuing...");
|
||||
ApplicationDependencies.getJobManager().add(new SmsSendJob(messageId, record.getIndividualRecipient(), runAttempt + 1));
|
||||
ApplicationDependencies.getJobManager().add(new SmsSendJob(messageId, record.getToRecipient(), runAttempt + 1));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
database.markAsSentFailed(messageId);
|
||||
ApplicationDependencies.getMessageNotifier().notifyMessageDeliveryFailed(context, record.getRecipient(), ConversationId.forConversation(record.getThreadId()));
|
||||
ApplicationDependencies.getMessageNotifier().notifyMessageDeliveryFailed(context, record.getToRecipient(), ConversationId.forConversation(record.getThreadId()));
|
||||
}
|
||||
} catch (NoSuchMessageException e) {
|
||||
Log.w(TAG, e);
|
||||
|
|
|
@ -102,7 +102,7 @@ public class LongMessageFragment extends FullScreenDialogFragment {
|
|||
if (message.get().getMessageRecord().isOutgoing()) {
|
||||
toolbar.setTitle(getString(R.string.LongMessageActivity_your_message));
|
||||
} else {
|
||||
Recipient recipient = message.get().getMessageRecord().getRecipient();
|
||||
Recipient recipient = message.get().getMessageRecord().getFromRecipient();
|
||||
String name = recipient.getDisplayName(requireContext());
|
||||
|
||||
toolbar.setTitle(getString(R.string.LongMessageActivity_message_from_s, name));
|
||||
|
@ -113,8 +113,8 @@ public class LongMessageFragment extends FullScreenDialogFragment {
|
|||
if (message.get().getMessageRecord().isOutgoing()) {
|
||||
bubble = sentBubble.get();
|
||||
colorizerView.setVisibility(View.VISIBLE);
|
||||
colorizerView.setBackground(message.get().getMessageRecord().getRecipient().getChatColors().getChatBubbleMask());
|
||||
bubble.getBackground().setColorFilter(message.get().getMessageRecord().getRecipient().getChatColors().getChatBubbleColorFilter());
|
||||
colorizerView.setBackground(message.get().getMessageRecord().getToRecipient().getChatColors().getChatBubbleMask());
|
||||
bubble.getBackground().setColorFilter(message.get().getMessageRecord().getToRecipient().getChatColors().getChatBubbleColorFilter());
|
||||
bubble.addOnLayoutChangeListener(bubbleLayoutListener);
|
||||
bubbleLayoutListener.onLayoutChange(bubble, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
} else {
|
||||
|
|
|
@ -324,7 +324,7 @@ class MediaSelectionRepository(context: Context) {
|
|||
val thread = SignalDatabase.threads.getOrCreateThreadIdFor(recipient)
|
||||
|
||||
val outgoingMessage = OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = recipient,
|
||||
body = splitBody,
|
||||
attachments = slideDeck.asAttachments(),
|
||||
sentTimeMillis = System.currentTimeMillis(),
|
||||
|
@ -370,7 +370,7 @@ class MediaSelectionRepository(context: Context) {
|
|||
}
|
||||
|
||||
val message = OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = recipient,
|
||||
body = body,
|
||||
sentTimeMillis = if (recipient.isDistributionList) distributionListPreUploadSentTimestamps.getOrPut(preUploadResults.first()) { System.currentTimeMillis() } else System.currentTimeMillis(),
|
||||
expiresIn = if (isStory) 0 else TimeUnit.SECONDS.toMillis(recipient.expiresInSeconds.toLong()),
|
||||
|
@ -401,7 +401,7 @@ class MediaSelectionRepository(context: Context) {
|
|||
storyClips.forEach {
|
||||
storyClipMessages.add(
|
||||
OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = recipient,
|
||||
body = body,
|
||||
attachments = listOf(MediaUploadRepository.asAttachment(context, it)),
|
||||
sentTimeMillis = if (recipient.isDistributionList) distributionListStoryClipsSentTimestamps.getOrPut(it.asKey()) { System.currentTimeMillis() } else System.currentTimeMillis(),
|
||||
|
|
|
@ -38,7 +38,7 @@ public final class MessageDetails {
|
|||
viewed = new TreeSet<>(RECIPIENT_COMPARATOR);
|
||||
skipped = new TreeSet<>(RECIPIENT_COMPARATOR);
|
||||
|
||||
if (conversationMessage.getMessageRecord().getRecipient().isSelf()) {
|
||||
if (conversationMessage.getMessageRecord().getToRecipient().isSelf()) {
|
||||
read.addAll(recipients);
|
||||
} else if (conversationMessage.getMessageRecord().isOutgoing()) {
|
||||
for (RecipientDeliveryStatus status : recipients) {
|
||||
|
|
|
@ -76,19 +76,19 @@ public final class MessageDetailsRepository {
|
|||
private @NonNull MessageDetails getRecipientDeliveryStatusesInternal(@NonNull MessageRecord messageRecord) {
|
||||
List<RecipientDeliveryStatus> recipients = new LinkedList<>();
|
||||
|
||||
if (!messageRecord.getRecipient().isGroup() && !messageRecord.getRecipient().isDistributionList()) {
|
||||
if (!messageRecord.getToRecipient().isGroup() && !messageRecord.getToRecipient().isDistributionList()) {
|
||||
recipients.add(new RecipientDeliveryStatus(messageRecord,
|
||||
messageRecord.getRecipient(),
|
||||
messageRecord.getToRecipient(),
|
||||
getStatusFor(messageRecord),
|
||||
messageRecord.isUnidentified(),
|
||||
messageRecord.getReceiptTimestamp(),
|
||||
getNetworkFailure(messageRecord, messageRecord.getRecipient()),
|
||||
getKeyMismatchFailure(messageRecord, messageRecord.getRecipient())));
|
||||
getNetworkFailure(messageRecord, messageRecord.getToRecipient()),
|
||||
getKeyMismatchFailure(messageRecord, messageRecord.getToRecipient())));
|
||||
} else {
|
||||
List<GroupReceiptTable.GroupReceiptInfo> receiptInfoList = SignalDatabase.groupReceipts().getGroupReceiptInfo(messageRecord.getId());
|
||||
|
||||
if (receiptInfoList.isEmpty() && messageRecord.getRecipient().isGroup()) {
|
||||
List<Recipient> group = SignalDatabase.groups().getGroupMembers(messageRecord.getRecipient().requireGroupId(), GroupTable.MemberSet.FULL_MEMBERS_EXCLUDING_SELF);
|
||||
if (receiptInfoList.isEmpty() && messageRecord.getToRecipient().isGroup()) {
|
||||
List<Recipient> group = SignalDatabase.groups().getGroupMembers(messageRecord.getToRecipient().requireGroupId(), GroupTable.MemberSet.FULL_MEMBERS_EXCLUDING_SELF);
|
||||
|
||||
for (Recipient recipient : group) {
|
||||
recipients.add(new RecipientDeliveryStatus(messageRecord,
|
||||
|
@ -99,8 +99,8 @@ public final class MessageDetailsRepository {
|
|||
getNetworkFailure(messageRecord, recipient),
|
||||
getKeyMismatchFailure(messageRecord, recipient)));
|
||||
}
|
||||
} else if (receiptInfoList.isEmpty() && messageRecord.getRecipient().isDistributionList()) {
|
||||
DistributionId distributionId = SignalDatabase.distributionLists().getDistributionId(messageRecord.getRecipient().requireDistributionListId());
|
||||
} else if (receiptInfoList.isEmpty() && messageRecord.getToRecipient().isDistributionList()) {
|
||||
DistributionId distributionId = SignalDatabase.distributionLists().getDistributionId(messageRecord.getToRecipient().requireDistributionListId());
|
||||
Set<RecipientId> recipientIds = SignalDatabase.storySends().getRecipientsForDistributionId(messageRecord.getId(), Objects.requireNonNull(distributionId));
|
||||
List<Recipient> resolved = Recipient.resolvedList(recipientIds);
|
||||
|
||||
|
|
|
@ -104,7 +104,7 @@ final class MessageHeaderViewHolder extends RecyclerView.ViewHolder implements G
|
|||
glideRequests,
|
||||
Locale.getDefault(),
|
||||
new HashSet<>(),
|
||||
conversationMessage.getMessageRecord().getRecipient(),
|
||||
conversationMessage.getMessageRecord().getToRecipient(),
|
||||
null,
|
||||
false,
|
||||
false,
|
||||
|
|
|
@ -51,7 +51,7 @@ final class RecipientViewHolder extends RecyclerView.ViewHolder {
|
|||
conflictButton.setVisibility(View.VISIBLE);
|
||||
error.setText(itemView.getContext().getString(R.string.message_details_recipient__new_safety_number));
|
||||
conflictButton.setOnClickListener(unused -> callbacks.onErrorClicked(data.getMessageRecord()));
|
||||
} else if ((data.getNetworkFailure() != null && !data.getMessageRecord().isPending()) || (!data.getMessageRecord().getRecipient().isPushGroup() && data.getMessageRecord().isFailed())) {
|
||||
} else if ((data.getNetworkFailure() != null && !data.getMessageRecord().isPending()) || (!data.getMessageRecord().getToRecipient().isPushGroup() && data.getMessageRecord().isFailed())) {
|
||||
timestamp.setVisibility(View.GONE);
|
||||
error.setVisibility(View.VISIBLE);
|
||||
conflictButton.setVisibility(View.GONE);
|
||||
|
|
|
@ -520,7 +520,7 @@ object DataMessageProcessor {
|
|||
|
||||
null
|
||||
} else {
|
||||
warn(envelope.timestamp, "[handleRemoteDelete] Invalid remote delete! deleteTime: ${envelope.serverTimestamp}, targetTime: ${targetMessage.serverTimestamp}, deleteAuthor: $senderRecipientId, targetAuthor: ${targetMessage.recipient.id}")
|
||||
warn(envelope.timestamp, "[handleRemoteDelete] Invalid remote delete! deleteTime: ${envelope.serverTimestamp}, targetTime: ${targetMessage.serverTimestamp}, deleteAuthor: $senderRecipientId, targetAuthor: ${targetMessage.fromRecipient.id}")
|
||||
null
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ import org.signal.core.util.logging.Log
|
|||
import org.signal.core.util.withinTransaction
|
||||
import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.crypto.ReentrantSessionLock
|
||||
import org.thoughtcrime.securesms.database.MessageTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.jobmanager.Job
|
||||
|
@ -318,7 +317,7 @@ class IncomingMessageObserver(private val context: Application) {
|
|||
val senderId = RecipientId.from(ServiceId.parseOrThrow(envelope.sourceUuid))
|
||||
|
||||
Log.i(TAG, "Received server receipt. Sender: $senderId, Device: ${envelope.sourceDevice}, Timestamp: ${envelope.timestamp}")
|
||||
SignalDatabase.messages.incrementDeliveryReceiptCount(MessageTable.SyncMessageId(senderId, envelope.timestamp), System.currentTimeMillis())
|
||||
SignalDatabase.messages.incrementDeliveryReceiptCount(envelope.timestamp, senderId, System.currentTimeMillis())
|
||||
SignalDatabase.messageLog.deleteEntryForRecipient(envelope.timestamp, senderId, envelope.sourceDevice)
|
||||
}
|
||||
|
||||
|
|
|
@ -1081,7 +1081,7 @@ public class MessageContentProcessor {
|
|||
return null;
|
||||
} else {
|
||||
warn(String.valueOf(content.getTimestamp()), String.format(Locale.ENGLISH, "[handleRemoteDelete] Invalid remote delete! deleteTime: %d, targetTime: %d, deleteAuthor: %s, targetAuthor: %s",
|
||||
content.getServerReceivedTimestamp(), targetMessage.getServerTimestamp(), senderRecipient.getId(), targetMessage.getRecipient().getId()));
|
||||
content.getServerReceivedTimestamp(), targetMessage.getServerTimestamp(), senderRecipient.getId(), targetMessage.getFromRecipient().getId()));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -2251,9 +2251,8 @@ public class MessageContentProcessor {
|
|||
}
|
||||
|
||||
if (recipient.isSelf()) {
|
||||
SyncMessageId id = new SyncMessageId(recipient.getId(), message.getTimestamp());
|
||||
SignalDatabase.messages().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementReadReceiptCount(id, System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementDeliveryReceiptCount(message.getTimestamp(), recipient.getId(), System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementReadReceiptCount(message.getTimestamp(), recipient.getId(), System.currentTimeMillis());
|
||||
}
|
||||
|
||||
database.setTransactionSuccessful();
|
||||
|
@ -2370,9 +2369,8 @@ public class MessageContentProcessor {
|
|||
attachments = Stream.of(allAttachments).filterNot(Attachment::isSticker).toList();
|
||||
|
||||
if (recipient.isSelf()) {
|
||||
SyncMessageId id = new SyncMessageId(recipient.getId(), message.getTimestamp());
|
||||
SignalDatabase.messages().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementReadReceiptCount(id, System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementDeliveryReceiptCount(message.getTimestamp(), recipient.getId(), System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementReadReceiptCount(message.getTimestamp(), recipient.getId(), System.currentTimeMillis());
|
||||
}
|
||||
|
||||
messageTable.setTransactionSuccessful();
|
||||
|
@ -2407,7 +2405,7 @@ public class MessageContentProcessor {
|
|||
log(envelopeTimestamp, "Synchronize sent media message for " + message.getTimestamp());
|
||||
|
||||
MessageTable database = SignalDatabase.messages();
|
||||
Recipient recipients = getSyncMessageDestination(message);
|
||||
Recipient recipient = getSyncMessageDestination(message);
|
||||
Optional<QuoteModel> quote = getValidatedQuote(message.getDataMessage().get().getQuote());
|
||||
Optional<Attachment> sticker = getStickerAttachment(message.getDataMessage().get().getSticker());
|
||||
Optional<List<Contact>> sharedContacts = getContacts(message.getDataMessage().get().getSharedContacts());
|
||||
|
@ -2423,7 +2421,7 @@ public class MessageContentProcessor {
|
|||
syncAttachments.add(sticker.get());
|
||||
}
|
||||
|
||||
OutgoingMessage mediaMessage = new OutgoingMessage(recipients,
|
||||
OutgoingMessage mediaMessage = new OutgoingMessage(recipient,
|
||||
message.getDataMessage().get().getBody().orElse(null),
|
||||
syncAttachments,
|
||||
message.getTimestamp(),
|
||||
|
@ -2445,11 +2443,11 @@ public class MessageContentProcessor {
|
|||
bodyRanges,
|
||||
-1);
|
||||
|
||||
if (recipients.getExpiresInSeconds() != message.getDataMessage().get().getExpiresInSeconds()) {
|
||||
if (recipient.getExpiresInSeconds() != message.getDataMessage().get().getExpiresInSeconds()) {
|
||||
handleSynchronizeSentExpirationUpdate(message);
|
||||
}
|
||||
|
||||
long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(recipients);
|
||||
long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(recipient);
|
||||
|
||||
long messageId;
|
||||
List<DatabaseAttachment> attachments;
|
||||
|
@ -2459,10 +2457,10 @@ public class MessageContentProcessor {
|
|||
try {
|
||||
messageId = database.insertMessageOutbox(mediaMessage, threadId, false, GroupReceiptTable.STATUS_UNKNOWN, null);
|
||||
|
||||
if (recipients.isGroup()) {
|
||||
updateGroupReceiptStatus(message, messageId, recipients.requireGroupId());
|
||||
if (recipient.isGroup()) {
|
||||
updateGroupReceiptStatus(message, messageId, recipient.requireGroupId());
|
||||
} else {
|
||||
database.markUnidentified(messageId, isUnidentified(message, recipients));
|
||||
database.markUnidentified(messageId, isUnidentified(message, recipient));
|
||||
}
|
||||
|
||||
database.markAsSent(messageId, true);
|
||||
|
@ -2481,10 +2479,10 @@ public class MessageContentProcessor {
|
|||
TimeUnit.SECONDS.toMillis(message.getDataMessage().get().getExpiresInSeconds()));
|
||||
}
|
||||
|
||||
if (recipients.isSelf()) {
|
||||
SyncMessageId id = new SyncMessageId(recipients.getId(), message.getTimestamp());
|
||||
SignalDatabase.messages().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementReadReceiptCount(id, System.currentTimeMillis());
|
||||
if (recipient.isSelf()) {
|
||||
SyncMessageId id = new SyncMessageId(recipient.getId(), message.getTimestamp());
|
||||
SignalDatabase.messages().incrementDeliveryReceiptCount(message.getTimestamp(), recipient.getId(), System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementReadReceiptCount(message.getTimestamp(), recipient.getId(), System.currentTimeMillis());
|
||||
}
|
||||
|
||||
database.setTransactionSuccessful();
|
||||
|
@ -2672,9 +2670,8 @@ public class MessageContentProcessor {
|
|||
}
|
||||
|
||||
if (recipient.isSelf()) {
|
||||
SyncMessageId id = new SyncMessageId(recipient.getId(), message.getTimestamp());
|
||||
SignalDatabase.messages().incrementDeliveryReceiptCount(id, System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementReadReceiptCount(id, System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementDeliveryReceiptCount(message.getTimestamp(), recipient.getId(), System.currentTimeMillis());
|
||||
SignalDatabase.messages().incrementReadReceiptCount(message.getTimestamp(), recipient.getId(), System.currentTimeMillis());
|
||||
}
|
||||
|
||||
return threadId;
|
||||
|
@ -2825,20 +2822,16 @@ public class MessageContentProcessor {
|
|||
|
||||
log(TAG, "Processing viewed receipts. Sender: " + senderRecipient.getId() + ", Device: " + content.getSenderDevice() + ", Only Stories: " + (!readReceipts && storyViewedReceipts) + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
|
||||
|
||||
List<SyncMessageId> ids = Stream.of(message.getTimestamps())
|
||||
.map(t -> new SyncMessageId(senderRecipient.getId(), t))
|
||||
.toList();
|
||||
|
||||
final Collection<SyncMessageId> unhandled;
|
||||
final Set<Long> unhandled;
|
||||
if (readReceipts && storyViewedReceipts) {
|
||||
unhandled = SignalDatabase.messages().incrementViewedReceiptCounts(ids, content.getTimestamp());
|
||||
unhandled = SignalDatabase.messages().incrementViewedReceiptCounts(message.getTimestamps(), senderRecipient.getId(), content.getTimestamp());
|
||||
} else if (readReceipts) {
|
||||
unhandled = SignalDatabase.messages().incrementViewedNonStoryReceiptCounts(ids, content.getTimestamp());
|
||||
unhandled = SignalDatabase.messages().incrementViewedNonStoryReceiptCounts(message.getTimestamps(), senderRecipient.getId(), content.getTimestamp());
|
||||
} else {
|
||||
unhandled = SignalDatabase.messages().incrementViewedStoryReceiptCounts(ids, content.getTimestamp());
|
||||
unhandled = SignalDatabase.messages().incrementViewedStoryReceiptCounts(message.getTimestamps(), senderRecipient.getId(), content.getTimestamp());
|
||||
}
|
||||
|
||||
Set<SyncMessageId> handled = new HashSet<>(ids);
|
||||
Set<Long> handled = new HashSet<>(unhandled);
|
||||
handled.removeAll(unhandled);
|
||||
|
||||
SignalDatabase.messages().updateViewedStories(handled);
|
||||
|
@ -2846,10 +2839,10 @@ public class MessageContentProcessor {
|
|||
if (unhandled.size() > 0) {
|
||||
RecipientId selfId = Recipient.self().getId();
|
||||
|
||||
for (SyncMessageId id : unhandled) {
|
||||
warn(String.valueOf(content.getTimestamp()), "[handleViewedReceipt] Could not find matching message! timestamp: " + id.getTimetamp() + ", author: " + id.getRecipientId() + " | Receipt so associating with message from self (" + selfId + ")");
|
||||
for (long timestamp : unhandled) {
|
||||
warn(String.valueOf(content.getTimestamp()), "[handleViewedReceipt] Could not find matching message! timestamp: " + timestamp + ", author: " + senderRecipient.getId() + " | Receipt so associating with message from self (" + selfId + ")");
|
||||
if (!processingEarlyContent) {
|
||||
ApplicationDependencies.getEarlyMessageCache().store(selfId, id.getTimetamp(), content);
|
||||
ApplicationDependencies.getEarlyMessageCache().store(selfId, timestamp, content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2866,14 +2859,10 @@ public class MessageContentProcessor {
|
|||
{
|
||||
log(content.getTimestamp(), "Processing delivery receipts. Sender: " + senderRecipient.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
|
||||
|
||||
List<SyncMessageId> ids = Stream.of(message.getTimestamps())
|
||||
.map(t -> new SyncMessageId(senderRecipient.getId(), t))
|
||||
.toList();
|
||||
Set<Long> unhandled = SignalDatabase.messages().incrementDeliveryReceiptCounts(message.getTimestamps(), senderRecipient.getId(), content.getTimestamp());
|
||||
|
||||
Collection<SyncMessageId> unhandled = SignalDatabase.messages().incrementDeliveryReceiptCounts(ids, content.getTimestamp());
|
||||
|
||||
for (SyncMessageId id : unhandled) {
|
||||
warn(String.valueOf(content.getTimestamp()), "[handleDeliveryReceipt] Could not find matching message! timestamp: " + id.getTimetamp() + " author: " + id.getRecipientId());
|
||||
for (long timestamp : unhandled) {
|
||||
warn(String.valueOf(content.getTimestamp()), "[handleDeliveryReceipt] Could not find matching message! timestamp: " + timestamp + " author: " + senderRecipient.getId());
|
||||
// Early delivery receipts are special-cased in the database methods
|
||||
}
|
||||
|
||||
|
@ -2898,19 +2887,15 @@ public class MessageContentProcessor {
|
|||
|
||||
log(TAG, "Processing read receipts. Sender: " + senderRecipient.getId() + ", Device: " + content.getSenderDevice() + ", Timestamps: " + Util.join(message.getTimestamps(), ", "));
|
||||
|
||||
List<SyncMessageId> ids = Stream.of(message.getTimestamps())
|
||||
.map(t -> new SyncMessageId(senderRecipient.getId(), t))
|
||||
.toList();
|
||||
|
||||
Collection<SyncMessageId> unhandled = SignalDatabase.messages().incrementReadReceiptCounts(ids, content.getTimestamp());
|
||||
Set<Long> unhandled = SignalDatabase.messages().incrementReadReceiptCounts(message.getTimestamps(), senderRecipient.getId(), content.getTimestamp());
|
||||
|
||||
if (unhandled.size() > 0) {
|
||||
RecipientId selfId = Recipient.self().getId();
|
||||
|
||||
for (SyncMessageId id : unhandled) {
|
||||
warn(String.valueOf(content.getTimestamp()), "[handleReadReceipt] Could not find matching message! timestamp: " + id.getTimetamp() + ", author: " + id.getRecipientId() + " | Receipt, so associating with message from self (" + selfId + ")");
|
||||
for (long timestamp : unhandled) {
|
||||
warn(String.valueOf(content.getTimestamp()), "[handleReadReceipt] Could not find matching message! timestamp: " + timestamp + ", author: " + senderRecipient.getId() + " | Receipt, so associating with message from self (" + selfId + ")");
|
||||
if (!processingEarlyContent) {
|
||||
ApplicationDependencies.getEarlyMessageCache().store(selfId, id.getTimetamp(), content);
|
||||
ApplicationDependencies.getEarlyMessageCache().store(selfId, timestamp, content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ object MessageDecryptor {
|
|||
return Result.Ignore(envelope, serverDeliveredTimestamp, followUpOperations.toUnmodifiableList())
|
||||
}
|
||||
|
||||
Log.d(TAG, "${logPrefix(envelope, cipherResult)} Successfully decrypted the envelope.")
|
||||
Log.d(TAG, "${logPrefix(envelope, cipherResult)} Successfully decrypted the envelope (GUID ${envelope.serverGuid}).")
|
||||
|
||||
val validationResult: EnvelopeContentValidator.Result = EnvelopeContentValidator.validate(envelope, cipherResult.content)
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.messages
|
|||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import org.thoughtcrime.securesms.database.MessageTable.SyncMessageId
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.dependencies.ApplicationDependencies
|
||||
import org.thoughtcrime.securesms.jobs.PushProcessEarlyMessagesJob
|
||||
|
@ -39,15 +38,14 @@ object ReceiptMessageProcessor {
|
|||
) {
|
||||
log(envelope.timestamp, "Processing delivery receipts. Sender: $senderRecipientId, Device: ${metadata.sourceDeviceId}, Timestamps: ${deliveryReceipt.timestampList.joinToString(", ")}")
|
||||
|
||||
val ids = deliveryReceipt.timestampList.map { SyncMessageId(senderRecipientId, it) }
|
||||
val unhandled = SignalDatabase.messages.incrementDeliveryReceiptCounts(ids, envelope.timestamp)
|
||||
val missingTargetTimestamps: Set<Long> = SignalDatabase.messages.incrementDeliveryReceiptCounts(deliveryReceipt.timestampList, senderRecipientId, envelope.timestamp)
|
||||
|
||||
for (id in unhandled) {
|
||||
warn(envelope.timestamp, "[handleDeliveryReceipt] Could not find matching message! timestamp: ${id.timetamp} author: ${id.recipientId}")
|
||||
for (targetTimestamp in missingTargetTimestamps) {
|
||||
warn(envelope.timestamp, "[handleDeliveryReceipt] Could not find matching message! targetTimestamp: $targetTimestamp, receiptAuthor: $senderRecipientId")
|
||||
// Early delivery receipts are special-cased in the database methods
|
||||
}
|
||||
|
||||
if (unhandled.isNotEmpty()) {
|
||||
if (missingTargetTimestamps.isNotEmpty()) {
|
||||
PushProcessEarlyMessagesJob.enqueue()
|
||||
}
|
||||
|
||||
|
@ -71,21 +69,20 @@ object ReceiptMessageProcessor {
|
|||
|
||||
log(envelope.timestamp, "Processing read receipts. Sender: $senderRecipientId, Device: ${metadata.sourceDeviceId}, Timestamps: ${readReceipt.timestampList.joinToString(", ")}")
|
||||
|
||||
val ids = readReceipt.timestampList.map { SyncMessageId(senderRecipientId, it) }
|
||||
val unhandled = SignalDatabase.messages.incrementReadReceiptCounts(ids, envelope.timestamp)
|
||||
val missingTargetTimestamps: Set<Long> = SignalDatabase.messages.incrementReadReceiptCounts(readReceipt.timestampList, senderRecipientId, envelope.timestamp)
|
||||
|
||||
if (unhandled.isNotEmpty()) {
|
||||
if (missingTargetTimestamps.isNotEmpty()) {
|
||||
val selfId = Recipient.self().id
|
||||
|
||||
for (id in unhandled) {
|
||||
warn(envelope.timestamp, "[handleReadReceipt] Could not find matching message! timestamp: ${id.timetamp}, author: ${id.recipientId} | Receipt, so associating with message from self ($selfId)")
|
||||
for (targetTimestamp in missingTargetTimestamps) {
|
||||
warn(envelope.timestamp, "[handleReadReceipt] Could not find matching message! targetTimestamp: $targetTimestamp, receiptAuthor: $senderRecipientId | Receipt, so associating with message from self ($selfId)")
|
||||
if (earlyMessageCacheEntry != null) {
|
||||
ApplicationDependencies.getEarlyMessageCache().store(selfId, id.timetamp, earlyMessageCacheEntry)
|
||||
ApplicationDependencies.getEarlyMessageCache().store(selfId, targetTimestamp, earlyMessageCacheEntry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unhandled.isNotEmpty() && earlyMessageCacheEntry != null) {
|
||||
if (missingTargetTimestamps.isNotEmpty() && earlyMessageCacheEntry != null) {
|
||||
PushProcessEarlyMessagesJob.enqueue()
|
||||
}
|
||||
}
|
||||
|
@ -108,30 +105,29 @@ object ReceiptMessageProcessor {
|
|||
|
||||
log(envelope.timestamp, "Processing viewed receipts. Sender: $senderRecipientId, Device: ${metadata.sourceDeviceId}, Only Stories: ${!readReceipts}, Timestamps: ${viewedReceipt.timestampList.joinToString(", ")}")
|
||||
|
||||
val ids = viewedReceipt.timestampList.map { SyncMessageId(senderRecipientId, it) }
|
||||
|
||||
val unhandled: Collection<SyncMessageId> = if (readReceipts && storyViewedReceipts) {
|
||||
SignalDatabase.messages.incrementViewedReceiptCounts(ids, envelope.timestamp)
|
||||
val missingTargetTimestamps: Set<Long> = if (readReceipts && storyViewedReceipts) {
|
||||
SignalDatabase.messages.incrementViewedReceiptCounts(viewedReceipt.timestampList, senderRecipientId, envelope.timestamp)
|
||||
} else if (readReceipts) {
|
||||
SignalDatabase.messages.incrementViewedNonStoryReceiptCounts(ids, envelope.timestamp)
|
||||
SignalDatabase.messages.incrementViewedNonStoryReceiptCounts(viewedReceipt.timestampList, senderRecipientId, envelope.timestamp)
|
||||
} else {
|
||||
SignalDatabase.messages.incrementViewedStoryReceiptCounts(ids, envelope.timestamp)
|
||||
SignalDatabase.messages.incrementViewedStoryReceiptCounts(viewedReceipt.timestampList, senderRecipientId, envelope.timestamp)
|
||||
}
|
||||
|
||||
val handled: Set<SyncMessageId> = ids.toSet() - unhandled.toSet()
|
||||
SignalDatabase.messages.updateViewedStories(handled)
|
||||
val foundTargetTimestamps: Set<Long> = viewedReceipt.timestampList.toSet() - missingTargetTimestamps.toSet()
|
||||
SignalDatabase.messages.updateViewedStories(foundTargetTimestamps)
|
||||
|
||||
if (unhandled.isNotEmpty()) {
|
||||
if (missingTargetTimestamps.isNotEmpty()) {
|
||||
val selfId = Recipient.self().id
|
||||
for (id in unhandled) {
|
||||
warn(envelope.timestamp, "[handleViewedReceipt] Could not find matching message! timestamp: ${id.timetamp}, author: ${id.recipientId} | Receipt so associating with message from self ($selfId)")
|
||||
|
||||
for (targetTimestamp in missingTargetTimestamps) {
|
||||
warn(envelope.timestamp, "[handleViewedReceipt] Could not find matching message! targetTimestamp: $targetTimestamp, receiptAuthor: $senderRecipientId | Receipt so associating with message from self ($selfId)")
|
||||
if (earlyMessageCacheEntry != null) {
|
||||
ApplicationDependencies.getEarlyMessageCache().store(selfId, id.timetamp, earlyMessageCacheEntry)
|
||||
ApplicationDependencies.getEarlyMessageCache().store(selfId, targetTimestamp, earlyMessageCacheEntry)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (unhandled.isNotEmpty() && earlyMessageCacheEntry != null) {
|
||||
if (missingTargetTimestamps.isNotEmpty() && earlyMessageCacheEntry != null) {
|
||||
PushProcessEarlyMessagesJob.enqueue()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.thoughtcrime.securesms.database.CallTable
|
|||
import org.thoughtcrime.securesms.database.GroupReceiptTable
|
||||
import org.thoughtcrime.securesms.database.GroupTable
|
||||
import org.thoughtcrime.securesms.database.MessageTable.MarkedMessageInfo
|
||||
import org.thoughtcrime.securesms.database.MessageTable.SyncMessageId
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException
|
||||
import org.thoughtcrime.securesms.database.PaymentMetaDataUtil
|
||||
import org.thoughtcrime.securesms.database.SentStorySyncManifest
|
||||
|
@ -323,9 +322,8 @@ object SyncMessageProcessor {
|
|||
attachments = allAttachments.filterNot { it.isSticker }
|
||||
|
||||
if (recipient.isSelf) {
|
||||
val id = SyncMessageId(recipient.id, sent.timestamp)
|
||||
SignalDatabase.messages.incrementDeliveryReceiptCount(id, System.currentTimeMillis())
|
||||
SignalDatabase.messages.incrementReadReceiptCount(id, System.currentTimeMillis())
|
||||
SignalDatabase.messages.incrementDeliveryReceiptCount(sent.timestamp, recipient.id, System.currentTimeMillis())
|
||||
SignalDatabase.messages.incrementReadReceiptCount(sent.timestamp, recipient.id, System.currentTimeMillis())
|
||||
}
|
||||
|
||||
SignalDatabase.messages.setTransactionSuccessful()
|
||||
|
@ -536,9 +534,8 @@ object SyncMessageProcessor {
|
|||
.scheduleDeletion(messageId, true, sent.expirationStartTimestamp, sent.message.expireTimer.seconds.inWholeMilliseconds)
|
||||
}
|
||||
if (recipient.isSelf) {
|
||||
val id = SyncMessageId(recipient.id, sent.timestamp)
|
||||
SignalDatabase.messages.incrementDeliveryReceiptCount(id, System.currentTimeMillis())
|
||||
SignalDatabase.messages.incrementReadReceiptCount(id, System.currentTimeMillis())
|
||||
SignalDatabase.messages.incrementDeliveryReceiptCount(sent.timestamp, recipient.id, System.currentTimeMillis())
|
||||
SignalDatabase.messages.incrementReadReceiptCount(sent.timestamp, recipient.id, System.currentTimeMillis())
|
||||
}
|
||||
SignalDatabase.messages.setTransactionSuccessful()
|
||||
} finally {
|
||||
|
@ -614,9 +611,8 @@ object SyncMessageProcessor {
|
|||
ApplicationDependencies.getExpiringMessageManager().scheduleDeletion(messageId, true, sent.expirationStartTimestamp, sent.message.expireTimer.seconds.inWholeMilliseconds)
|
||||
}
|
||||
if (recipient.isSelf) {
|
||||
val id = SyncMessageId(recipient.id, sent.timestamp)
|
||||
SignalDatabase.messages.incrementDeliveryReceiptCount(id, System.currentTimeMillis())
|
||||
SignalDatabase.messages.incrementReadReceiptCount(id, System.currentTimeMillis())
|
||||
SignalDatabase.messages.incrementDeliveryReceiptCount(sent.timestamp, recipient.id, System.currentTimeMillis())
|
||||
SignalDatabase.messages.incrementReadReceiptCount(sent.timestamp, recipient.id, System.currentTimeMillis())
|
||||
}
|
||||
SignalDatabase.messages.setTransactionSuccessful()
|
||||
} finally {
|
||||
|
@ -662,7 +658,7 @@ object SyncMessageProcessor {
|
|||
messageId = SignalDatabase.messages.insertMessageOutbox(outgoingMessage, threadId, false, GroupReceiptTable.STATUS_UNKNOWN, null)
|
||||
updateGroupReceiptStatus(sent, messageId, recipient.requireGroupId())
|
||||
} else {
|
||||
val outgoingTextMessage = text(recipient = recipient, body = body, expiresIn = expiresInMillis, sentTimeMillis = sent.timestamp, bodyRanges = bodyRanges)
|
||||
val outgoingTextMessage = text(threadRecipient = recipient, body = body, expiresIn = expiresInMillis, sentTimeMillis = sent.timestamp, bodyRanges = bodyRanges)
|
||||
messageId = SignalDatabase.messages.insertMessageOutbox(outgoingTextMessage, threadId, false, null)
|
||||
SignalDatabase.messages.markUnidentified(messageId, sent.isUnidentified(recipient.serviceId.orNull()))
|
||||
}
|
||||
|
@ -674,9 +670,8 @@ object SyncMessageProcessor {
|
|||
}
|
||||
|
||||
if (recipient.isSelf) {
|
||||
val id = SyncMessageId(recipient.id, sent.timestamp)
|
||||
SignalDatabase.messages.incrementDeliveryReceiptCount(id, System.currentTimeMillis())
|
||||
SignalDatabase.messages.incrementReadReceiptCount(id, System.currentTimeMillis())
|
||||
SignalDatabase.messages.incrementDeliveryReceiptCount(sent.timestamp, recipient.id, System.currentTimeMillis())
|
||||
SignalDatabase.messages.incrementReadReceiptCount(sent.timestamp, recipient.id, System.currentTimeMillis())
|
||||
}
|
||||
|
||||
return threadId
|
||||
|
|
|
@ -124,9 +124,10 @@ public class ApplicationMigrations {
|
|||
static final int RECOVERY_PASSWORD_SYNC = 79;
|
||||
static final int DECRYPTIONS_DRAINED = 80;
|
||||
static final int REBUILD_MESSAGE_FTS_INDEX_3 = 81;
|
||||
static final int TO_FROM_RECIPIENTS = 82;
|
||||
}
|
||||
|
||||
public static final int CURRENT_VERSION = 81;
|
||||
public static final int CURRENT_VERSION = 82;
|
||||
|
||||
/**
|
||||
* This *must* be called after the {@link JobManager} has been instantiated, but *before* the call
|
||||
|
@ -552,6 +553,10 @@ public class ApplicationMigrations {
|
|||
jobs.put(Version.REBUILD_MESSAGE_FTS_INDEX_3, new RebuildMessageSearchIndexMigrationJob());
|
||||
}
|
||||
|
||||
if (lastSeenVersion < Version.TO_FROM_RECIPIENTS) {
|
||||
jobs.put(Version.TO_FROM_RECIPIENTS, new DatabaseMigrationJob());
|
||||
}
|
||||
|
||||
return jobs;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import org.thoughtcrime.securesms.sms.GroupV2UpdateMessageUtil
|
|||
* Represents all the data needed for an outgoing message.
|
||||
*/
|
||||
data class OutgoingMessage(
|
||||
val recipient: Recipient,
|
||||
val threadRecipient: Recipient,
|
||||
val sentTimeMillis: Long,
|
||||
val body: String = "",
|
||||
val distributionType: Int = ThreadTable.DistributionTypes.DEFAULT,
|
||||
|
@ -82,7 +82,7 @@ data class OutgoingMessage(
|
|||
bodyRanges: BodyRangeList? = null,
|
||||
scheduledDate: Long = -1
|
||||
) : this(
|
||||
recipient = recipient,
|
||||
threadRecipient = recipient,
|
||||
body = body ?: "",
|
||||
attachments = attachments,
|
||||
sentTimeMillis = timestamp,
|
||||
|
@ -123,7 +123,7 @@ data class OutgoingMessage(
|
|||
bodyRanges: BodyRangeList? = null,
|
||||
contacts: List<Contact> = emptyList()
|
||||
) : this(
|
||||
recipient = recipient,
|
||||
threadRecipient = recipient,
|
||||
body = buildMessage(slideDeck, body ?: ""),
|
||||
attachments = slideDeck.asAttachments(),
|
||||
sentTimeMillis = timestamp,
|
||||
|
@ -168,9 +168,9 @@ data class OutgoingMessage(
|
|||
* A literal, insecure SMS message.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun sms(recipient: Recipient, body: String, subscriptionId: Int): OutgoingMessage {
|
||||
fun sms(threadRecipient: Recipient, body: String, subscriptionId: Int): OutgoingMessage {
|
||||
return OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = threadRecipient,
|
||||
sentTimeMillis = System.currentTimeMillis(),
|
||||
body = body,
|
||||
subscriptionId = subscriptionId,
|
||||
|
@ -183,14 +183,14 @@ data class OutgoingMessage(
|
|||
*/
|
||||
@JvmStatic
|
||||
fun text(
|
||||
recipient: Recipient,
|
||||
threadRecipient: Recipient,
|
||||
body: String,
|
||||
expiresIn: Long,
|
||||
sentTimeMillis: Long = System.currentTimeMillis(),
|
||||
bodyRanges: BodyRangeList? = null
|
||||
): OutgoingMessage {
|
||||
return OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = threadRecipient,
|
||||
sentTimeMillis = sentTimeMillis,
|
||||
body = body,
|
||||
expiresIn = expiresIn,
|
||||
|
@ -204,11 +204,11 @@ data class OutgoingMessage(
|
|||
* Helper for creating a group update message when a state change occurs and needs to be sent to others.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun groupUpdateMessage(recipient: Recipient, group: DecryptedGroupV2Context, sentTimeMillis: Long): OutgoingMessage {
|
||||
fun groupUpdateMessage(threadRecipient: Recipient, group: DecryptedGroupV2Context, sentTimeMillis: Long): OutgoingMessage {
|
||||
val groupContext = MessageGroupContext(group)
|
||||
|
||||
return OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = threadRecipient,
|
||||
body = groupContext.encodedGroupContext,
|
||||
sentTimeMillis = sentTimeMillis,
|
||||
messageGroupContext = groupContext,
|
||||
|
@ -223,7 +223,7 @@ data class OutgoingMessage(
|
|||
*/
|
||||
@JvmStatic
|
||||
fun groupUpdateMessage(
|
||||
recipient: Recipient,
|
||||
threadRecipient: Recipient,
|
||||
groupContext: MessageGroupContext,
|
||||
avatar: List<Attachment> = emptyList(),
|
||||
sentTimeMillis: Long,
|
||||
|
@ -235,7 +235,7 @@ data class OutgoingMessage(
|
|||
mentions: List<Mention> = emptyList()
|
||||
): OutgoingMessage {
|
||||
return OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = threadRecipient,
|
||||
body = groupContext.encodedGroupContext,
|
||||
isGroup = true,
|
||||
isGroupUpdate = true,
|
||||
|
@ -257,7 +257,7 @@ data class OutgoingMessage(
|
|||
*/
|
||||
@JvmStatic
|
||||
fun textStoryMessage(
|
||||
recipient: Recipient,
|
||||
threadRecipient: Recipient,
|
||||
body: String,
|
||||
sentTimeMillis: Long,
|
||||
storyType: StoryType,
|
||||
|
@ -265,7 +265,7 @@ data class OutgoingMessage(
|
|||
bodyRanges: BodyRangeList?
|
||||
): OutgoingMessage {
|
||||
return OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = threadRecipient,
|
||||
body = body,
|
||||
sentTimeMillis = sentTimeMillis,
|
||||
storyType = storyType,
|
||||
|
@ -279,9 +279,9 @@ data class OutgoingMessage(
|
|||
* Specialized message sent to request someone activate payments.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun requestToActivatePaymentsMessage(recipient: Recipient, sentTimeMillis: Long, expiresIn: Long): OutgoingMessage {
|
||||
fun requestToActivatePaymentsMessage(threadRecipient: Recipient, sentTimeMillis: Long, expiresIn: Long): OutgoingMessage {
|
||||
return OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = threadRecipient,
|
||||
sentTimeMillis = sentTimeMillis,
|
||||
expiresIn = expiresIn,
|
||||
isRequestToActivatePayments = true,
|
||||
|
@ -295,9 +295,9 @@ data class OutgoingMessage(
|
|||
* be sent to those that sent requests prior to activation.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun paymentsActivatedMessage(recipient: Recipient, sentTimeMillis: Long, expiresIn: Long): OutgoingMessage {
|
||||
fun paymentsActivatedMessage(threadRecipient: Recipient, sentTimeMillis: Long, expiresIn: Long): OutgoingMessage {
|
||||
return OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = threadRecipient,
|
||||
sentTimeMillis = sentTimeMillis,
|
||||
expiresIn = expiresIn,
|
||||
isPaymentsActivated = true,
|
||||
|
@ -310,9 +310,9 @@ data class OutgoingMessage(
|
|||
* Type of message sent when sending a payment to another Signal contact.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun paymentNotificationMessage(recipient: Recipient, paymentUuid: String, sentTimeMillis: Long, expiresIn: Long): OutgoingMessage {
|
||||
fun paymentNotificationMessage(threadRecipient: Recipient, paymentUuid: String, sentTimeMillis: Long, expiresIn: Long): OutgoingMessage {
|
||||
return OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = threadRecipient,
|
||||
body = paymentUuid,
|
||||
sentTimeMillis = sentTimeMillis,
|
||||
expiresIn = expiresIn,
|
||||
|
@ -325,9 +325,9 @@ data class OutgoingMessage(
|
|||
* Helper for creating expiration update messages.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun expirationUpdateMessage(recipient: Recipient, sentTimeMillis: Long, expiresIn: Long): OutgoingMessage {
|
||||
fun expirationUpdateMessage(threadRecipient: Recipient, sentTimeMillis: Long, expiresIn: Long): OutgoingMessage {
|
||||
return OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = threadRecipient,
|
||||
sentTimeMillis = sentTimeMillis,
|
||||
expiresIn = expiresIn,
|
||||
isExpirationUpdate = true,
|
||||
|
@ -340,9 +340,9 @@ data class OutgoingMessage(
|
|||
* Message for when you have verified the identity of a contact.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun identityVerifiedMessage(recipient: Recipient, sentTimeMillis: Long): OutgoingMessage {
|
||||
fun identityVerifiedMessage(threadRecipient: Recipient, sentTimeMillis: Long): OutgoingMessage {
|
||||
return OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = threadRecipient,
|
||||
sentTimeMillis = sentTimeMillis,
|
||||
isIdentityVerified = true,
|
||||
isUrgent = false,
|
||||
|
@ -354,9 +354,9 @@ data class OutgoingMessage(
|
|||
* Message for when the verification status of an identity is getting set to the default.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun identityDefaultMessage(recipient: Recipient, sentTimeMillis: Long): OutgoingMessage {
|
||||
fun identityDefaultMessage(threadRecipient: Recipient, sentTimeMillis: Long): OutgoingMessage {
|
||||
return OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = threadRecipient,
|
||||
sentTimeMillis = sentTimeMillis,
|
||||
isIdentityDefault = true,
|
||||
isUrgent = false,
|
||||
|
@ -369,9 +369,9 @@ data class OutgoingMessage(
|
|||
* but it doesn't hurt to support receiving them in sync messages.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun endSessionMessage(recipient: Recipient, sentTimeMillis: Long): OutgoingMessage {
|
||||
fun endSessionMessage(threadRecipient: Recipient, sentTimeMillis: Long): OutgoingMessage {
|
||||
return OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = threadRecipient,
|
||||
sentTimeMillis = sentTimeMillis,
|
||||
isEndSession = true,
|
||||
isUrgent = false,
|
||||
|
|
|
@ -293,7 +293,7 @@ sealed class NotificationBuilder(protected val context: Context) {
|
|||
.setIcon(notificationItem.getPersonIcon(context).toIconCompat())
|
||||
|
||||
if (includeShortcut) {
|
||||
personBuilder.setKey(ConversationUtil.getShortcutId(notificationItem.individualRecipient))
|
||||
personBuilder.setKey(ConversationUtil.getShortcutId(notificationItem.authorRecipient))
|
||||
}
|
||||
|
||||
person = personBuilder.build()
|
||||
|
@ -319,7 +319,7 @@ sealed class NotificationBuilder(protected val context: Context) {
|
|||
if (line != null) {
|
||||
style.addLine(line)
|
||||
}
|
||||
addPerson(notificationItem.individualRecipient)
|
||||
addPerson(notificationItem.authorRecipient)
|
||||
}
|
||||
|
||||
builder.setStyle(style)
|
||||
|
|
|
@ -74,7 +74,7 @@ data class NotificationConversation(
|
|||
val stringBuilder = SpannableStringBuilder()
|
||||
|
||||
if (privacy.isDisplayContact && recipient.isGroup) {
|
||||
stringBuilder.append(Util.getBoldedString(mostRecentNotification.individualRecipient.getDisplayName(context) + ": "))
|
||||
stringBuilder.append(Util.getBoldedString(mostRecentNotification.authorRecipient.getDisplayName(context) + ": "))
|
||||
}
|
||||
|
||||
return if (privacy.isDisplayMessage) {
|
||||
|
|
|
@ -112,7 +112,7 @@ object NotificationFactory {
|
|||
conversation = conversation,
|
||||
targetThread = targetThread,
|
||||
defaultBubbleState = defaultBubbleState,
|
||||
shouldAlert = (conversation.hasNewNotifications() || alertOverrides.contains(conversation.thread)) && !conversation.mostRecentNotification.individualRecipient.isSelf
|
||||
shouldAlert = (conversation.hasNewNotifications() || alertOverrides.contains(conversation.thread)) && !conversation.mostRecentNotification.authorRecipient.isSelf
|
||||
)
|
||||
if (conversation.hasNewNotifications()) {
|
||||
threadsThatNewlyAlerted += conversation.thread
|
||||
|
@ -157,7 +157,7 @@ object NotificationFactory {
|
|||
conversation = conversation,
|
||||
targetThread = targetThread,
|
||||
defaultBubbleState = defaultBubbleState,
|
||||
shouldAlert = (conversation.hasNewNotifications() || alertOverrides.contains(conversation.thread)) && !conversation.mostRecentNotification.individualRecipient.isSelf
|
||||
shouldAlert = (conversation.hasNewNotifications() || alertOverrides.contains(conversation.thread)) && !conversation.mostRecentNotification.authorRecipient.isSelf
|
||||
)
|
||||
} catch (e: SecurityException) {
|
||||
Log.w(TAG, "Too many pending intents device quirk", e)
|
||||
|
|
|
@ -49,12 +49,12 @@ sealed class NotificationItem(val threadRecipient: Recipient, protected val reco
|
|||
val slideDeck: SlideDeck? = if (record.isViewOnce) null else (record as? MmsMessageRecord)?.slideDeck
|
||||
val isJoined: Boolean = record.isJoined
|
||||
val isPersonSelf: Boolean
|
||||
get() = individualRecipient.isSelf
|
||||
get() = authorRecipient.isSelf
|
||||
|
||||
protected val notifiedTimestamp: Long = record.notifiedTimestamp
|
||||
|
||||
abstract val timestamp: Long
|
||||
abstract val individualRecipient: Recipient
|
||||
abstract val authorRecipient: Recipient
|
||||
abstract val isNewNotification: Boolean
|
||||
|
||||
protected abstract fun getPrimaryTextActual(context: Context): CharSequence
|
||||
|
@ -92,8 +92,8 @@ sealed class NotificationItem(val threadRecipient: Recipient, protected val reco
|
|||
context.getString(R.string.SingleRecipientNotificationBuilder_new_message)
|
||||
} else {
|
||||
SpannableStringBuilder().apply {
|
||||
append(Util.getBoldedString(individualRecipient.getShortDisplayNameIncludingUsername(context)))
|
||||
if (threadRecipient != individualRecipient) {
|
||||
append(Util.getBoldedString(authorRecipient.getShortDisplayNameIncludingUsername(context)))
|
||||
if (threadRecipient != authorRecipient) {
|
||||
append(Util.getBoldedString("@${threadRecipient.getDisplayName(context)}"))
|
||||
}
|
||||
append(": ")
|
||||
|
@ -104,7 +104,7 @@ sealed class NotificationItem(val threadRecipient: Recipient, protected val reco
|
|||
|
||||
fun getPersonName(context: Context): CharSequence {
|
||||
return if (SignalStore.settings().messageNotificationsPrivacy.isDisplayContact) {
|
||||
individualRecipient.getDisplayName(context)
|
||||
authorRecipient.getDisplayName(context)
|
||||
} else {
|
||||
context.getString(R.string.SingleRecipientNotificationBuilder_signal)
|
||||
}
|
||||
|
@ -115,8 +115,8 @@ sealed class NotificationItem(val threadRecipient: Recipient, protected val reco
|
|||
}
|
||||
|
||||
fun getPersonUri(): String? {
|
||||
return if (SignalStore.settings().messageNotificationsPrivacy.isDisplayContact && individualRecipient.isSystemContact) {
|
||||
individualRecipient.contactUri.toString()
|
||||
return if (SignalStore.settings().messageNotificationsPrivacy.isDisplayContact && authorRecipient.isSystemContact) {
|
||||
authorRecipient.contactUri.toString()
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
@ -124,7 +124,7 @@ sealed class NotificationItem(val threadRecipient: Recipient, protected val reco
|
|||
|
||||
fun getPersonIcon(context: Context): Bitmap? {
|
||||
return if (SignalStore.settings().messageNotificationsPrivacy.isDisplayContact) {
|
||||
individualRecipient.getContactDrawable(context).toLargeBitmap(context)
|
||||
authorRecipient.getContactDrawable(context).toLargeBitmap(context)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
@ -153,8 +153,8 @@ sealed class NotificationItem(val threadRecipient: Recipient, protected val reco
|
|||
return timestamp == other.timestamp &&
|
||||
id == other.id &&
|
||||
isMms == other.isMms &&
|
||||
individualRecipient == other.individualRecipient &&
|
||||
individualRecipient.hasSameContent(other.individualRecipient) &&
|
||||
authorRecipient == other.authorRecipient &&
|
||||
authorRecipient.hasSameContent(other.authorRecipient) &&
|
||||
slideDeck?.thumbnailSlide?.isInProgress == other.slideDeck?.thumbnailSlide?.isInProgress &&
|
||||
record.isRemoteDelete == other.record.isRemoteDelete
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ sealed class NotificationItem(val threadRecipient: Recipient, protected val reco
|
|||
*/
|
||||
class MessageNotification(threadRecipient: Recipient, record: MessageRecord) : NotificationItem(threadRecipient, record) {
|
||||
override val timestamp: Long = record.timestamp
|
||||
override val individualRecipient: Recipient = if (record.isOutgoing) Recipient.self() else record.individualRecipient.resolve()
|
||||
override val authorRecipient: Recipient = record.fromRecipient.resolve()
|
||||
override val isNewNotification: Boolean = notifiedTimestamp == 0L
|
||||
|
||||
private var thumbnailInfo: ThumbnailInfo? = null
|
||||
|
@ -302,7 +302,7 @@ class MessageNotification(threadRecipient: Recipient, record: MessageRecord) : N
|
|||
*/
|
||||
class ReactionNotification(threadRecipient: Recipient, record: MessageRecord, val reaction: ReactionRecord) : NotificationItem(threadRecipient, record) {
|
||||
override val timestamp: Long = reaction.dateReceived
|
||||
override val individualRecipient: Recipient = Recipient.resolved(reaction.author)
|
||||
override val authorRecipient: Recipient = Recipient.resolved(reaction.author)
|
||||
override val isNewNotification: Boolean = timestamp > notifiedTimestamp
|
||||
|
||||
override fun getPrimaryTextActual(context: Context): CharSequence {
|
||||
|
|
|
@ -38,7 +38,7 @@ data class NotificationState(val conversations: List<NotificationConversation>,
|
|||
get() = notificationItems.lastOrNull()
|
||||
|
||||
val mostRecentSender: Recipient?
|
||||
get() = mostRecentNotification?.individualRecipient
|
||||
get() = mostRecentNotification?.authorRecipient
|
||||
|
||||
fun getNonVisibleConversation(visibleThread: ConversationId?): List<NotificationConversation> {
|
||||
return conversations.filterNot { it.thread == visibleThread }
|
||||
|
@ -81,7 +81,7 @@ data class NotificationState(val conversations: List<NotificationConversation>,
|
|||
}
|
||||
|
||||
fun getThreadsWithMostRecentNotificationFromSelf(): Set<ConversationId> {
|
||||
return conversations.filter { it.mostRecentNotification.individualRecipient.isSelf }
|
||||
return conversations.filter { it.mostRecentNotification.authorRecipient.isSelf }
|
||||
.map { it.thread }
|
||||
.toSet()
|
||||
}
|
||||
|
|
|
@ -112,8 +112,8 @@ object NotificationStateProvider {
|
|||
}
|
||||
|
||||
notificationItems.sort()
|
||||
if (notificationItems.isNotEmpty() && stickyThreads.containsKey(thread) && !notificationItems.last().individualRecipient.isSelf) {
|
||||
val indexOfOldestNonSelfMessage: Int = notificationItems.indexOfLast { it.individualRecipient.isSelf } + 1
|
||||
if (notificationItems.isNotEmpty() && stickyThreads.containsKey(thread) && !notificationItems.last().authorRecipient.isSelf) {
|
||||
val indexOfOldestNonSelfMessage: Int = notificationItems.indexOfLast { it.authorRecipient.isSelf } + 1
|
||||
notificationItems = notificationItems.slice(indexOfOldestNonSelfMessage..notificationItems.lastIndex).toMutableList()
|
||||
}
|
||||
|
||||
|
|
|
@ -64,8 +64,8 @@ public final class ReviewUtil {
|
|||
.getGroupMembers(groupId, GroupTable.MemberSet.FULL_MEMBERS_INCLUDING_SELF);
|
||||
|
||||
List<ReviewRecipient> changed = Stream.of(profileChangeRecords)
|
||||
.distinctBy(record -> record.getRecipient().getId())
|
||||
.map(record -> new ReviewRecipient(record.getRecipient().resolve(), getProfileChangeDetails(record)))
|
||||
.distinctBy(record -> record.getFromRecipient().getId())
|
||||
.map(record -> new ReviewRecipient(record.getFromRecipient().resolve(), getProfileChangeDetails(record)))
|
||||
.filter(recipient -> !recipient.getRecipient().isSystemContact())
|
||||
.toList();
|
||||
|
||||
|
|
|
@ -134,9 +134,9 @@ object SafetyNumberBottomSheet {
|
|||
|
||||
private fun getDestinationFromRecord(messageRecord: MessageRecord): List<ContactSearchKey.RecipientSearchKey> {
|
||||
val key = if ((messageRecord as? MmsMessageRecord)?.storyType?.isStory == true) {
|
||||
ContactSearchKey.RecipientSearchKey(messageRecord.recipient.id, true)
|
||||
ContactSearchKey.RecipientSearchKey(messageRecord.toRecipient.id, true)
|
||||
} else {
|
||||
ContactSearchKey.RecipientSearchKey(messageRecord.recipient.id, false)
|
||||
ContactSearchKey.RecipientSearchKey(messageRecord.toRecipient.id, false)
|
||||
}
|
||||
|
||||
return listOf(key)
|
||||
|
|
|
@ -367,8 +367,7 @@ public class SearchRepository {
|
|||
CharSequence updatedBody = MentionUtil.updateBodyAndMentionsWithDisplayNames(context, body, mentions).getBody();
|
||||
CharSequence updatedSnippet = makeSnippet(cleanQueries, Objects.requireNonNull(updatedBody));
|
||||
|
||||
//noinspection ConstantConditions
|
||||
results.add(new MessageResult(threadTable.getRecipientForThreadId(record.getThreadId()), record.getRecipient(), updatedBody, updatedSnippet, record.getThreadId(), record.getId(), record.getDateReceived(), true));
|
||||
results.add(new MessageResult(record.getToRecipient(), record.getFromRecipient(), updatedBody, updatedSnippet, record.getThreadId(), record.getId(), record.getDateReceived(), true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -394,8 +393,7 @@ public class SearchRepository {
|
|||
|
||||
try (MessageTable.Reader reader = messageTable.getMessages(mentionQueryResults.keySet())) {
|
||||
for (MessageRecord record : reader) {
|
||||
//noinspection ConstantConditions
|
||||
results.add(new MessageResult(threadTable.getRecipientForThreadId(record.getThreadId()), record.getRecipient(), record.getBody(), record.getBody(), record.getThreadId(), record.getId(), record.getDateReceived(), true));
|
||||
results.add(new MessageResult(record.getToRecipient(), record.getFromRecipient(), record.getBody(), record.getBody(), record.getThreadId(), record.getId(), record.getDateReceived(), true));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,19 +47,19 @@ class ScheduledMessageManager(
|
|||
val delay = (oldestMessage.scheduledDate - System.currentTimeMillis()).coerceAtLeast(0)
|
||||
Log.i(TAG, "The next scheduled message needs to be sent in $delay ms.")
|
||||
|
||||
return Event(delay, oldestMessage.recipient.id, oldestMessage.threadId)
|
||||
return Event(delay, oldestMessage.toRecipient.id, oldestMessage.threadId)
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
override fun executeEvent(event: Event) {
|
||||
val scheduledMessagesToSend = messagesTable.getScheduledMessagesBefore(System.currentTimeMillis())
|
||||
for (record in scheduledMessagesToSend) {
|
||||
val expiresIn = SignalDatabase.recipients.getExpiresInSeconds(record.recipient.id)
|
||||
val expiresIn = SignalDatabase.recipients.getExpiresInSeconds(record.toRecipient.id)
|
||||
if (messagesTable.clearScheduledStatus(record.threadId, record.id, expiresIn.seconds.inWholeMilliseconds)) {
|
||||
if (record.recipient.isPushGroup) {
|
||||
PushGroupSendJob.enqueue(application, ApplicationDependencies.getJobManager(), record.id, record.recipient.id, emptySet(), true)
|
||||
if (record.toRecipient.isPushGroup) {
|
||||
PushGroupSendJob.enqueue(application, ApplicationDependencies.getJobManager(), record.id, record.toRecipient.id, emptySet(), true)
|
||||
} else {
|
||||
IndividualSendJob.enqueue(application, ApplicationDependencies.getJobManager(), record.id, record.recipient, true)
|
||||
IndividualSendJob.enqueue(application, ApplicationDependencies.getJobManager(), record.id, record.toRecipient, true)
|
||||
}
|
||||
} else {
|
||||
Log.i(TAG, "messageId=${record.id} was not a scheduled message, ignoring")
|
||||
|
|
|
@ -31,7 +31,7 @@ public class IncomingTextMessage implements Parcelable {
|
|||
private static final String TAG = Log.tag(IncomingTextMessage.class);
|
||||
|
||||
private final String message;
|
||||
private final RecipientId sender;
|
||||
private final RecipientId authorId;
|
||||
private final int senderDeviceId;
|
||||
private final int protocol;
|
||||
private final String serviceCenterAddress;
|
||||
|
@ -47,9 +47,9 @@ public class IncomingTextMessage implements Parcelable {
|
|||
private final boolean unidentified;
|
||||
@Nullable private final String serverGuid;
|
||||
|
||||
public IncomingTextMessage(@NonNull RecipientId sender, @NonNull SmsMessage message, int subscriptionId) {
|
||||
public IncomingTextMessage(@NonNull RecipientId authorId, @NonNull SmsMessage message, int subscriptionId) {
|
||||
this.message = message.getDisplayMessageBody();
|
||||
this.sender = sender;
|
||||
this.authorId = authorId;
|
||||
this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID;
|
||||
this.protocol = message.getProtocolIdentifier();
|
||||
this.serviceCenterAddress = message.getServiceCenterAddress();
|
||||
|
@ -66,7 +66,7 @@ public class IncomingTextMessage implements Parcelable {
|
|||
this.serverGuid = null;
|
||||
}
|
||||
|
||||
public IncomingTextMessage(@NonNull RecipientId sender,
|
||||
public IncomingTextMessage(@NonNull RecipientId authorId,
|
||||
int senderDeviceId,
|
||||
long sentTimestampMillis,
|
||||
long serverTimestampMillis,
|
||||
|
@ -78,7 +78,7 @@ public class IncomingTextMessage implements Parcelable {
|
|||
String serverGuid)
|
||||
{
|
||||
this.message = encodedBody;
|
||||
this.sender = sender;
|
||||
this.authorId = authorId;
|
||||
this.senderDeviceId = senderDeviceId;
|
||||
this.protocol = 31337;
|
||||
this.serviceCenterAddress = "GCM";
|
||||
|
@ -97,7 +97,7 @@ public class IncomingTextMessage implements Parcelable {
|
|||
|
||||
public IncomingTextMessage(Parcel in) {
|
||||
this.message = in.readString();
|
||||
this.sender = in.readParcelable(IncomingTextMessage.class.getClassLoader());
|
||||
this.authorId = in.readParcelable(IncomingTextMessage.class.getClassLoader());
|
||||
this.senderDeviceId = in.readInt();
|
||||
this.protocol = in.readInt();
|
||||
this.serviceCenterAddress = in.readString();
|
||||
|
@ -116,8 +116,8 @@ public class IncomingTextMessage implements Parcelable {
|
|||
|
||||
public IncomingTextMessage(IncomingTextMessage base, String newBody) {
|
||||
this.message = newBody;
|
||||
this.sender = base.getSender();
|
||||
this.senderDeviceId = base.getSenderDeviceId();
|
||||
this.authorId = base.getAuthorId();
|
||||
this.senderDeviceId = base.getAuthorDeviceId();
|
||||
this.protocol = base.getProtocol();
|
||||
this.serviceCenterAddress = base.getServiceCenterAddress();
|
||||
this.replyPathPresent = base.isReplyPathPresent();
|
||||
|
@ -141,8 +141,8 @@ public class IncomingTextMessage implements Parcelable {
|
|||
}
|
||||
|
||||
this.message = body.toString();
|
||||
this.sender = fragments.get(0).getSender();
|
||||
this.senderDeviceId = fragments.get(0).getSenderDeviceId();
|
||||
this.authorId = fragments.get(0).getAuthorId();
|
||||
this.senderDeviceId = fragments.get(0).getAuthorDeviceId();
|
||||
this.protocol = fragments.get(0).getProtocol();
|
||||
this.serviceCenterAddress = fragments.get(0).getServiceCenterAddress();
|
||||
this.replyPathPresent = fragments.get(0).isReplyPathPresent();
|
||||
|
@ -186,11 +186,11 @@ public class IncomingTextMessage implements Parcelable {
|
|||
return message;
|
||||
}
|
||||
|
||||
public RecipientId getSender() {
|
||||
return sender;
|
||||
public RecipientId getAuthorId() {
|
||||
return authorId;
|
||||
}
|
||||
|
||||
public int getSenderDeviceId() {
|
||||
public int getAuthorDeviceId() {
|
||||
return senderDeviceId;
|
||||
}
|
||||
|
||||
|
@ -277,7 +277,7 @@ public class IncomingTextMessage implements Parcelable {
|
|||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
out.writeString(message);
|
||||
out.writeParcelable(sender, flags);
|
||||
out.writeParcelable(authorId, flags);
|
||||
out.writeInt(senderDeviceId);
|
||||
out.writeInt(protocol);
|
||||
out.writeString(serviceCenterAddress);
|
||||
|
|
|
@ -120,13 +120,13 @@ public class MessageSender {
|
|||
database.beginTransaction();
|
||||
|
||||
for (OutgoingMessage message : messages) {
|
||||
long allocatedThreadId = threadTable.getOrCreateValidThreadId(message.getRecipient(), -1L, message.getDistributionType());
|
||||
long allocatedThreadId = threadTable.getOrCreateValidThreadId(message.getThreadRecipient(), -1L, message.getDistributionType());
|
||||
long messageId = database.insertMessageOutbox(message.stripAttachments(), allocatedThreadId, false, insertListener);
|
||||
|
||||
messageIds.add(messageId);
|
||||
threads.add(allocatedThreadId);
|
||||
|
||||
if (message.getRecipient().isGroup() && message.getAttachments().isEmpty() && message.getLinkPreviews().isEmpty() && message.getSharedContacts().isEmpty()) {
|
||||
if (message.getThreadRecipient().isGroup() && message.getAttachments().isEmpty() && message.getLinkPreviews().isEmpty() && message.getSharedContacts().isEmpty()) {
|
||||
SignalLocalMetrics.GroupMessageSend.onInsertedIntoDatabase(messageId, metricId);
|
||||
} else {
|
||||
SignalLocalMetrics.GroupMessageSend.cancel(metricId);
|
||||
|
@ -136,7 +136,7 @@ public class MessageSender {
|
|||
for (int i = 0; i < messageIds.size(); i++) {
|
||||
long messageId = messageIds.get(i);
|
||||
OutgoingMessage message = messages.get(i);
|
||||
Recipient recipient = message.getRecipient();
|
||||
Recipient recipient = message.getThreadRecipient();
|
||||
|
||||
if (recipient.isDistributionList()) {
|
||||
DistributionId distributionId = Objects.requireNonNull(SignalDatabase.distributionLists().getDistributionId(recipient.requireDistributionListId()));
|
||||
|
@ -196,7 +196,7 @@ public class MessageSender {
|
|||
for (int i = 0; i < messageIds.size(); i++) {
|
||||
long messageId = messageIds.get(i);
|
||||
OutgoingMessage message = messages.get(i);
|
||||
Recipient recipient = message.getRecipient();
|
||||
Recipient recipient = message.getThreadRecipient();
|
||||
List<UploadDependencyGraph.Node> dependencies = dependencyGraph.getDependencyMap().get(message);
|
||||
|
||||
List<String> jobDependencyIds = (dependencies != null) ? dependencies.stream().map(UploadDependencyGraph.Node::getJobId).collect(Collectors.toList())
|
||||
|
@ -224,16 +224,16 @@ public class MessageSender {
|
|||
@Nullable final String metricId,
|
||||
@Nullable final MessageTable.InsertListener insertListener)
|
||||
{
|
||||
Log.i(TAG, "Sending media message to " + message.getRecipient().getId() + ", thread: " + threadId);
|
||||
Log.i(TAG, "Sending media message to " + message.getThreadRecipient().getId() + ", thread: " + threadId);
|
||||
try {
|
||||
ThreadTable threadTable = SignalDatabase.threads();
|
||||
MessageTable database = SignalDatabase.messages();
|
||||
|
||||
long allocatedThreadId = threadTable.getOrCreateValidThreadId(message.getRecipient(), threadId, message.getDistributionType());
|
||||
Recipient recipient = message.getRecipient();
|
||||
long allocatedThreadId = threadTable.getOrCreateValidThreadId(message.getThreadRecipient(), threadId, message.getDistributionType());
|
||||
Recipient recipient = message.getThreadRecipient();
|
||||
long messageId = database.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, recipient, message, allocatedThreadId), allocatedThreadId, sendType != SendType.SIGNAL, insertListener);
|
||||
|
||||
if (message.getRecipient().isGroup() && message.getAttachments().isEmpty() && message.getLinkPreviews().isEmpty() && message.getSharedContacts().isEmpty()) {
|
||||
if (message.getThreadRecipient().isGroup() && message.getAttachments().isEmpty() && message.getLinkPreviews().isEmpty() && message.getSharedContacts().isEmpty()) {
|
||||
SignalLocalMetrics.GroupMessageSend.onInsertedIntoDatabase(messageId, metricId);
|
||||
} else {
|
||||
SignalLocalMetrics.GroupMessageSend.cancel(metricId);
|
||||
|
@ -256,7 +256,7 @@ public class MessageSender {
|
|||
final long threadId,
|
||||
final MessageTable.InsertListener insertListener)
|
||||
{
|
||||
Log.i(TAG, "Sending media message with pre-uploads to " + message.getRecipient().getId() + ", thread: " + threadId + ", pre-uploads: " + preUploadResults);
|
||||
Log.i(TAG, "Sending media message with pre-uploads to " + message.getThreadRecipient().getId() + ", thread: " + threadId + ", pre-uploads: " + preUploadResults);
|
||||
Preconditions.checkArgument(message.getAttachments().isEmpty(), "If the media is pre-uploaded, there should be no attachments on the message.");
|
||||
|
||||
try {
|
||||
|
@ -264,8 +264,8 @@ public class MessageSender {
|
|||
MessageTable mmsDatabase = SignalDatabase.messages();
|
||||
AttachmentTable attachmentDatabase = SignalDatabase.attachments();
|
||||
|
||||
Recipient recipient = message.getRecipient();
|
||||
long allocatedThreadId = threadTable.getOrCreateValidThreadId(message.getRecipient(), threadId);
|
||||
Recipient recipient = message.getThreadRecipient();
|
||||
long allocatedThreadId = threadTable.getOrCreateValidThreadId(message.getThreadRecipient(), threadId);
|
||||
long messageId = mmsDatabase.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, recipient, message, allocatedThreadId),
|
||||
allocatedThreadId,
|
||||
false,
|
||||
|
@ -292,7 +292,7 @@ public class MessageSender {
|
|||
@NonNull Collection<PreUploadResult> preUploadResults,
|
||||
boolean overwritePreUploadMessageIds)
|
||||
{
|
||||
Log.i(TAG, "Sending media broadcast (overwrite: " + overwritePreUploadMessageIds + ") to " + Stream.of(messages).map(m -> m.getRecipient().getId()).toList());
|
||||
Log.i(TAG, "Sending media broadcast (overwrite: " + overwritePreUploadMessageIds + ") to " + Stream.of(messages).map(m -> m.getThreadRecipient().getId()).toList());
|
||||
Preconditions.checkArgument(messages.size() > 0, "No messages!");
|
||||
Preconditions.checkArgument(Stream.of(messages).allMatch(m -> m.getAttachments().isEmpty()), "Messages can't have attachments! They should be pre-uploaded.");
|
||||
|
||||
|
@ -309,8 +309,8 @@ public class MessageSender {
|
|||
mmsDatabase.beginTransaction();
|
||||
try {
|
||||
if (overwritePreUploadMessageIds) {
|
||||
long primaryThreadId = threadTable.getOrCreateThreadIdFor(primaryMessage.getRecipient(), primaryMessage.getDistributionType());
|
||||
long primaryMessageId = mmsDatabase.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, primaryMessage.getRecipient(), primaryMessage, primaryThreadId),
|
||||
long primaryThreadId = threadTable.getOrCreateThreadIdFor(primaryMessage.getThreadRecipient(), primaryMessage.getDistributionType());
|
||||
long primaryMessageId = mmsDatabase.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, primaryMessage.getThreadRecipient(), primaryMessage, primaryThreadId),
|
||||
primaryThreadId,
|
||||
false,
|
||||
null);
|
||||
|
@ -337,8 +337,8 @@ public class MessageSender {
|
|||
}
|
||||
|
||||
for (OutgoingMessage secondaryMessage : secondaryMessages) {
|
||||
long allocatedThreadId = threadTable.getOrCreateThreadIdFor(secondaryMessage.getRecipient(), secondaryMessage.getDistributionType());
|
||||
long messageId = mmsDatabase.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, secondaryMessage.getRecipient(), secondaryMessage, allocatedThreadId),
|
||||
long allocatedThreadId = threadTable.getOrCreateThreadIdFor(secondaryMessage.getThreadRecipient(), secondaryMessage.getDistributionType());
|
||||
long messageId = mmsDatabase.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, secondaryMessage.getThreadRecipient(), secondaryMessage, allocatedThreadId),
|
||||
allocatedThreadId,
|
||||
false,
|
||||
null);
|
||||
|
@ -370,7 +370,7 @@ public class MessageSender {
|
|||
for (int i = 0; i < messageIds.size(); i++) {
|
||||
long messageId = messageIds.get(i);
|
||||
OutgoingMessage message = messages.get(i);
|
||||
Recipient recipient = message.getRecipient();
|
||||
Recipient recipient = message.getThreadRecipient();
|
||||
|
||||
if (recipient.isDistributionList()) {
|
||||
List<RecipientId> members = SignalDatabase.distributionLists().getMembers(recipient.requireDistributionListId());
|
||||
|
@ -390,7 +390,7 @@ public class MessageSender {
|
|||
|
||||
for (int i = 0; i < messageIds.size(); i++) {
|
||||
long messageId = messageIds.get(i);
|
||||
Recipient recipient = messages.get(i).getRecipient();
|
||||
Recipient recipient = messages.get(i).getThreadRecipient();
|
||||
|
||||
if (isLocalSelfSend(context, recipient, SendType.SIGNAL)) {
|
||||
sendLocalMediaSelf(context, messageId);
|
||||
|
@ -473,7 +473,7 @@ public class MessageSender {
|
|||
|
||||
public static void resendGroupMessage(@NonNull Context context, @NonNull MessageRecord messageRecord, @NonNull Set<RecipientId> filterRecipientIds) {
|
||||
if (!messageRecord.isMms()) throw new AssertionError("Not Group");
|
||||
sendGroupPush(context, messageRecord.getRecipient(), messageRecord.getId(), filterRecipientIds, Collections.emptyList());
|
||||
sendGroupPush(context, messageRecord.getToRecipient(), messageRecord.getId(), filterRecipientIds, Collections.emptyList());
|
||||
onMessageSent();
|
||||
}
|
||||
|
||||
|
@ -481,14 +481,14 @@ public class MessageSender {
|
|||
if (!messageRecord.isMms() && !((MmsMessageRecord) messageRecord).getStoryType().isStory()) {
|
||||
throw new AssertionError("Not a story");
|
||||
}
|
||||
sendDistributionList(context, messageRecord.getRecipient(), messageRecord.getId(), filterRecipientIds, Collections.emptyList());
|
||||
sendDistributionList(context, messageRecord.getToRecipient(), messageRecord.getId(), filterRecipientIds, Collections.emptyList());
|
||||
onMessageSent();
|
||||
}
|
||||
|
||||
public static void resend(Context context, MessageRecord messageRecord) {
|
||||
long messageId = messageRecord.getId();
|
||||
boolean forceSms = messageRecord.isForcedSms();
|
||||
Recipient recipient = messageRecord.getRecipient();
|
||||
Recipient recipient = messageRecord.getToRecipient();
|
||||
|
||||
SendType sendType;
|
||||
|
||||
|
@ -658,9 +658,9 @@ public class MessageSender {
|
|||
mmsDatabase.markAsSent(messageId, true);
|
||||
mmsDatabase.markUnidentified(messageId, true);
|
||||
|
||||
mmsDatabase.incrementDeliveryReceiptCount(syncId, System.currentTimeMillis());
|
||||
mmsDatabase.incrementReadReceiptCount(syncId, System.currentTimeMillis());
|
||||
mmsDatabase.incrementViewedReceiptCount(syncId, System.currentTimeMillis());
|
||||
mmsDatabase.incrementDeliveryReceiptCount(message.getSentTimeMillis(), Recipient.self().getId(), System.currentTimeMillis());
|
||||
mmsDatabase.incrementReadReceiptCount(message.getSentTimeMillis(), Recipient.self().getId(), System.currentTimeMillis());
|
||||
mmsDatabase.incrementViewedReceiptCount(message.getSentTimeMillis(), Recipient.self().getId(), System.currentTimeMillis());
|
||||
|
||||
if (message.getExpiresIn() > 0 && !message.isExpirationUpdate()) {
|
||||
mmsDatabase.markExpireStarted(messageId);
|
||||
|
|
|
@ -31,7 +31,6 @@ import org.thoughtcrime.securesms.fonts.TextToScript
|
|||
import org.thoughtcrime.securesms.fonts.TypefaceCache
|
||||
import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader
|
||||
import org.thoughtcrime.securesms.mms.GlideApp
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
import org.thoughtcrime.securesms.util.Base64
|
||||
import org.thoughtcrime.securesms.util.ParcelUtil
|
||||
|
@ -94,7 +93,7 @@ data class StoryTextPostModel(
|
|||
return parseFrom(
|
||||
body = messageRecord.body,
|
||||
storySentAtMillis = messageRecord.timestamp,
|
||||
storyAuthor = if (messageRecord.isOutgoing) Recipient.self().id else messageRecord.individualRecipient.id,
|
||||
storyAuthor = messageRecord.fromRecipient.id,
|
||||
bodyRanges = messageRecord.messageRanges
|
||||
)
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ data class StoriesLandingItemData(
|
|||
val primaryStory: ConversationMessage,
|
||||
val secondaryStory: ConversationMessage?,
|
||||
val storyRecipient: Recipient,
|
||||
val individualRecipient: Recipient = primaryStory.messageRecord.individualRecipient,
|
||||
val individualRecipient: Recipient = primaryStory.messageRecord.fromRecipient,
|
||||
val dateInMilliseconds: Long = primaryStory.messageRecord.dateSent,
|
||||
val sendingCount: Long = 0,
|
||||
val failureCount: Long = 0
|
||||
|
|
|
@ -119,8 +119,8 @@ class MyStoriesFragment : DSLSettingsFragment(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
val recipient = if (it.distributionStory.messageRecord.recipient.isGroup) {
|
||||
it.distributionStory.messageRecord.recipient
|
||||
val recipient = if (it.distributionStory.messageRecord.toRecipient.isGroup) {
|
||||
it.distributionStory.messageRecord.toRecipient
|
||||
} else {
|
||||
Recipient.self()
|
||||
}
|
||||
|
|
|
@ -28,8 +28,8 @@ class MyStoriesRepository(context: Context) {
|
|||
val storiesMap = mutableMapOf<Recipient, List<MessageRecord>>()
|
||||
SignalDatabase.messages.getAllOutgoingStories(true, -1).use {
|
||||
for (messageRecord in it) {
|
||||
val currentList = storiesMap[messageRecord.recipient] ?: emptyList()
|
||||
storiesMap[messageRecord.recipient] = (currentList + messageRecord)
|
||||
val currentList = storiesMap[messageRecord.toRecipient] ?: emptyList()
|
||||
storiesMap[messageRecord.toRecipient] = (currentList + messageRecord)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -54,7 +54,7 @@ open class StoryViewerPageRepository(context: Context, private val storyViewStat
|
|||
}
|
||||
|
||||
val results = stories.filterNot {
|
||||
recipient.isMyStory && it.recipient.isGroup
|
||||
recipient.isMyStory && it.toRecipient.isGroup
|
||||
}
|
||||
|
||||
emitter.onNext(results)
|
||||
|
@ -79,9 +79,9 @@ open class StoryViewerPageRepository(context: Context, private val storyViewStat
|
|||
val recipient = Recipient.resolved(recipientId)
|
||||
val story = StoryPost(
|
||||
id = record.id,
|
||||
sender = if (record.isOutgoing) Recipient.self() else record.individualRecipient,
|
||||
sender = record.fromRecipient,
|
||||
group = if (recipient.isGroup) recipient else null,
|
||||
distributionList = if (record.recipient.isDistributionList) record.recipient else null,
|
||||
distributionList = if (record.toRecipient.isDistributionList) record.toRecipient else null,
|
||||
viewCount = record.viewedReceiptCount,
|
||||
replyCount = SignalDatabase.messages.getNumberOfStoryReplies(record.id),
|
||||
dateInMilliseconds = record.dateSent,
|
||||
|
|
|
@ -110,7 +110,7 @@ class StoryDirectReplyDialogFragment :
|
|||
if (state.groupDirectReplyRecipient != null) {
|
||||
composer.displayReplyHint(state.groupDirectReplyRecipient)
|
||||
} else if (state.storyRecord != null) {
|
||||
composer.displayReplyHint(state.storyRecord.recipient)
|
||||
composer.displayReplyHint(state.storyRecord.fromRecipient)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,21 +30,18 @@ class StoryDirectReplyRepository(context: Context) {
|
|||
return Completable.create { emitter ->
|
||||
val message = SignalDatabase.messages.getMessageRecord(storyId) as MediaMmsMessageRecord
|
||||
val (recipient, threadId) = if (groupDirectReplyRecipientId == null) {
|
||||
message.recipient to message.threadId
|
||||
message.fromRecipient to message.threadId
|
||||
} else {
|
||||
val resolved = Recipient.resolved(groupDirectReplyRecipientId)
|
||||
resolved to SignalDatabase.threads.getOrCreateThreadIdFor(resolved)
|
||||
}
|
||||
|
||||
val quoteAuthor: Recipient = when {
|
||||
message.isOutgoing -> Recipient.self()
|
||||
else -> message.individualRecipient
|
||||
}
|
||||
val quoteAuthor: Recipient = message.fromRecipient
|
||||
|
||||
MessageSender.send(
|
||||
context,
|
||||
OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = recipient,
|
||||
body = body.toString(),
|
||||
sentTimeMillis = System.currentTimeMillis(),
|
||||
expiresIn = TimeUnit.SECONDS.toMillis(recipient.expiresInSeconds.toLong()),
|
||||
|
|
|
@ -8,7 +8,7 @@ import org.thoughtcrime.securesms.recipients.Recipient
|
|||
sealed class ReplyBody(val messageRecord: MessageRecord) {
|
||||
|
||||
val key: MessageId = MessageId(messageRecord.id)
|
||||
val sender: Recipient = if (messageRecord.isOutgoing) Recipient.self() else messageRecord.individualRecipient.resolve()
|
||||
val sender: Recipient = messageRecord.fromRecipient.resolve()
|
||||
val sentAtMillis: Long = messageRecord.dateSent
|
||||
|
||||
open fun hasSameContent(other: ReplyBody): Boolean {
|
||||
|
|
|
@ -56,7 +56,7 @@ class StoryGroupReplyRepository {
|
|||
}
|
||||
|
||||
fun getNameColorsMap(storyId: Long, sessionMemberCache: MutableMap<GroupId, Set<Recipient>>): Observable<Map<RecipientId, NameColor>> {
|
||||
return Single.fromCallable { SignalDatabase.messages.getMessageRecord(storyId).individualRecipient.id }
|
||||
return Single.fromCallable { SignalDatabase.messages.getMessageRecord(storyId).fromRecipient.id }
|
||||
.subscribeOn(Schedulers.io())
|
||||
.flatMapObservable { recipientId ->
|
||||
Observable.create<Map<RecipientId, NameColor>?> { emitter ->
|
||||
|
|
|
@ -56,7 +56,7 @@ object StoryGroupReplySender {
|
|||
MessageSender.send(
|
||||
context,
|
||||
OutgoingMessage(
|
||||
recipient = recipient,
|
||||
threadRecipient = recipient,
|
||||
body = body.toString(),
|
||||
sentTimeMillis = System.currentTimeMillis(),
|
||||
parentStoryId = ParentStoryId.GroupReply(message.id),
|
||||
|
|
|
@ -25,17 +25,15 @@ class StoryViewsRepository {
|
|||
|
||||
fun getStoryRecipient(storyId: Long): Single<Recipient> {
|
||||
return Single.fromCallable {
|
||||
val record = SignalDatabase.messages.getMessageRecord(storyId)
|
||||
|
||||
record.recipient
|
||||
SignalDatabase.messages.getMessageRecord(storyId).toRecipient
|
||||
}.subscribeOn(Schedulers.io())
|
||||
}
|
||||
|
||||
fun getViews(storyId: Long): Observable<List<StoryViewItemData>> {
|
||||
return Observable.create<List<StoryViewItemData>> { emitter ->
|
||||
val record: MessageRecord = SignalDatabase.messages.getMessageRecord(storyId)
|
||||
val filterIds: Set<RecipientId> = if (record.recipient.isDistributionList) {
|
||||
val distributionId: DistributionId = SignalDatabase.distributionLists.getDistributionId(record.recipient.requireDistributionListId())!!
|
||||
val filterIds: Set<RecipientId> = if (record.toRecipient.isDistributionList) {
|
||||
val distributionId: DistributionId = SignalDatabase.distributionLists.getDistributionId(record.toRecipient.requireDistributionListId())!!
|
||||
SignalDatabase.storySends.getRecipientsForDistributionId(storyId, distributionId)
|
||||
} else {
|
||||
emptySet()
|
||||
|
|
|
@ -93,13 +93,13 @@ public class AttachmentUtil {
|
|||
try {
|
||||
MessageRecord message = SignalDatabase.messages().getMessageRecord(attachment.getMmsId());
|
||||
|
||||
Recipient individualRecipient = message.getRecipient();
|
||||
Recipient threadRecipient = SignalDatabase.threads().getRecipientForThreadId(message.getThreadId());
|
||||
Recipient fromRecipient = message.getFromRecipient();
|
||||
Recipient toRecipient = message.getToRecipient();
|
||||
|
||||
if (threadRecipient != null && threadRecipient.isGroup()) {
|
||||
return threadRecipient.isProfileSharing() || isTrustedIndividual(individualRecipient, message);
|
||||
if (toRecipient != null && toRecipient.isGroup()) {
|
||||
return toRecipient.isProfileSharing() || isTrustedIndividual(fromRecipient, message);
|
||||
} else {
|
||||
return isTrustedIndividual(individualRecipient, message);
|
||||
return isTrustedIndividual(fromRecipient, message);
|
||||
}
|
||||
} catch (NoSuchMessageException e) {
|
||||
Log.w(TAG, "Message could not be found! Assuming not a trusted contact.");
|
||||
|
|
|
@ -28,7 +28,7 @@ public final class RemoteDeleteUtil {
|
|||
boolean isValidIncomingOutgoing = (selfIsDeleteSender && targetMessage.isOutgoing()) ||
|
||||
(!selfIsDeleteSender && !targetMessage.isOutgoing());
|
||||
|
||||
boolean isValidSender = targetMessage.getIndividualRecipient().getId().equals(deleteSenderId) || selfIsDeleteSender && targetMessage.isOutgoing();
|
||||
boolean isValidSender = targetMessage.getFromRecipient().getId().equals(deleteSenderId) || selfIsDeleteSender && targetMessage.isOutgoing();
|
||||
|
||||
long messageTimestamp = selfIsDeleteSender && targetMessage.isOutgoing() ? targetMessage.getDateSent()
|
||||
: targetMessage.getServerTimestamp();
|
||||
|
@ -47,11 +47,11 @@ public final class RemoteDeleteUtil {
|
|||
return !message.isUpdate() &&
|
||||
message.isOutgoing() &&
|
||||
message.isPush() &&
|
||||
(!message.getRecipient().isGroup() || message.getRecipient().isActiveGroup()) &&
|
||||
(!message.getToRecipient().isGroup() || message.getToRecipient().isActiveGroup()) &&
|
||||
!message.isRemoteDelete() &&
|
||||
!MessageRecordUtil.hasGiftBadge(message) &&
|
||||
!message.isPaymentNotification() &&
|
||||
(((currentTime - message.getDateSent()) < SEND_THRESHOLD) || message.getRecipient().isSelf());
|
||||
(((currentTime - message.getDateSent()) < SEND_THRESHOLD) || message.getToRecipient().isSelf());
|
||||
}
|
||||
|
||||
private static boolean isSelf(@NonNull RecipientId recipientId) {
|
||||
|
|
|
@ -143,8 +143,8 @@ object FakeMessageRecords {
|
|||
return MediaMmsMessageRecord(
|
||||
id,
|
||||
conversationRecipient,
|
||||
individualRecipient,
|
||||
recipientDeviceId,
|
||||
individualRecipient,
|
||||
dateSent,
|
||||
dateReceived,
|
||||
dateServer,
|
||||
|
|
|
@ -67,7 +67,7 @@ object TestMms {
|
|||
fun insert(
|
||||
db: SQLiteDatabase,
|
||||
message: OutgoingMessage,
|
||||
recipientId: RecipientId = message.recipient.id,
|
||||
recipientId: RecipientId = message.threadRecipient.id,
|
||||
body: String = message.body,
|
||||
type: Long = MessageTypes.BASE_INBOX_TYPE,
|
||||
unread: Boolean = false,
|
||||
|
@ -86,7 +86,8 @@ object TestMms {
|
|||
put(MessageTable.SMS_SUBSCRIPTION_ID, message.subscriptionId)
|
||||
put(MessageTable.EXPIRES_IN, message.expiresIn)
|
||||
put(MessageTable.VIEW_ONCE, message.isViewOnce)
|
||||
put(MessageTable.RECIPIENT_ID, recipientId.serialize())
|
||||
put(MessageTable.FROM_RECIPIENT_ID, recipientId.serialize())
|
||||
put(MessageTable.TO_RECIPIENT_ID, recipientId.serialize())
|
||||
put(MessageTable.DELIVERY_RECEIPT_COUNT, 0)
|
||||
put(MessageTable.RECEIPT_TIMESTAMP, 0)
|
||||
put(MessageTable.VIEWED_RECEIPT_COUNT, if (viewed) 1 else 0)
|
||||
|
|
|
@ -59,8 +59,9 @@ object TestSms {
|
|||
threadId: Long = 1
|
||||
): Long {
|
||||
val values = ContentValues().apply {
|
||||
put(MessageTable.RECIPIENT_ID, message.sender.serialize())
|
||||
put(MessageTable.RECIPIENT_DEVICE_ID, message.senderDeviceId)
|
||||
put(MessageTable.FROM_RECIPIENT_ID, message.authorId.serialize())
|
||||
put(MessageTable.FROM_DEVICE_ID, message.authorDeviceId)
|
||||
put(MessageTable.TO_RECIPIENT_ID, message.authorId.serialize())
|
||||
put(MessageTable.DATE_RECEIVED, message.receivedTimestampMillis)
|
||||
put(MessageTable.DATE_SENT, message.sentTimestampMillis)
|
||||
put(MessageTable.DATE_SERVER, message.serverTimestampMillis)
|
||||
|
|
|
@ -167,8 +167,8 @@ class UploadDependencyGraphTest {
|
|||
// GIVEN
|
||||
val attachment1 = UriAttachmentBuilder.build(uniqueLong.getAndIncrement(), contentType = MediaUtil.IMAGE_JPEG)
|
||||
val attachment2 = UriAttachmentBuilder.build(uniqueLong.getAndIncrement(), contentType = MediaUtil.IMAGE_JPEG)
|
||||
val message1 = OutgoingMessage(recipient = Recipient.UNKNOWN, sentTimeMillis = System.currentTimeMillis(), attachments = listOf(attachment1))
|
||||
val message2 = OutgoingMessage(recipient = Recipient.UNKNOWN, sentTimeMillis = System.currentTimeMillis() + 1, attachments = listOf(attachment2))
|
||||
val message1 = OutgoingMessage(threadRecipient = Recipient.UNKNOWN, sentTimeMillis = System.currentTimeMillis(), attachments = listOf(attachment1))
|
||||
val message2 = OutgoingMessage(threadRecipient = Recipient.UNKNOWN, sentTimeMillis = System.currentTimeMillis() + 1, attachments = listOf(attachment2))
|
||||
val testSubject = UploadDependencyGraph.create(listOf(message1, message2), jobManager) { getAttachmentForPreUpload(uniqueLong.getAndIncrement(), it) }
|
||||
|
||||
// WHEN
|
||||
|
@ -191,7 +191,7 @@ class UploadDependencyGraphTest {
|
|||
)
|
||||
}
|
||||
|
||||
val message = OutgoingMessage(recipient = Recipient.UNKNOWN, sentTimeMillis = System.currentTimeMillis(), attachments = uriAttachments)
|
||||
val message = OutgoingMessage(threadRecipient = Recipient.UNKNOWN, sentTimeMillis = System.currentTimeMillis(), attachments = uriAttachments)
|
||||
val testSubject = UploadDependencyGraph.create(listOf(message), jobManager) { getAttachmentForPreUpload(uniqueLong.getAndIncrement(), it) }
|
||||
val result = testSubject.consumeDeferredQueue()
|
||||
|
||||
|
@ -262,7 +262,7 @@ class UploadDependencyGraphTest {
|
|||
private fun Iterable<Int>.createMessages(uriAttachments: List<Attachment>): List<OutgoingMessage> {
|
||||
return mapIndexed { index, _ ->
|
||||
OutgoingMessage(
|
||||
recipient = Recipient.UNKNOWN,
|
||||
threadRecipient = Recipient.UNKNOWN,
|
||||
sentTimeMillis = System.currentTimeMillis() + index,
|
||||
attachments = uriAttachments,
|
||||
isSecure = true
|
||||
|
|
Loading…
Add table
Reference in a new issue