Skip to content

Commit

Permalink
Fix crash when scheduling a message in an empty thread.
Browse files Browse the repository at this point in the history
  • Loading branch information
cody-signal authored and alex-signal committed Feb 6, 2023
1 parent 1f31f4a commit 418b486
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,8 @@ private void setStatusIcons(ThreadRecord thread) {
} else if (!thread.isOutgoing() ||
thread.isOutgoingAudioCall() ||
thread.isOutgoingVideoCall() ||
thread.isVerificationStatusChange())
thread.isVerificationStatusChange() ||
thread.isScheduledMessage())
{
deliveryStatusIndicator.setNone();
alertView.setNone();
Expand Down Expand Up @@ -588,6 +589,8 @@ private void onRecipientChanged(@NonNull Recipient recipient) {
return emphasisAdded(context, context.getString(R.string.ThreadRecord_secure_session_reset), defaultTint);
} else if (MessageTypes.isLegacyType(thread.getType())) {
return emphasisAdded(context, context.getString(R.string.MessageRecord_message_encrypted_with_a_legacy_protocol_version_that_is_no_longer_supported), defaultTint);
} else if (thread.isScheduledMessage()) {
return emphasisAdded(context, context.getString(R.string.ThreadRecord_scheduled_message), R.drawable.symbol_calendar_compact_light_16, defaultTint);
} else if (MessageTypes.isDraftMessageType(thread.getType())) {
String draftText = context.getString(R.string.ThreadRecord_draft);
return emphasisAdded(context, draftText + " " + thread.getBody(), defaultTint);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1716,8 +1716,8 @@ public int getIncomingMeaningfulMessageCountSince(long threadId, long afterTime)
}

private @NonNull SqlUtil.Query buildMeaningfulMessagesQuery(long threadId) {
String query = THREAD_ID + " = ? AND " + STORY_TYPE + " = ? AND " + PARENT_STORY_ID + " <= ? AND " + SCHEDULED_DATE + " = ? AND (NOT " + TYPE + " & ? AND " + TYPE + " != ? AND " + TYPE + " != ? AND " + TYPE + " != ? AND " + TYPE + " != ? AND " + TYPE + " & " + MessageTypes.GROUP_V2_LEAVE_BITS + " != " + MessageTypes.GROUP_V2_LEAVE_BITS + ")";
return SqlUtil.buildQuery(query, threadId, 0, 0, -1, MessageTypes.IGNORABLE_TYPESMASK_WHEN_COUNTING, MessageTypes.PROFILE_CHANGE_TYPE, MessageTypes.CHANGE_NUMBER_TYPE, MessageTypes.SMS_EXPORT_TYPE, MessageTypes.BOOST_REQUEST_TYPE);
String query = THREAD_ID + " = ? AND " + STORY_TYPE + " = ? AND " + PARENT_STORY_ID + " <= ? AND " + "(NOT " + TYPE + " & ? AND " + TYPE + " != ? AND " + TYPE + " != ? AND " + TYPE + " != ? AND " + TYPE + " != ? AND " + TYPE + " & " + MessageTypes.GROUP_V2_LEAVE_BITS + " != " + MessageTypes.GROUP_V2_LEAVE_BITS + ")";
return SqlUtil.buildQuery(query, threadId, 0, 0, MessageTypes.IGNORABLE_TYPESMASK_WHEN_COUNTING, MessageTypes.PROFILE_CHANGE_TYPE, MessageTypes.CHANGE_NUMBER_TYPE, MessageTypes.SMS_EXPORT_TYPE, MessageTypes.BOOST_REQUEST_TYPE);
}

public void addFailures(long messageId, List<NetworkFailure> failure) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ private ThreadBodyUtil() {
return format(EmojiStrings.CARD, getPaymentActivatedSummary(context, record));
} else if (record.isCallLog() && !record.isGroupCall()) {
return new ThreadBody(getCallLogSummary(context, record));
} else if (MessageRecordUtil.isScheduled(record)) {
return new ThreadBody(context.getString(R.string.ThreadRecord_scheduled_message));
}

boolean hasImage = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ import org.thoughtcrime.securesms.storage.StorageSyncHelper
import org.thoughtcrime.securesms.util.ConversationUtil
import org.thoughtcrime.securesms.util.JsonUtils
import org.thoughtcrime.securesms.util.TextSecurePreferences
import org.thoughtcrime.securesms.util.isScheduled
import org.whispersystems.signalservice.api.push.ServiceId
import org.whispersystems.signalservice.api.storage.SignalAccountRecord
import org.whispersystems.signalservice.api.storage.SignalAccountRecord.PinnedConversation
Expand Down Expand Up @@ -1344,31 +1345,36 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
val record: MessageRecord = try {
messages.getConversationSnippet(threadId)
} catch (e: NoSuchMessageException) {
Log.w(TAG, "Failed to get a conversation snippet for thread $threadId")
val scheduledMessage: MessageRecord? = messages.getScheduledMessagesInThread(threadId).lastOrNull()

if (shouldDelete) {
deleteConversation(threadId)
}
if (scheduledMessage == null) {
Log.w(TAG, "Failed to get a conversation snippet for thread $threadId")
if (shouldDelete) {
deleteConversation(threadId)
}

if (isPinned) {
updateThread(
threadId = threadId,
meaningfulMessages = meaningfulMessages,
body = null,
attachment = null,
contentType = null,
extra = null,
date = 0,
status = 0,
deliveryReceiptCount = 0,
type = 0,
unarchive = unarchive,
expiresIn = 0,
readReceiptCount = 0
)
if (isPinned) {
updateThread(
threadId = threadId,
meaningfulMessages = meaningfulMessages,
body = null,
attachment = null,
contentType = null,
extra = null,
date = 0,
status = 0,
deliveryReceiptCount = 0,
type = 0,
unarchive = unarchive,
expiresIn = 0,
readReceiptCount = 0
)
}
return true
} else {
Log.i(TAG, "Using scheduled message for conversation snippet")
scheduledMessage
}

return true
}

val drafts: DraftTable.Drafts = SignalDatabase.drafts.getDrafts(threadId)
Expand Down Expand Up @@ -1575,7 +1581,9 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
}
}

