Add links to the all media view.

This commit is contained in:
Greyson Parrelli
2026-03-21 09:34:23 -04:00
committed by Cody Henthorne
parent 25b01a30be
commit 08491579dd
8 changed files with 323 additions and 20 deletions
@@ -61,8 +61,9 @@ 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.FROM_RECIPIENT_ID},
${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} as $THREAD_RECIPIENT_ID
${MessageTable.TABLE_NAME}.${MessageTable.FROM_RECIPIENT_ID},
${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} as $THREAD_RECIPIENT_ID,
${MessageTable.TABLE_NAME}.${MessageTable.LINK_PREVIEWS}
FROM
${AttachmentTable.TABLE_NAME}
LEFT JOIN ${MessageTable.TABLE_NAME} ON ${AttachmentTable.TABLE_NAME}.${AttachmentTable.MESSAGE_ID} = ${MessageTable.TABLE_NAME}.${MessageTable.ID}
@@ -135,6 +136,69 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
"""
)
private val LINK_MEDIA_QUERY = """
SELECT
${AttachmentTable.TABLE_NAME}.${AttachmentTable.ID} AS ${AttachmentTable.ID},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.CONTENT_TYPE},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.MESSAGE_ID},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.TRANSFER_STATE},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.DATA_SIZE},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.FILE_NAME},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.DATA_FILE},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.THUMBNAIL_FILE},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.CDN_NUMBER},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.REMOTE_LOCATION},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.REMOTE_KEY},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.REMOTE_DIGEST},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.FAST_PREFLIGHT_ID},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.VOICE_NOTE},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.BORDERLESS},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.VIDEO_GIF},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.WIDTH},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.HEIGHT},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.QUOTE},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.QUOTE_TARGET_CONTENT_TYPE},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.STICKER_PACK_ID},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.STICKER_PACK_KEY},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.STICKER_ID},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.STICKER_EMOJI},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.BLUR_HASH},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.TRANSFORM_PROPERTIES},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.DISPLAY_ORDER},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.CAPTION},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.UPLOAD_TIMESTAMP},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.REMOTE_INCREMENTAL_DIGEST},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.REMOTE_INCREMENTAL_DIGEST_CHUNK_SIZE},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.DATA_HASH_END},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.ARCHIVE_CDN},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.THUMBNAIL_RESTORE_STATE},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.ARCHIVE_TRANSFER_STATE},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.ATTACHMENT_UUID},
${MessageTable.TABLE_NAME}.${MessageTable.TYPE},
${MessageTable.TABLE_NAME}.${MessageTable.DATE_SENT},
${MessageTable.TABLE_NAME}.${MessageTable.DATE_RECEIVED},
${MessageTable.TABLE_NAME}.${MessageTable.DATE_SERVER},
${MessageTable.TABLE_NAME}.${MessageTable.THREAD_ID},
${MessageTable.TABLE_NAME}.${MessageTable.FROM_RECIPIENT_ID},
${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} as $THREAD_RECIPIENT_ID,
${MessageTable.TABLE_NAME}.${MessageTable.LINK_PREVIEWS}
FROM
${MessageTable.TABLE_NAME}
LEFT JOIN ${AttachmentTable.TABLE_NAME} ON ${AttachmentTable.TABLE_NAME}.${AttachmentTable.MESSAGE_ID} = ${MessageTable.TABLE_NAME}.${MessageTable.ID}
AND ${AttachmentTable.TABLE_NAME}.${AttachmentTable.QUOTE} = 0
AND ${AttachmentTable.TABLE_NAME}.${AttachmentTable.STICKER_PACK_ID} IS NULL
LEFT JOIN ${ThreadTable.TABLE_NAME} ON ${ThreadTable.TABLE_NAME}.${ThreadTable.ID} = ${MessageTable.TABLE_NAME}.${MessageTable.THREAD_ID}
WHERE
${MessageTable.TABLE_NAME}.${MessageTable.THREAD_ID} __EQUALITY__ ? AND
${MessageTable.TABLE_NAME}.${MessageTable.LINK_PREVIEWS} IS NOT NULL AND
${MessageTable.TABLE_NAME}.${MessageTable.VIEW_ONCE} = 0 AND
${MessageTable.TABLE_NAME}.${MessageTable.STORY_TYPE} = 0 AND
${MessageTable.TABLE_NAME}.${MessageTable.LATEST_REVISION_ID} IS NULL AND
${MessageTable.TABLE_NAME}.${MessageTable.FROM_RECIPIENT_ID} > 0 AND
$THREAD_RECIPIENT_ID > 0 AND
${MessageTable.TABLE_NAME}.${MessageTable.SCHEDULED_DATE} < 0
"""
private val DOCUMENT_MEDIA_QUERY = String.format(
BASE_MEDIA_QUERY,
"""
@@ -180,6 +244,17 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
return readableDatabase.rawQuery(query, args)
}
fun getLinkMediaForThread(threadId: Long, sorting: Sorting): Cursor {
val orderBy = when (sorting) {
Sorting.Newest -> " ORDER BY ${MessageTable.TABLE_NAME}.${MessageTable.DATE_SENT} DESC"
Sorting.Oldest -> " ORDER BY ${MessageTable.TABLE_NAME}.${MessageTable.DATE_SENT} ASC"
Sorting.Largest -> " ORDER BY ${AttachmentTable.TABLE_NAME}.${AttachmentTable.DATA_SIZE} DESC"
}
val query = applyEqualityOperator(threadId, LINK_MEDIA_QUERY) + orderBy
val args = arrayOf(threadId.toString())
return readableDatabase.rawQuery(query, args)
}
fun getAllMediaForThread(threadId: Long, sorting: Sorting): Cursor {
val query = sorting.applyToQuery(applyEqualityOperator(threadId, ALL_MEDIA_QUERY))
val args = arrayOf(threadId.toString() + "")
@@ -236,7 +311,8 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
val threadRecipientId: RecipientId,
val threadId: Long,
val date: Long,
val isOutgoing: Boolean
val isOutgoing: Boolean,
val linkPreviewJson: String? = null
) {
val contentType: String?
@@ -245,8 +321,11 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
companion object {
@JvmStatic
fun from(cursor: Cursor): MediaRecord {
val linkPreviewIdx = cursor.getColumnIndex(MessageTable.LINK_PREVIEWS)
val attachmentIdIdx = cursor.getColumnIndex(AttachmentTable.ID)
val hasAttachment = attachmentIdIdx != -1 && !cursor.isNull(attachmentIdIdx)
return MediaRecord(
attachment = SignalDatabase.attachments.getAttachment(cursor),
attachment = if (hasAttachment) SignalDatabase.attachments.getAttachment(cursor) else null,
recipientId = RecipientId.from(cursor.requireLong(MessageTable.FROM_RECIPIENT_ID)),
threadId = cursor.requireLong(MessageTable.THREAD_ID),
threadRecipientId = RecipientId.from(cursor.requireLong(THREAD_RECIPIENT_ID)),
@@ -255,7 +334,8 @@ class MediaTable internal constructor(context: Context?, databaseHelper: SignalD
} else {
cursor.requireLong(MessageTable.DATE_RECEIVED)
},
isOutgoing = MessageTypes.isOutgoingMessageType(cursor.requireLong(MessageTable.TYPE))
isOutgoing = MessageTypes.isOutgoingMessageType(cursor.requireLong(MessageTable.TYPE)),
linkPreviewJson = if (linkPreviewIdx != -1) cursor.getString(linkPreviewIdx) else null
)
}
}
@@ -14,6 +14,7 @@ public abstract class MediaLoader extends AbstractCursorLoader {
GALLERY,
DOCUMENT,
AUDIO,
LINK,
ALL
}
}
@@ -40,6 +40,7 @@ public final class ThreadMediaLoader extends MediaLoader {
case GALLERY : return mediaDatabase.getGalleryMediaForThread(threadId, sorting);
case DOCUMENT: return mediaDatabase.getDocumentMediaForThread(threadId, sorting);
case AUDIO : return mediaDatabase.getAudioMediaForThread(threadId, sorting);
case LINK : return mediaDatabase.getLinkMediaForThread(threadId, sorting);
case ALL : return mediaDatabase.getAllMediaForThread(threadId, sorting);
default : throw new AssertionError();
}