mirror of
https://github.com/signalapp/Signal-Android.git
synced 2026-04-02 08:23:00 +01:00
Remove attachment table JSON join.
This commit is contained in:
committed by
Cody Henthorne
parent
7253aaaa14
commit
be4bf27ede
@@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.R
|
||||
import org.thoughtcrime.securesms.database.NoSuchMessageException
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase.Companion.messages
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.database.withAttachments
|
||||
import org.thoughtcrime.securesms.util.hasAudio
|
||||
import java.util.concurrent.Executor
|
||||
import java.util.concurrent.Executors
|
||||
@@ -258,7 +259,7 @@ class VoiceNotePlayerCallback(val context: Context, val player: VoiceNotePlayer)
|
||||
|
||||
private fun loadMediaItemsForSinglePlayback(messageId: Long): List<MediaItem> {
|
||||
return try {
|
||||
listOf(messages.getMessageRecord(messageId)).messageRecordsToVoiceNoteMediaItems()
|
||||
listOf(messages.getMessageRecord(messageId)).withAttachments().messageRecordsToVoiceNoteMediaItems()
|
||||
} catch (e: NoSuchMessageException) {
|
||||
Log.w(TAG, "Could not find message.", e)
|
||||
emptyList()
|
||||
@@ -268,7 +269,7 @@ class VoiceNotePlayerCallback(val context: Context, val player: VoiceNotePlayer)
|
||||
@WorkerThread
|
||||
private fun loadMediaItemsForConsecutivePlayback(messageId: Long): List<MediaItem> {
|
||||
return try {
|
||||
messages.getMessagesAfterVoiceNoteInclusive(messageId, LIMIT).messageRecordsToVoiceNoteMediaItems()
|
||||
messages.getMessagesAfterVoiceNoteInclusive(messageId, LIMIT).withAttachments().messageRecordsToVoiceNoteMediaItems()
|
||||
} catch (e: NoSuchMessageException) {
|
||||
Log.w(TAG, "Could not find message.", e)
|
||||
emptyList()
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.thoughtcrime.securesms.database.model.MessageId
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList
|
||||
import org.thoughtcrime.securesms.database.withAttachments
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.keyboard.KeyboardUtil
|
||||
import org.thoughtcrime.securesms.mms.GifSlide
|
||||
@@ -219,7 +220,8 @@ class DraftRepository(
|
||||
|
||||
private fun loadDraftMessageEditInternal(serialized: String): ConversationMessage? {
|
||||
val messageId = MessageId.deserialize(serialized)
|
||||
val messageRecord: MessageRecord = SignalDatabase.messages.getMessageRecordOrNull(messageId.id) ?: return null
|
||||
var messageRecord: MessageRecord = SignalDatabase.messages.getMessageRecordOrNull(messageId.id) ?: return null
|
||||
messageRecord = messageRecord.withAttachments()
|
||||
val threadRecipient: Recipient = requireNotNull(SignalDatabase.threads.getRecipientForThreadId(messageRecord.threadId))
|
||||
if (messageRecord.hasTextSlide()) {
|
||||
val textSlide = messageRecord.requireTextSlide()
|
||||
|
||||
@@ -20,14 +20,11 @@ import android.content.ContentValues
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.media.MediaDataSource
|
||||
import android.text.TextUtils
|
||||
import androidx.annotation.VisibleForTesting
|
||||
import androidx.annotation.WorkerThread
|
||||
import androidx.core.content.contentValuesOf
|
||||
import com.bumptech.glide.Glide
|
||||
import okio.ByteString.Companion.toByteString
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import org.signal.blurhash.BlurHash
|
||||
import org.signal.core.models.backup.MediaId
|
||||
import org.signal.core.models.backup.MediaName
|
||||
@@ -107,7 +104,6 @@ import org.thoughtcrime.securesms.stickers.StickerLocator
|
||||
import org.thoughtcrime.securesms.util.BitmapDecodingException
|
||||
import org.thoughtcrime.securesms.util.FileUtils
|
||||
import org.thoughtcrime.securesms.util.ImageCompressionUtil
|
||||
import org.thoughtcrime.securesms.util.JsonUtils.SaneJSONObject
|
||||
import org.thoughtcrime.securesms.util.MediaUtil
|
||||
import org.thoughtcrime.securesms.util.RemoteConfig
|
||||
import org.thoughtcrime.securesms.video.EncryptedMediaDataSource
|
||||
@@ -122,7 +118,6 @@ import java.io.InputStream
|
||||
import java.security.DigestInputStream
|
||||
import java.security.MessageDigest
|
||||
import java.security.NoSuchAlgorithmException
|
||||
import java.util.LinkedList
|
||||
import java.util.UUID
|
||||
import kotlin.text.appendLine
|
||||
import kotlin.time.Duration
|
||||
@@ -183,8 +178,6 @@ class AttachmentTable(
|
||||
const val QUOTE_TARGET_CONTENT_TYPE = "quote_target_content_type"
|
||||
const val METADATA_ID = "metadata_id"
|
||||
|
||||
const val ATTACHMENT_JSON_ALIAS = "attachment_json"
|
||||
|
||||
private const val DIRECTORY = "parts"
|
||||
|
||||
const val TRANSFER_PROGRESS_DONE = 0
|
||||
@@ -2327,80 +2320,6 @@ class AttachmentTable(
|
||||
notifyConversationListeners(threadId)
|
||||
}
|
||||
|
||||
fun getAttachments(cursor: Cursor): List<DatabaseAttachment> {
|
||||
return try {
|
||||
if (cursor.getColumnIndex(ATTACHMENT_JSON_ALIAS) != -1) {
|
||||
if (cursor.isNull(ATTACHMENT_JSON_ALIAS)) {
|
||||
return LinkedList()
|
||||
}
|
||||
|
||||
val result: MutableList<DatabaseAttachment> = mutableListOf()
|
||||
val array = JSONArray(cursor.requireString(ATTACHMENT_JSON_ALIAS))
|
||||
|
||||
for (i in 0 until array.length()) {
|
||||
val jsonObject = SaneJSONObject(array.getJSONObject(i))
|
||||
|
||||
if (!jsonObject.isNull(ID)) {
|
||||
val contentType = jsonObject.getString(CONTENT_TYPE)
|
||||
|
||||
result += DatabaseAttachment(
|
||||
attachmentId = AttachmentId(jsonObject.getLong(ID)),
|
||||
mmsId = jsonObject.getLong(MESSAGE_ID),
|
||||
hasData = !TextUtils.isEmpty(jsonObject.getString(DATA_FILE)),
|
||||
hasThumbnail = MediaUtil.isImageType(contentType) || MediaUtil.isVideoType(contentType),
|
||||
contentType = contentType,
|
||||
transferProgress = jsonObject.getInt(TRANSFER_STATE),
|
||||
size = jsonObject.getLong(DATA_SIZE),
|
||||
fileName = jsonObject.getString(FILE_NAME),
|
||||
cdn = Cdn.deserialize(jsonObject.getInt(CDN_NUMBER)),
|
||||
location = jsonObject.getString(REMOTE_LOCATION),
|
||||
key = jsonObject.getString(REMOTE_KEY),
|
||||
digest = null,
|
||||
incrementalDigest = null,
|
||||
incrementalMacChunkSize = 0,
|
||||
fastPreflightId = jsonObject.getString(FAST_PREFLIGHT_ID),
|
||||
voiceNote = jsonObject.getInt(VOICE_NOTE) != 0,
|
||||
borderless = jsonObject.getInt(BORDERLESS) != 0,
|
||||
videoGif = jsonObject.getInt(VIDEO_GIF) != 0,
|
||||
width = jsonObject.getInt(WIDTH),
|
||||
height = jsonObject.getInt(HEIGHT),
|
||||
quote = jsonObject.getInt(QUOTE) != 0,
|
||||
quoteTargetContentType = if (!jsonObject.isNull(QUOTE_TARGET_CONTENT_TYPE)) jsonObject.getString(QUOTE_TARGET_CONTENT_TYPE) else null,
|
||||
caption = jsonObject.getString(CAPTION),
|
||||
stickerLocator = if (jsonObject.getInt(STICKER_ID) >= 0) {
|
||||
StickerLocator(
|
||||
jsonObject.getString(STICKER_PACK_ID)!!,
|
||||
jsonObject.getString(STICKER_PACK_KEY)!!,
|
||||
jsonObject.getInt(STICKER_ID),
|
||||
jsonObject.getString(STICKER_EMOJI)
|
||||
)
|
||||
} else {
|
||||
null
|
||||
},
|
||||
blurHash = if (MediaUtil.isAudioType(contentType)) null else BlurHash.parseOrNull(jsonObject.getString(BLUR_HASH)),
|
||||
audioHash = if (MediaUtil.isAudioType(contentType)) AudioHash.parseOrNull(jsonObject.getString(BLUR_HASH)) else null,
|
||||
transformProperties = parseTransformProperties(jsonObject.getString(TRANSFORM_PROPERTIES)),
|
||||
displayOrder = jsonObject.getInt(DISPLAY_ORDER),
|
||||
uploadTimestamp = jsonObject.getLong(UPLOAD_TIMESTAMP),
|
||||
dataHash = jsonObject.getString(DATA_HASH_END),
|
||||
archiveCdn = if (jsonObject.isNull(ARCHIVE_CDN)) null else jsonObject.getInt(ARCHIVE_CDN),
|
||||
thumbnailRestoreState = ThumbnailRestoreState.deserialize(jsonObject.getInt(THUMBNAIL_RESTORE_STATE)),
|
||||
archiveTransferState = ArchiveTransferState.deserialize(jsonObject.getInt(ARCHIVE_TRANSFER_STATE)),
|
||||
uuid = UuidUtil.parseOrNull(jsonObject.getString(ATTACHMENT_UUID)),
|
||||
metadata = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
} else {
|
||||
listOf(getAttachment(cursor))
|
||||
}
|
||||
} catch (e: JSONException) {
|
||||
throw AssertionError(e)
|
||||
}
|
||||
}
|
||||
|
||||
fun hasStickerAttachments(): Boolean {
|
||||
return readableDatabase
|
||||
.exists(TABLE_NAME)
|
||||
@@ -3395,7 +3314,7 @@ class AttachmentTable(
|
||||
"""
|
||||
}
|
||||
|
||||
private fun getAttachment(cursor: Cursor): DatabaseAttachment {
|
||||
internal fun getAttachment(cursor: Cursor): DatabaseAttachment {
|
||||
val contentType = cursor.requireString(CONTENT_TYPE)
|
||||
|
||||
return DatabaseAttachment(
|
||||
@@ -3438,7 +3357,7 @@ class AttachmentTable(
|
||||
}
|
||||
|
||||
private fun Cursor.readAttachments(): List<DatabaseAttachment> {
|
||||
return getAttachments(this)
|
||||
return listOf(getAttachment(this))
|
||||
}
|
||||
|
||||
private fun Cursor.readAttachment(): DatabaseAttachment {
|
||||
|
||||
@@ -245,10 +245,8 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun from(cursor: Cursor): MediaRecord {
|
||||
val attachments = SignalDatabase.attachments.getAttachments(cursor)
|
||||
|
||||
return MediaRecord(
|
||||
attachment = if (attachments.isNotEmpty()) attachments[0] else null,
|
||||
attachment = SignalDatabase.attachments.getAttachment(cursor),
|
||||
recipientId = RecipientId.from(cursor.requireLong(MessageTable.FROM_RECIPIENT_ID)),
|
||||
threadId = cursor.requireLong(MessageTable.THREAD_ID),
|
||||
threadRecipientId = RecipientId.from(cursor.requireLong(THREAD_RECIPIENT_ID)),
|
||||
|
||||
@@ -393,48 +393,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
DELETED_BY
|
||||
)
|
||||
|
||||
private val MMS_PROJECTION: Array<String> = MMS_PROJECTION_BASE + "NULL AS ${AttachmentTable.ATTACHMENT_JSON_ALIAS}"
|
||||
|
||||
private val MMS_PROJECTION_WITH_ATTACHMENTS: Array<String> = MMS_PROJECTION_BASE +
|
||||
"""
|
||||
json_group_array(
|
||||
json_object(
|
||||
'${AttachmentTable.ID}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.ID},
|
||||
'${AttachmentTable.MESSAGE_ID}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.MESSAGE_ID},
|
||||
'${AttachmentTable.DATA_SIZE}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.DATA_SIZE},
|
||||
'${AttachmentTable.FILE_NAME}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.FILE_NAME},
|
||||
'${AttachmentTable.DATA_FILE}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.DATA_FILE},
|
||||
'${AttachmentTable.THUMBNAIL_FILE}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.THUMBNAIL_FILE},
|
||||
'${AttachmentTable.CONTENT_TYPE}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.CONTENT_TYPE},
|
||||
'${AttachmentTable.CDN_NUMBER}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.CDN_NUMBER},
|
||||
'${AttachmentTable.REMOTE_LOCATION}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.REMOTE_LOCATION},
|
||||
'${AttachmentTable.FAST_PREFLIGHT_ID}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.FAST_PREFLIGHT_ID},
|
||||
'${AttachmentTable.VOICE_NOTE}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.VOICE_NOTE},
|
||||
'${AttachmentTable.BORDERLESS}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.BORDERLESS},
|
||||
'${AttachmentTable.VIDEO_GIF}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.VIDEO_GIF},
|
||||
'${AttachmentTable.WIDTH}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.WIDTH},
|
||||
'${AttachmentTable.HEIGHT}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.HEIGHT},
|
||||
'${AttachmentTable.QUOTE}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.QUOTE},
|
||||
'${AttachmentTable.REMOTE_KEY}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.REMOTE_KEY},
|
||||
'${AttachmentTable.TRANSFER_STATE}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.TRANSFER_STATE},
|
||||
'${AttachmentTable.CAPTION}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.CAPTION},
|
||||
'${AttachmentTable.STICKER_PACK_ID}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.STICKER_PACK_ID},
|
||||
'${AttachmentTable.STICKER_PACK_KEY}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.STICKER_PACK_KEY},
|
||||
'${AttachmentTable.STICKER_ID}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.STICKER_ID},
|
||||
'${AttachmentTable.STICKER_EMOJI}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.STICKER_EMOJI},
|
||||
'${AttachmentTable.BLUR_HASH}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.BLUR_HASH},
|
||||
'${AttachmentTable.TRANSFORM_PROPERTIES}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.TRANSFORM_PROPERTIES},
|
||||
'${AttachmentTable.DISPLAY_ORDER}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.DISPLAY_ORDER},
|
||||
'${AttachmentTable.UPLOAD_TIMESTAMP}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.UPLOAD_TIMESTAMP},
|
||||
'${AttachmentTable.DATA_HASH_END}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.DATA_HASH_END},
|
||||
'${AttachmentTable.ARCHIVE_CDN}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.ARCHIVE_CDN},
|
||||
'${AttachmentTable.THUMBNAIL_RESTORE_STATE}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.THUMBNAIL_RESTORE_STATE},
|
||||
'${AttachmentTable.ARCHIVE_TRANSFER_STATE}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.ARCHIVE_TRANSFER_STATE},
|
||||
'${AttachmentTable.ATTACHMENT_UUID}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.ATTACHMENT_UUID},
|
||||
'${AttachmentTable.QUOTE_TARGET_CONTENT_TYPE}', ${AttachmentTable.TABLE_NAME}.${AttachmentTable.QUOTE_TARGET_CONTENT_TYPE}
|
||||
)
|
||||
) AS ${AttachmentTable.ATTACHMENT_JSON_ALIAS}
|
||||
""".toSingleLine()
|
||||
private val MMS_PROJECTION: Array<String> = MMS_PROJECTION_BASE
|
||||
|
||||
private const val IS_STORY_CLAUSE = "$STORY_TYPE > 0 AND $DELETED_BY IS NULL AND $STORY_ARCHIVED = 0"
|
||||
private const val IS_ARCHIVED_STORY_CLAUSE = "$STORY_TYPE > 0 AND $DELETED_BY IS NULL AND $STORY_ARCHIVED > 0"
|
||||
@@ -534,6 +493,11 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
return MmsReader(cursor)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun withAttachmentData(record: MessageRecord): MessageRecord {
|
||||
return record.withAttachments()
|
||||
}
|
||||
|
||||
private fun getSharedContacts(cursor: Cursor, attachments: List<DatabaseAttachment>): List<Contact> {
|
||||
val serializedContacts: String? = cursor.requireString(SHARED_CONTACTS)
|
||||
|
||||
@@ -666,7 +630,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
|
||||
fun getExpirationStartedMessages(): Cursor {
|
||||
val where = "$EXPIRE_STARTED > 0"
|
||||
return rawQueryWithAttachments(where, null)
|
||||
return queryMessages(where, null)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1418,12 +1382,12 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
whereArgs = buildArgs(threadId)
|
||||
}
|
||||
|
||||
return MmsReader(rawQueryWithAttachments(where, whereArgs))
|
||||
return MmsReader(queryMessages(where, whereArgs))
|
||||
}
|
||||
|
||||
fun getAllOutgoingStories(reverse: Boolean, limit: Int): Reader {
|
||||
val where = "$IS_STORY_CLAUSE AND ($outgoingTypeClause)"
|
||||
return MmsReader(rawQueryWithAttachments(where, null, reverse, limit.toLong()))
|
||||
return MmsReader(queryMessages(where, null, reverse, limit.toLong()))
|
||||
}
|
||||
|
||||
fun markAllIncomingStoriesRead(): List<MarkedMessageInfo> {
|
||||
@@ -1465,7 +1429,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
val threadId = threads.getThreadIdIfExistsFor(recipientId)
|
||||
val where = "$IS_STORY_CLAUSE AND $THREAD_ID = ?"
|
||||
val whereArgs = buildArgs(threadId)
|
||||
val cursor = rawQueryWithAttachments(where, whereArgs, false, limit.toLong())
|
||||
val cursor = queryMessages(where, whereArgs, false, limit.toLong())
|
||||
return MmsReader(cursor)
|
||||
}
|
||||
|
||||
@@ -1473,7 +1437,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
val threadId = threads.getThreadIdIfExistsFor(recipientId)
|
||||
val query = "$IS_STORY_CLAUSE AND NOT ($outgoingTypeClause) AND $THREAD_ID = ? AND $VIEWED_COLUMN = ?"
|
||||
val args = buildArgs(threadId, 0)
|
||||
return MmsReader(rawQueryWithAttachments(query, args, false, limit.toLong()))
|
||||
return MmsReader(queryMessages(query, args, false, limit.toLong()))
|
||||
}
|
||||
|
||||
fun getUnreadMissedCallCount(): Long {
|
||||
@@ -1636,7 +1600,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
fun getStoryReplies(parentStoryId: Long): Cursor {
|
||||
val where = "$PARENT_STORY_ID = ?"
|
||||
val whereArgs = buildArgs(parentStoryId)
|
||||
return rawQueryWithAttachments(where, whereArgs, false, 0)
|
||||
return queryMessages(where, whereArgs, false, 0)
|
||||
}
|
||||
|
||||
fun getNumberOfStoryReplies(parentStoryId: Long): Int {
|
||||
@@ -1785,7 +1749,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
val storyClause = if (includeActive) "$STORY_TYPE > 0 AND $DELETED_BY IS NULL" else IS_ARCHIVED_STORY_CLAUSE
|
||||
val where = "$storyClause AND ($outgoingTypeClause)"
|
||||
val order = if (sortNewest) "$TABLE_NAME.$DATE_SENT DESC" else "$TABLE_NAME.$DATE_SENT ASC"
|
||||
return MmsReader(rawQueryWithAttachments(where, null, orderBy = order, limit = limit.toLong(), offset = offset.toLong()))
|
||||
return MmsReader(queryMessages(where, null, orderBy = order, limit = limit.toLong(), offset = offset.toLong()))
|
||||
}
|
||||
|
||||
fun getOldestArchivedStorySentTimestamp(): Long? {
|
||||
@@ -2121,17 +2085,15 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
/**
|
||||
* Note: [reverse] and [orderBy] are mutually exclusive. If you want the order to be reversed, explicitly use 'ASC' or 'DESC'
|
||||
*/
|
||||
private fun rawQueryWithAttachments(where: String, arguments: Array<String>?, reverse: Boolean = false, limit: Long = 0, offset: Long = 0, orderBy: String = ""): Cursor {
|
||||
private fun queryMessages(where: String, arguments: Array<String>?, reverse: Boolean = false, limit: Long = 0, offset: Long = 0, orderBy: String = ""): Cursor {
|
||||
val database = databaseHelper.signalReadableDatabase
|
||||
var rawQueryString = """
|
||||
SELECT
|
||||
${Util.join(MMS_PROJECTION_WITH_ATTACHMENTS, ",")}
|
||||
FROM
|
||||
$TABLE_NAME LEFT OUTER JOIN ${AttachmentTable.TABLE_NAME} ON ($TABLE_NAME.$ID = ${AttachmentTable.TABLE_NAME}.${AttachmentTable.MESSAGE_ID})
|
||||
WHERE
|
||||
$where
|
||||
GROUP BY
|
||||
$TABLE_NAME.$ID
|
||||
SELECT
|
||||
${Util.join(MMS_PROJECTION, ",")}
|
||||
FROM
|
||||
$TABLE_NAME
|
||||
WHERE
|
||||
$where
|
||||
""".toSingleLine()
|
||||
|
||||
if (orderBy.isNotEmpty()) {
|
||||
@@ -2151,24 +2113,24 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
}
|
||||
|
||||
private fun internalGetMessage(messageId: Long): Cursor {
|
||||
return rawQueryWithAttachments(RAW_ID_WHERE, buildArgs(messageId))
|
||||
return queryMessages(RAW_ID_WHERE, buildArgs(messageId))
|
||||
}
|
||||
|
||||
@Throws(NoSuchMessageException::class)
|
||||
fun getMessageRecord(messageId: Long): MessageRecord {
|
||||
rawQueryWithAttachments(RAW_ID_WHERE, arrayOf(messageId.toString() + "")).use { cursor ->
|
||||
queryMessages(RAW_ID_WHERE, arrayOf(messageId.toString() + "")).use { cursor ->
|
||||
return MmsReader(cursor).getNext() ?: throw NoSuchMessageException("No message for ID: $messageId")
|
||||
}
|
||||
}
|
||||
|
||||
fun getMessageRecordOrNull(messageId: Long): MessageRecord? {
|
||||
rawQueryWithAttachments(RAW_ID_WHERE, buildArgs(messageId)).use { cursor ->
|
||||
queryMessages(RAW_ID_WHERE, buildArgs(messageId)).use { cursor ->
|
||||
return MmsReader(cursor).firstOrNull()
|
||||
}
|
||||
}
|
||||
|
||||
fun getPinnedMessages(threadId: Long, orderByPinned: Boolean): List<MmsMessageRecord> {
|
||||
val cursor = rawQueryWithAttachments(
|
||||
val cursor = queryMessages(
|
||||
where = "$THREAD_ID = ? AND $PINNED_UNTIL > 0",
|
||||
arguments = buildArgs(threadId),
|
||||
reverse = true,
|
||||
@@ -2213,7 +2175,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
|
||||
fun getMessages(messageIds: Collection<Long?>): MmsReader {
|
||||
val ids = TextUtils.join(",", messageIds)
|
||||
return mmsReaderFor(rawQueryWithAttachments("$TABLE_NAME.$ID IN ($ids)", null))
|
||||
return mmsReaderFor(queryMessages("$TABLE_NAME.$ID IN ($ids)", null))
|
||||
}
|
||||
|
||||
fun getMessageEditHistory(id: Long): MmsReader {
|
||||
@@ -2672,7 +2634,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
|
||||
@Throws(MmsException::class, NoSuchMessageException::class)
|
||||
fun getOutgoingMessage(messageId: Long): OutgoingMessage {
|
||||
return rawQueryWithAttachments(RAW_ID_WHERE, arrayOf(messageId.toString())).readToSingleObject { cursor ->
|
||||
return queryMessages(RAW_ID_WHERE, arrayOf(messageId.toString())).readToSingleObject { cursor ->
|
||||
val associatedAttachments = attachments.getAttachmentsForMessage(messageId)
|
||||
val associatedPoll = polls.getPollForOutgoingMessage(messageId)
|
||||
val mentions = mentions.getMentionsForMessage(messageId)
|
||||
@@ -4236,7 +4198,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
val where = "$TABLE_NAME.$THREAD_ID = ? AND $TABLE_NAME.$DATE_RECEIVED >= ? AND $TABLE_NAME.$SCHEDULED_DATE = -1 AND $TABLE_NAME.$LATEST_REVISION_ID IS NULL"
|
||||
val args = buildArgs(threadId, timestamp)
|
||||
|
||||
return mmsReaderFor(rawQueryWithAttachments(where, args, false, limit)).use { reader ->
|
||||
return mmsReaderFor(queryMessages(where, args, false, limit)).use { reader ->
|
||||
reader.filterNotNull()
|
||||
}
|
||||
}
|
||||
@@ -4896,7 +4858,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
return getConversationSnippetCursor(threadId)
|
||||
.readToSingleObject { cursor ->
|
||||
val id = cursor.requireLong(ID)
|
||||
messages.getMessageRecord(id)
|
||||
messages.getMessageRecord(id).withAttachments()
|
||||
} ?: throw NoSuchMessageException("no message")
|
||||
}
|
||||
|
||||
@@ -6455,7 +6417,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
val mismatches = getMismatchedIdentities(mismatchDocument)
|
||||
val networkFailures = getFailures(networkDocument)
|
||||
|
||||
val attachments = attachments.getAttachments(cursor)
|
||||
val attachments: List<DatabaseAttachment> = emptyList()
|
||||
|
||||
val contacts = getSharedContacts(cursor, attachments)
|
||||
val contactAttachments = contacts.mapNotNull { it.avatarAttachment }.toSet()
|
||||
@@ -6465,7 +6427,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
|
||||
val slideDeck = buildSlideDeck(attachments.filterNot { contactAttachments.contains(it) }.filterNot { previewAttachments.contains(it) })
|
||||
|
||||
val quote = getQuote(cursor)
|
||||
val quote = getQuote(cursor, attachments)
|
||||
|
||||
val messageRanges: BodyRangeList? = if (messageRangesData != null) {
|
||||
try {
|
||||
@@ -6563,7 +6525,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
return emptySet()
|
||||
}
|
||||
|
||||
private fun getQuote(cursor: Cursor): Quote? {
|
||||
private fun getQuote(cursor: Cursor, attachments: List<DatabaseAttachment>): Quote? {
|
||||
val quoteId = cursor.requireLong(QUOTE_ID)
|
||||
val quoteAuthor = cursor.requireLong(QUOTE_AUTHOR)
|
||||
var quoteText: CharSequence? = cursor.requireString(QUOTE_BODY)
|
||||
@@ -6572,7 +6534,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
var quoteMentions = parseQuoteMentions(cursor)
|
||||
val bodyRanges = parseQuoteBodyRanges(cursor)
|
||||
|
||||
val attachments = attachments.getAttachments(cursor)
|
||||
val quoteAttachments: List<Attachment> = attachments.filter { it.quote }
|
||||
val quoteDeck = SlideDeck(quoteAttachments)
|
||||
|
||||
@@ -6632,3 +6593,21 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun MessageRecord.withAttachments(): MessageRecord {
|
||||
if (this !is MmsMessageRecord) return this
|
||||
val fetchedAttachments = SignalDatabase.attachments.getAttachmentsForMessage(id)
|
||||
return if (fetchedAttachments.isNotEmpty()) withAttachments(fetchedAttachments) else this
|
||||
}
|
||||
|
||||
fun List<MessageRecord>.withAttachments(): List<MessageRecord> {
|
||||
if (isEmpty()) return this
|
||||
val allAttachments = SignalDatabase.attachments.getAttachmentsForMessages(map { it.id })
|
||||
return map { record ->
|
||||
if (record is MmsMessageRecord) {
|
||||
allAttachments[record.id]?.let { record.withAttachments(it) } ?: record
|
||||
} else {
|
||||
record
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ package org.thoughtcrime.securesms.jobs
|
||||
import org.signal.core.util.logging.Log
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.MessageId
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.jobmanager.Job
|
||||
import kotlin.time.Duration.Companion.days
|
||||
@@ -52,7 +51,7 @@ class RetryPendingSendsJob private constructor(parameters: Parameters) : Job(par
|
||||
reader.forEach { message ->
|
||||
val threadRecipient = SignalDatabase.threads.getRecipientForThreadId(message.threadId)
|
||||
if (threadRecipient != null) {
|
||||
val hasMedia = (message as? MmsMessageRecord)?.slideDeck?.slides?.isNotEmpty() == true
|
||||
val hasMedia = SignalDatabase.attachments.getAttachmentsForMessage(message.id).isNotEmpty()
|
||||
Log.d(TAG, "[${message.dateSent}] Found pending message MessageId::${message.id}, enqueueing second check job")
|
||||
AppDependencies.jobManager.add(RetryPendingSendSecondCheckJob(MessageId(message.id), threadRecipient, hasMedia))
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.signal.core.util.logging.Log;
|
||||
import org.thoughtcrime.securesms.conversation.ConversationMessage;
|
||||
import org.thoughtcrime.securesms.database.MessageTable;
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase;
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord;
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -45,7 +46,11 @@ class LongMessageRepository {
|
||||
@WorkerThread
|
||||
private Optional<MmsMessageRecord> getMmsMessage(@NonNull MessageTable mmsDatabase, long messageId) {
|
||||
try (Cursor cursor = mmsDatabase.getMessageCursor(messageId)) {
|
||||
return Optional.ofNullable((MmsMessageRecord) MessageTable.mmsReaderFor(cursor).getNext());
|
||||
MessageRecord record = MessageTable.mmsReaderFor(cursor).getNext();
|
||||
if (record != null) {
|
||||
record = MessageTable.withAttachmentData(record);
|
||||
}
|
||||
return Optional.ofNullable((MmsMessageRecord) record);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase.Companion.media
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.withAttachments
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceDeleteSyncJob
|
||||
import org.thoughtcrime.securesms.longmessage.resolveBody
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
@@ -85,7 +86,7 @@ class MediaPreviewRepository {
|
||||
}
|
||||
|
||||
val messageIds = mediaRecords.mapNotNull { it.attachment?.mmsId }.toSet()
|
||||
val messages: Map<Long, SpannableString> = SignalDatabase.messages.getMessages(messageIds)
|
||||
val messages: Map<Long, SpannableString> = SignalDatabase.messages.getMessages(messageIds).toList().withAttachments()
|
||||
.map { it as MmsMessageRecord }
|
||||
.associate { it.id to it.resolveBody(context).getDisplayBody(context) }
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.thoughtcrime.securesms.database.model.MessageId
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList
|
||||
import org.thoughtcrime.securesms.database.model.toBodyRangeList
|
||||
import org.thoughtcrime.securesms.database.withAttachments
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.groups.GroupId
|
||||
import org.thoughtcrime.securesms.jobs.AttachmentDownloadJob
|
||||
@@ -69,7 +70,8 @@ object EditMessageProcessor {
|
||||
val isMediaMessage = message.isMediaMessage
|
||||
val groupId: GroupId.V2? = message.groupV2?.groupId
|
||||
|
||||
val originalMessage = targetMessage.originalMessageId?.let { SignalDatabase.messages.getMessageRecord(it.id) } ?: targetMessage
|
||||
val originalMessageWithoutAttachments = targetMessage.originalMessageId?.let { SignalDatabase.messages.getMessageRecord(it.id) } ?: targetMessage
|
||||
val originalMessage = originalMessageWithoutAttachments.withAttachments()
|
||||
val validTiming = MessageConstraintsUtil.isValidEditMessageReceive(originalMessage, senderRecipient, envelope.serverTimestamp!!)
|
||||
val validAuthor = senderRecipient.id == originalMessage.fromRecipient.id
|
||||
val validGroup = groupId == targetThreadRecipient.groupId.orNull()
|
||||
|
||||
@@ -4,6 +4,7 @@ import org.signal.paging.PagedDataSource
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.StoryType
|
||||
import org.thoughtcrime.securesms.database.withAttachments
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
|
||||
class StoryArchivePagedDataSource(
|
||||
@@ -17,25 +18,29 @@ class StoryArchivePagedDataSource(
|
||||
}
|
||||
|
||||
override fun load(start: Int, length: Int, totalSize: Int, cancellationSignal: PagedDataSource.CancellationSignal): List<ArchivedStoryItem> {
|
||||
return SignalDatabase.messages.getArchiveScreenStoriesPage(includeActive, sortNewest, start, length).use { reader ->
|
||||
val rawRecords = SignalDatabase.messages.getArchiveScreenStoriesPage(includeActive, sortNewest, start, length).use { reader ->
|
||||
reader.mapNotNull { record ->
|
||||
if (cancellationSignal.isCanceled) return@use emptyList()
|
||||
val mmsRecord = record as? MmsMessageRecord
|
||||
ArchivedStoryItem(
|
||||
messageId = record.id,
|
||||
dateSent = record.dateSent,
|
||||
thumbnailUri = mmsRecord?.slideDeck?.thumbnailSlide?.uri,
|
||||
blurHash = mmsRecord?.slideDeck?.thumbnailSlide?.placeholderBlur,
|
||||
storyType = mmsRecord?.storyType ?: StoryType.NONE,
|
||||
body = record.body
|
||||
)
|
||||
record
|
||||
}
|
||||
}
|
||||
|
||||
return rawRecords.withAttachments().map { record ->
|
||||
val mmsRecord = record as? MmsMessageRecord
|
||||
ArchivedStoryItem(
|
||||
messageId = record.id,
|
||||
dateSent = record.dateSent,
|
||||
thumbnailUri = mmsRecord?.slideDeck?.thumbnailSlide?.uri,
|
||||
blurHash = mmsRecord?.slideDeck?.thumbnailSlide?.placeholderBlur,
|
||||
storyType = mmsRecord?.storyType ?: StoryType.NONE,
|
||||
body = record.body
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun load(key: Long): ArchivedStoryItem? {
|
||||
val record = SignalDatabase.messages.getMessageRecordOrNull(key) ?: return null
|
||||
val mmsRecord = record as? MmsMessageRecord
|
||||
val mmsRecord = record.withAttachments() as? MmsMessageRecord
|
||||
return ArchivedStoryItem(
|
||||
messageId = record.id,
|
||||
dateSent = record.dateSent,
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.thoughtcrime.securesms.database.GroupReceiptTable
|
||||
import org.thoughtcrime.securesms.database.RxDatabaseObserver
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.database.withAttachments
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.sms.MessageSender
|
||||
|
||||
@@ -27,14 +28,20 @@ class MyStoriesRepository(context: Context) {
|
||||
.conversationList
|
||||
.toObservable()
|
||||
.map {
|
||||
val storiesMap = mutableMapOf<Recipient, List<MessageRecord>>()
|
||||
val allRecords = mutableListOf<MessageRecord>()
|
||||
SignalDatabase.messages.getAllOutgoingStories(true, -1).use {
|
||||
for (messageRecord in it) {
|
||||
val currentList = storiesMap[messageRecord.toRecipient] ?: emptyList()
|
||||
storiesMap[messageRecord.toRecipient] = (currentList + messageRecord)
|
||||
allRecords.add(messageRecord)
|
||||
}
|
||||
}
|
||||
|
||||
val withAttachments = allRecords.withAttachments()
|
||||
val storiesMap = mutableMapOf<Recipient, List<MessageRecord>>()
|
||||
for (record in withAttachments) {
|
||||
val currentList = storiesMap[record.toRecipient] ?: emptyList()
|
||||
storiesMap[record.toRecipient] = (currentList + record)
|
||||
}
|
||||
|
||||
storiesMap.toSortedMap(MyStoryBiasComparator()).map { (r, m) -> createDistributionSet(r, m) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.thoughtcrime.securesms.database.MessageTable
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.DistributionListId
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.withAttachments
|
||||
import org.thoughtcrime.securesms.keyvalue.SignalStore
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
import org.thoughtcrime.securesms.recipients.RecipientId
|
||||
@@ -17,7 +18,7 @@ open class StoryViewerRepository {
|
||||
fun getFirstStory(recipientId: RecipientId, storyId: Long): Single<MmsMessageRecord> {
|
||||
return if (storyId > 0) {
|
||||
Single.fromCallable {
|
||||
SignalDatabase.messages.getMessageRecord(storyId) as MmsMessageRecord
|
||||
SignalDatabase.messages.getMessageRecord(storyId).withAttachments() as MmsMessageRecord
|
||||
}
|
||||
} else {
|
||||
Single.fromCallable {
|
||||
@@ -32,7 +33,7 @@ open class StoryViewerRepository {
|
||||
SignalDatabase.messages.getAllStoriesFor(recipientId, 1)
|
||||
}
|
||||
}
|
||||
reader.use { it.iterator().next() } as MmsMessageRecord
|
||||
reader.use { it.iterator().next() }.withAttachments() as MmsMessageRecord
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.database.model.MessageId
|
||||
import org.thoughtcrime.securesms.database.model.MessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.model.databaseprotos.StoryTextPost
|
||||
import org.thoughtcrime.securesms.database.withAttachments
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.jobs.MultiDeviceViewedUpdateJob
|
||||
import org.thoughtcrime.securesms.jobs.SendViewedReceiptJob
|
||||
@@ -58,7 +59,7 @@ open class StoryViewerPageRepository(context: Context, private val storyViewStat
|
||||
recipient.isMyStory && it.toRecipient.isGroup
|
||||
}
|
||||
|
||||
emitter.onNext(results)
|
||||
emitter.onNext(results.withAttachments())
|
||||
}
|
||||
|
||||
val storyObserver = DatabaseObserver.Observer {
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.thoughtcrime.securesms.database.MessageTypes
|
||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
||||
import org.thoughtcrime.securesms.database.model.MessageId
|
||||
import org.thoughtcrime.securesms.database.model.MmsMessageRecord
|
||||
import org.thoughtcrime.securesms.database.withAttachments
|
||||
import org.thoughtcrime.securesms.dependencies.AppDependencies
|
||||
import org.thoughtcrime.securesms.recipients.Recipient
|
||||
|
||||
@@ -16,20 +17,20 @@ class StoryGroupReplyDataSource(private val parentStoryId: Long) : PagedDataSour
|
||||
}
|
||||
|
||||
override fun load(start: Int, length: Int, totalSize: Int, cancellationSignal: PagedDataSource.CancellationSignal): MutableList<ReplyBody> {
|
||||
val results: MutableList<ReplyBody> = ArrayList(length)
|
||||
val rawRecords = mutableListOf<MmsMessageRecord>()
|
||||
SignalDatabase.messages.getStoryReplies(parentStoryId).use { cursor ->
|
||||
cursor.moveToPosition(start - 1)
|
||||
val mmsReader = MessageTable.MmsReader(cursor)
|
||||
while (cursor.moveToNext() && cursor.position < start + length) {
|
||||
results.add(readRowFromRecord(mmsReader.getCurrent() as MmsMessageRecord))
|
||||
rawRecords.add(mmsReader.getCurrent() as MmsMessageRecord)
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
return rawRecords.withAttachments().map { readRowFromRecord(it as MmsMessageRecord) }.toMutableList()
|
||||
}
|
||||
|
||||
override fun load(key: MessageId): ReplyBody {
|
||||
return readRowFromRecord(SignalDatabase.messages.getMessageRecord(key.id) as MmsMessageRecord)
|
||||
return readRowFromRecord(SignalDatabase.messages.getMessageRecord(key.id).withAttachments() as MmsMessageRecord)
|
||||
}
|
||||
|
||||
override fun getKey(data: ReplyBody): MessageId {
|
||||
|
||||
Reference in New Issue
Block a user