val extras: Extra? = if (record.isRemoteDelete) {
val extras: Extra? = if (record.isScheduled()) {
Extra.forScheduledMessage(individualRecipientId)
} else if (record.isRemoteDelete) {
Extra.forRemoteDelete(individualRecipientId)
} else if (record.isViewOnce) {
Extra.forViewOnce(individualRecipientId)
Expand Down Expand Up @@ -1778,7 +1786,8 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
@field:JsonProperty @param:JsonProperty("isGv2Invite") val isGv2Invite: Boolean = false,
@field:JsonProperty @param:JsonProperty("groupAddedBy") val groupAddedBy: String? = null,
@field:JsonProperty @param:JsonProperty("individualRecipientId") private val individualRecipientId: String,
@field:JsonProperty @param:JsonProperty("bodyRanges") val bodyRanges: String? = null
@field:JsonProperty @param:JsonProperty("bodyRanges") val bodyRanges: String? = null,
@field:JsonProperty @param:JsonProperty("isScheduled") val isScheduled: Boolean = false
) {

fun getIndividualRecipientId(): String {
Expand Down Expand Up @@ -1821,6 +1830,10 @@ class ThreadTable(context: Context, databaseHelper: SignalDatabase) : DatabaseTa
fun forBodyRanges(bodyRanges: BodyRangeList, individualRecipient: RecipientId): Extra {
return Extra(individualRecipientId = individualRecipient.serialize(), bodyRanges = bodyRanges.serialize())
}

fun forScheduledMessage(individualRecipient: RecipientId): Extra {
return Extra(individualRecipientId = individualRecipient.serialize(), isScheduled = true)
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ public boolean isDelivered() {
return StatusUtil.isDelivered(deliveryStatus, deliveryReceiptCount);
}

public boolean isScheduledMessage() {
return extra != null && extra.isScheduled();
}

public @Nullable RecipientId getGroupAddedBy() {
if (extra != null && extra.getGroupAddedBy() != null) return RecipientId.from(extra.getGroupAddedBy());
else return null;
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1960,6 +1960,8 @@
<string name="ThreadRecord__reacted_s_to_their_story">Reacted %1$s to their story</string>
<!-- Displayed in the conversation list when your most recent message is a payment to or from the person the conversation is with -->
<string name="ThreadRecord_payment">Payment</string>
<!-- Displayed in the conversation list when your only message in a conversation is a scheduled send. -->
<string name="ThreadRecord_scheduled_message">Scheduled message</string>

<!-- UpdateApkReadyListener -->
<string name="UpdateApkReadyListener_Signal_update">Signal update</string>
Expand Down

0 comments on commit 418b486

Please sign in to comment.