Add the ability to do an export of a single chat.

This commit is contained in:
Greyson Parrelli
2026-03-16 13:57:51 -04:00
committed by Michelle Tang
parent 2f41d15a41
commit 2b163a9acd
12 changed files with 1469 additions and 22 deletions
@@ -84,11 +84,6 @@ import org.thoughtcrime.securesms.crypto.AttachmentSecret
import org.thoughtcrime.securesms.crypto.ClassicDecryptingPartInputStream
import org.thoughtcrime.securesms.crypto.ModernDecryptingPartInputStream
import org.thoughtcrime.securesms.crypto.ModernEncryptingPartOutputStream
import org.thoughtcrime.securesms.database.AttachmentTable.ArchiveTransferState.COPY_PENDING
import org.thoughtcrime.securesms.database.AttachmentTable.ArchiveTransferState.FINISHED
import org.thoughtcrime.securesms.database.AttachmentTable.ArchiveTransferState.NONE
import org.thoughtcrime.securesms.database.AttachmentTable.ArchiveTransferState.PERMANENT_FAILURE
import org.thoughtcrime.securesms.database.AttachmentTable.ArchiveTransferState.UPLOAD_IN_PROGRESS
import org.thoughtcrime.securesms.database.AttachmentTable.Companion.DATA_FILE
import org.thoughtcrime.securesms.database.AttachmentTable.Companion.DATA_HASH_END
import org.thoughtcrime.securesms.database.AttachmentTable.Companion.PREUPLOAD_MESSAGE_ID
@@ -496,6 +491,32 @@ class AttachmentTable(
.flatten()
}
/**
* Returns the number of attachments that will be exported for a plaintext export of a given thread.
* Used for estimating progress.
*/
fun getPlaintextExportableAttachmentCountForThread(threadId: Long): Int {
return readableDatabase.rawQuery(
"""
SELECT COUNT(*)
FROM $TABLE_NAME
INNER JOIN ${MessageTable.TABLE_NAME} ON $TABLE_NAME.$MESSAGE_ID = ${MessageTable.TABLE_NAME}.${MessageTable.ID}
WHERE ${MessageTable.TABLE_NAME}.${MessageTable.THREAD_ID} = ?
AND ${MessageTable.TABLE_NAME}.${MessageTable.STORY_TYPE} = 0
AND ${MessageTable.TABLE_NAME}.${MessageTable.PARENT_STORY_ID} <= 0
AND ${MessageTable.TABLE_NAME}.${MessageTable.SCHEDULED_DATE} = -1
AND ${MessageTable.TABLE_NAME}.${MessageTable.LATEST_REVISION_ID} IS NULL
AND ${MessageTable.TABLE_NAME}.${MessageTable.VIEW_ONCE} = 0
AND ${MessageTable.TABLE_NAME}.${MessageTable.DELETED_BY} IS NULL
AND $TABLE_NAME.$DATA_FILE IS NOT NULL
AND $TABLE_NAME.$QUOTE = 0
""".trimIndent(),
arrayOf(threadId.toString())
).use { cursor ->
if (cursor.moveToFirst()) cursor.getInt(0) else 0
}
}
fun getAttachmentsForMessagesArchive(mmsIds: Collection<Long>): Map<Long, List<DatabaseAttachment>> {
if (mmsIds.isEmpty()) {
return emptyMap()
@@ -5372,14 +5372,14 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat
* A cursor containing all of the messages in a given thread, in the proper order, respecting offset/limit.
* This does *not* have attachments in it.
*/
fun getConversation(threadId: Long, offset: Long, limit: Long): Cursor {
fun getConversation(threadId: Long, offset: Long = 0, limit: Long = 0, dateReceiveOrderBy: String = "DESC"): Cursor {
val limitStr: String = if (limit > 0 || offset > 0) "$offset, $limit" else ""
return readableDatabase
.select(*MMS_PROJECTION)
.from("$TABLE_NAME INDEXED BY $INDEX_THREAD_STORY_SCHEDULED_DATE_LATEST_REVISION_ID")
.where("$THREAD_ID = ? AND $STORY_TYPE = ? AND $PARENT_STORY_ID <= ? AND $SCHEDULED_DATE = ? AND $LATEST_REVISION_ID IS NULL", threadId, 0, 0, -1)
.orderBy("$DATE_RECEIVED DESC")
.orderBy("$DATE_RECEIVED $dateReceiveOrderBy")
.limit(limitStr)
.run()
}