Move to defined from_recipient_id and to_recipient_id columns on message table.

This commit is contained in:
Greyson Parrelli 2023-04-14 14:23:05 -04:00 committed by Cody Henthorne
parent d079f85eca
commit 279ad7945e
86 changed files with 944 additions and 719 deletions

View file

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

View file

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

View file

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

View file

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

View file

@ -31,7 +31,7 @@ object Gifts {
expiresIn: Long
): OutgoingMessage {
return OutgoingMessage(
recipient = recipient,
threadRecipient = recipient,
body = Base64.encodeBytes(giftBadge.toByteArray()),
isSecure = true,
sentTimeMillis = sentTimestamp,

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -143,8 +143,8 @@ object FakeMessageRecords {
return MediaMmsMessageRecord(
id,
conversationRecipient,
individualRecipient,
recipientDeviceId,
individualRecipient,
dateSent,
dateReceived,
dateServer,

View file

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

View file

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

View file

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