Convert MediaTable to kotlin.

This commit is contained in:
Greyson Parrelli 2023-02-11 13:56:17 -05:00
parent af6f16bdb6
commit 408c288936
3 changed files with 275 additions and 302 deletions

View file

@ -11,7 +11,7 @@ class DataAndStorageSettingsRepository {
fun getTotalStorageUse(consumer: (Long) -> Unit) {
SignalExecutors.BOUNDED.execute {
val breakdown = SignalDatabase.media.storageBreakdown
val breakdown = SignalDatabase.media.getStorageBreakdown()
consumer(listOf(breakdown.audioSize, breakdown.documentSize, breakdown.photoSize, breakdown.videoSize).sum())
}

View file

@ -1,301 +0,0 @@
package org.thoughtcrime.securesms.database;
import android.annotation.SuppressLint;
import android.content.Context;
import android.database.Cursor;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.thoughtcrime.securesms.attachments.DatabaseAttachment;
import org.thoughtcrime.securesms.recipients.RecipientId;
import org.thoughtcrime.securesms.util.MediaUtil;
import java.util.List;
@SuppressLint({"RecipientIdDatabaseReferenceUsage", "ThreadIdDatabaseReferenceUsage"}) // Not a real table, just a view
public class MediaTable extends DatabaseTable {
public static final int ALL_THREADS = -1;
private static final String THREAD_RECIPIENT_ID = "THREAD_RECIPIENT_ID";
private static final String BASE_MEDIA_QUERY = "SELECT " + AttachmentTable.TABLE_NAME + "." + AttachmentTable.ROW_ID + " AS " + AttachmentTable.ROW_ID + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.CONTENT_TYPE + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.UNIQUE_ID + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.MMS_ID + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.TRANSFER_STATE + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.SIZE + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.FILE_NAME + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.DATA + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.CDN_NUMBER + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.CONTENT_LOCATION + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.CONTENT_DISPOSITION + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.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.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.VISUAL_HASH + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.TRANSFORM_PROPERTIES + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.DISPLAY_ORDER + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.CAPTION + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.NAME + ", "
+ AttachmentTable.TABLE_NAME + "." + AttachmentTable.UPLOAD_TIMESTAMP + ", "
+ 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.RECIPIENT_ID + ", "
+ ThreadTable.TABLE_NAME + "." + ThreadTable.RECIPIENT_ID + " as " + THREAD_RECIPIENT_ID + " "
+ "FROM " + AttachmentTable.TABLE_NAME + " LEFT JOIN " + MessageTable.TABLE_NAME
+ " ON " + AttachmentTable.TABLE_NAME + "." + AttachmentTable.MMS_ID + " = " + MessageTable.TABLE_NAME + "." + MessageTable.ID + " "
+ "LEFT JOIN " + ThreadTable.TABLE_NAME
+ " ON " + ThreadTable.TABLE_NAME + "." + ThreadTable.ID + " = " + MessageTable.TABLE_NAME + "." + MessageTable.THREAD_ID + " "
+ "WHERE " + AttachmentTable.MMS_ID + " IN (SELECT " + MessageTable.ID
+ " FROM " + MessageTable.TABLE_NAME
+ " WHERE " + MessageTable.THREAD_ID + " __EQUALITY__ ?) AND (%s) AND "
+ MessageTable.VIEW_ONCE + " = 0 AND "
+ MessageTable.STORY_TYPE + " = 0 AND "
+ AttachmentTable.DATA + " IS NOT NULL AND "
+ "(" + AttachmentTable.QUOTE + " = 0 OR (" + AttachmentTable.QUOTE + " = 1 AND " + AttachmentTable.DATA_HASH + " IS NULL)) AND "
+ AttachmentTable.STICKER_PACK_ID + " IS NULL AND "
+ MessageTable.TABLE_NAME + "." + MessageTable.RECIPIENT_ID + " > 0 AND "
+ THREAD_RECIPIENT_ID + " > 0";
private static final String UNIQUE_MEDIA_QUERY = "SELECT "
+ "MAX(" + AttachmentTable.SIZE + ") as " + AttachmentTable.SIZE + ", "
+ AttachmentTable.CONTENT_TYPE + " "
+ "FROM " + AttachmentTable.TABLE_NAME + " "
+ "WHERE " + AttachmentTable.STICKER_PACK_ID + " IS NULL AND " + AttachmentTable.TRANSFER_STATE + " = " + AttachmentTable.TRANSFER_PROGRESS_DONE + " "
+ "GROUP BY " + AttachmentTable.DATA;
private static final String GALLERY_MEDIA_QUERY = String.format(BASE_MEDIA_QUERY, AttachmentTable.CONTENT_TYPE + " NOT LIKE 'image/svg%' AND (" +
AttachmentTable.CONTENT_TYPE + " LIKE 'image/%' OR " +
AttachmentTable.CONTENT_TYPE + " LIKE 'video/%')");
private static final String AUDIO_MEDIA_QUERY = String.format(BASE_MEDIA_QUERY, AttachmentTable.CONTENT_TYPE + " LIKE 'audio/%'");
private static final String ALL_MEDIA_QUERY = String.format(BASE_MEDIA_QUERY, AttachmentTable.CONTENT_TYPE + " NOT LIKE 'text/x-signal-plain'");
private static final String DOCUMENT_MEDIA_QUERY = String.format(BASE_MEDIA_QUERY, AttachmentTable.CONTENT_TYPE + " LIKE 'image/svg%' OR (" +
AttachmentTable.CONTENT_TYPE + " NOT LIKE 'image/%' AND " +
AttachmentTable.CONTENT_TYPE + " NOT LIKE 'video/%' AND " +
AttachmentTable.CONTENT_TYPE + " NOT LIKE 'audio/%' AND " +
AttachmentTable.CONTENT_TYPE + " NOT LIKE 'text/x-signal-plain')");
MediaTable(Context context, SignalDatabase databaseHelper) {
super(context, databaseHelper);
}
public @NonNull Cursor getGalleryMediaForThread(long threadId, @NonNull Sorting sorting) {
SQLiteDatabase database = databaseHelper.getSignalReadableDatabase();
String query = sorting.applyToQuery(applyEqualityOperator(threadId, GALLERY_MEDIA_QUERY));
String[] args = {threadId + ""};
return database.rawQuery(query, args);
}
public @NonNull Cursor getDocumentMediaForThread(long threadId, @NonNull Sorting sorting) {
SQLiteDatabase database = databaseHelper.getSignalReadableDatabase();
String query = sorting.applyToQuery(applyEqualityOperator(threadId, DOCUMENT_MEDIA_QUERY));
String[] args = {threadId + ""};
return database.rawQuery(query, args);
}
public @NonNull Cursor getAudioMediaForThread(long threadId, @NonNull Sorting sorting) {
SQLiteDatabase database = databaseHelper.getSignalReadableDatabase();
String query = sorting.applyToQuery(applyEqualityOperator(threadId, AUDIO_MEDIA_QUERY));
String[] args = {threadId + ""};
return database.rawQuery(query, args);
}
public @NonNull Cursor getAllMediaForThread(long threadId, @NonNull Sorting sorting) {
SQLiteDatabase database = databaseHelper.getSignalReadableDatabase();
String query = sorting.applyToQuery(applyEqualityOperator(threadId, ALL_MEDIA_QUERY));
String[] args = {threadId + ""};
return database.rawQuery(query, args);
}
private static String applyEqualityOperator(long threadId, String query) {
return query.replace("__EQUALITY__", threadId == ALL_THREADS ? "!=" : "=");
}
public StorageBreakdown getStorageBreakdown() {
StorageBreakdown storageBreakdown = new StorageBreakdown();
SQLiteDatabase database = databaseHelper.getSignalReadableDatabase();
try (Cursor cursor = database.rawQuery(UNIQUE_MEDIA_QUERY, new String[0])) {
int sizeColumn = cursor.getColumnIndexOrThrow(AttachmentTable.SIZE);
int contentTypeColumn = cursor.getColumnIndexOrThrow(AttachmentTable.CONTENT_TYPE);
while (cursor.moveToNext()) {
int size = cursor.getInt(sizeColumn);
String type = cursor.getString(contentTypeColumn);
switch (MediaUtil.getSlideTypeFromContentType(type)) {
case GIF:
case IMAGE:
case MMS:
storageBreakdown.photoSize += size;
break;
case VIDEO:
storageBreakdown.videoSize += size;
break;
case AUDIO:
storageBreakdown.audioSize += size;
break;
case LONG_TEXT:
case DOCUMENT:
storageBreakdown.documentSize += size;
break;
default:
break;
}
}
}
return storageBreakdown;
}
public static class MediaRecord {
private final DatabaseAttachment attachment;
private final RecipientId recipientId;
private final RecipientId threadRecipientId;
private final long threadId;
private final long date;
private final boolean outgoing;
private MediaRecord(@Nullable DatabaseAttachment attachment,
@NonNull RecipientId recipientId,
@NonNull RecipientId threadRecipientId,
long threadId,
long date,
boolean outgoing)
{
this.attachment = attachment;
this.recipientId = recipientId;
this.threadRecipientId = threadRecipientId;
this.threadId = threadId;
this.date = date;
this.outgoing = outgoing;
}
public static MediaRecord from(@NonNull Cursor cursor) {
AttachmentTable attachmentDatabase = SignalDatabase.attachments();
List<DatabaseAttachment> attachments = attachmentDatabase.getAttachments(cursor);
RecipientId recipientId = RecipientId.from(cursor.getLong(cursor.getColumnIndexOrThrow(MessageTable.RECIPIENT_ID)));
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(MessageTable.THREAD_ID));
boolean outgoing = MessageTypes.isOutgoingMessageType(cursor.getLong(cursor.getColumnIndexOrThrow(MessageTable.TYPE)));
long date;
if (MessageTypes.isPushType(cursor.getLong(cursor.getColumnIndexOrThrow(MessageTable.TYPE)))) {
date = cursor.getLong(cursor.getColumnIndexOrThrow(MessageTable.DATE_SENT));
} else {
date = cursor.getLong(cursor.getColumnIndexOrThrow(MessageTable.DATE_RECEIVED));
}
RecipientId threadRecipient = RecipientId.from(cursor.getLong(cursor.getColumnIndexOrThrow(THREAD_RECIPIENT_ID)));
return new MediaRecord(attachments != null && attachments.size() > 0 ? attachments.get(0) : null,
recipientId,
threadRecipient,
threadId,
date,
outgoing);
}
public @Nullable DatabaseAttachment getAttachment() {
return attachment;
}
public String getContentType() {
return attachment.getContentType();
}
public @NonNull RecipientId getRecipientId() {
return recipientId;
}
public @NonNull RecipientId getThreadRecipientId() {
return threadRecipientId;
}
public long getThreadId() {
return threadId;
}
public long getDate() {
return date;
}
public boolean isOutgoing() {
return outgoing;
}
}
public enum Sorting {
Newest (AttachmentTable.TABLE_NAME + "." + AttachmentTable.MMS_ID + " DESC, " + AttachmentTable.TABLE_NAME + "." + AttachmentTable.DISPLAY_ORDER + " DESC, " + AttachmentTable.TABLE_NAME + "." + AttachmentTable.ROW_ID + " DESC"),
Oldest (AttachmentTable.TABLE_NAME + "." + AttachmentTable.MMS_ID + " ASC, " + AttachmentTable.TABLE_NAME + "." + AttachmentTable.DISPLAY_ORDER + " DESC, " + AttachmentTable.TABLE_NAME + "." + AttachmentTable.ROW_ID + " ASC"),
Largest(AttachmentTable.TABLE_NAME + "." + AttachmentTable.SIZE + " DESC, " + AttachmentTable.TABLE_NAME + "." + AttachmentTable.DISPLAY_ORDER + " DESC");
private final String postFix;
Sorting(@NonNull String order) {
postFix = " ORDER BY " + order;
}
private String applyToQuery(@NonNull String query) {
return query + postFix;
}
public boolean isRelatedToFileSize() {
return this == Largest;
}
public static @NonNull Sorting deserialize(int code) {
switch (code) {
case 0:
return Newest;
case 1:
return Oldest;
case 2:
return Largest;
default:
throw new IllegalArgumentException("Unknown code: " + code);
}
}
}
public final static class StorageBreakdown {
private long photoSize;
private long videoSize;
private long audioSize;
private long documentSize;
public long getPhotoSize() {
return photoSize;
}
public long getVideoSize() {
return videoSize;
}
public long getAudioSize() {
return audioSize;
}
public long getDocumentSize() {
return documentSize;
}
}
}

View file

@ -0,0 +1,274 @@
package org.thoughtcrime.securesms.database
import android.annotation.SuppressLint
import android.content.Context
import android.database.Cursor
import org.signal.core.util.requireInt
import org.signal.core.util.requireLong
import org.signal.core.util.requireNonNullString
import org.signal.core.util.toSingleLine
import org.thoughtcrime.securesms.attachments.DatabaseAttachment
import org.thoughtcrime.securesms.recipients.RecipientId
import org.thoughtcrime.securesms.util.MediaUtil
import org.thoughtcrime.securesms.util.MediaUtil.SlideType
@SuppressLint("RecipientIdDatabaseReferenceUsage", "ThreadIdDatabaseReferenceUsage") // Not a real table, just a view
class MediaTable internal constructor(context: Context?, databaseHelper: SignalDatabase?) : DatabaseTable(context, databaseHelper) {
companion object {
const val ALL_THREADS = -1
private const val THREAD_RECIPIENT_ID = "THREAD_RECIPIENT_ID"
private val BASE_MEDIA_QUERY = """
SELECT
${AttachmentTable.TABLE_NAME}.${AttachmentTable.ROW_ID} AS ${AttachmentTable.ROW_ID},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.CONTENT_TYPE},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.UNIQUE_ID},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.MMS_ID},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.TRANSFER_STATE},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.SIZE},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.FILE_NAME},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.DATA},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.CDN_NUMBER},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.CONTENT_LOCATION},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.CONTENT_DISPOSITION},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.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.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.VISUAL_HASH},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.TRANSFORM_PROPERTIES},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.DISPLAY_ORDER},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.CAPTION},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.NAME},
${AttachmentTable.TABLE_NAME}.${AttachmentTable.UPLOAD_TIMESTAMP},
${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.RECIPIENT_ID},
${ThreadTable.TABLE_NAME}.${ThreadTable.RECIPIENT_ID} as $THREAD_RECIPIENT_ID
FROM
${AttachmentTable.TABLE_NAME}
LEFT JOIN ${MessageTable.TABLE_NAME} ON ${AttachmentTable.TABLE_NAME}.${AttachmentTable.MMS_ID} = ${MessageTable.TABLE_NAME}.${MessageTable.ID}
LEFT JOIN ${ThreadTable.TABLE_NAME} ON ${ThreadTable.TABLE_NAME}.${ThreadTable.ID} = ${MessageTable.TABLE_NAME}.${MessageTable.THREAD_ID}
WHERE
${AttachmentTable.MMS_ID} IN (
SELECT ${MessageTable.ID}
FROM ${MessageTable.TABLE_NAME}
WHERE ${MessageTable.THREAD_ID} __EQUALITY__ ?
) AND
(%s) AND
${MessageTable.VIEW_ONCE} = 0 AND
${MessageTable.STORY_TYPE} = 0 AND
${AttachmentTable.DATA} IS NOT NULL AND
(
${AttachmentTable.QUOTE} = 0 OR
(
${AttachmentTable.QUOTE} = 1 AND
${AttachmentTable.DATA_HASH} IS NULL
)
) AND
${AttachmentTable.STICKER_PACK_ID} IS NULL AND
${MessageTable.TABLE_NAME}.${MessageTable.RECIPIENT_ID} > 0 AND
$THREAD_RECIPIENT_ID > 0
""".toSingleLine()
private val UNIQUE_MEDIA_QUERY = """
SELECT
MAX(${AttachmentTable.SIZE}) as ${AttachmentTable.SIZE},
${AttachmentTable.CONTENT_TYPE}
FROM
${AttachmentTable.TABLE_NAME}
WHERE
${AttachmentTable.STICKER_PACK_ID} IS NULL AND
${AttachmentTable.TRANSFER_STATE} = ${AttachmentTable.TRANSFER_PROGRESS_DONE}
GROUP BY ${AttachmentTable.DATA}
""".toSingleLine()
private val GALLERY_MEDIA_QUERY = String.format(
BASE_MEDIA_QUERY,
"""
${AttachmentTable.CONTENT_TYPE} NOT LIKE 'image/svg%' AND
(${AttachmentTable.CONTENT_TYPE} LIKE 'image/%' OR ${AttachmentTable.CONTENT_TYPE} LIKE 'video/%')
""".toSingleLine()
)
private val AUDIO_MEDIA_QUERY = String.format(BASE_MEDIA_QUERY, "${AttachmentTable.CONTENT_TYPE} LIKE 'audio/%'")
private val ALL_MEDIA_QUERY = String.format(BASE_MEDIA_QUERY, "${AttachmentTable.CONTENT_TYPE} NOT LIKE 'text/x-signal-plain'")
private val DOCUMENT_MEDIA_QUERY = String.format(
BASE_MEDIA_QUERY,
"""
${AttachmentTable.CONTENT_TYPE} LIKE 'image/svg%' OR
(
${AttachmentTable.CONTENT_TYPE} NOT LIKE 'image/%' AND
${AttachmentTable.CONTENT_TYPE} NOT LIKE 'video/%' AND
${AttachmentTable.CONTENT_TYPE} NOT LIKE 'audio/%' AND
${AttachmentTable.CONTENT_TYPE} NOT LIKE 'text/x-signal-plain'
)""".toSingleLine()
)
private fun applyEqualityOperator(threadId: Long, query: String): String {
return query.replace("__EQUALITY__", if (threadId == ALL_THREADS.toLong()) "!=" else "=")
}
}
fun getGalleryMediaForThread(threadId: Long, sorting: Sorting): Cursor {
val query = sorting.applyToQuery(applyEqualityOperator(threadId, GALLERY_MEDIA_QUERY))
val args = arrayOf(threadId.toString() + "")
return readableDatabase.rawQuery(query, args)
}
fun getDocumentMediaForThread(threadId: Long, sorting: Sorting): Cursor {
val query = sorting.applyToQuery(applyEqualityOperator(threadId, DOCUMENT_MEDIA_QUERY))
val args = arrayOf(threadId.toString() + "")
return readableDatabase.rawQuery(query, args)
}
fun getAudioMediaForThread(threadId: Long, sorting: Sorting): Cursor {
val query = sorting.applyToQuery(applyEqualityOperator(threadId, AUDIO_MEDIA_QUERY))
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() + "")
return readableDatabase.rawQuery(query, args)
}
fun getStorageBreakdown(): StorageBreakdown {
var photoSize: Long = 0
var videoSize: Long = 0
var audioSize: Long = 0
var documentSize: Long = 0
readableDatabase.rawQuery(UNIQUE_MEDIA_QUERY, null).use { cursor ->
while (cursor.moveToNext()) {
val size: Int = cursor.requireInt(AttachmentTable.SIZE)
val type: String = cursor.requireNonNullString(AttachmentTable.CONTENT_TYPE)
when (MediaUtil.getSlideTypeFromContentType(type)) {
SlideType.GIF,
SlideType.IMAGE,
SlideType.MMS -> {
photoSize += size.toLong()
}
SlideType.VIDEO -> {
videoSize += size.toLong()
}
SlideType.AUDIO -> {
audioSize += size.toLong()
}
SlideType.LONG_TEXT,
SlideType.DOCUMENT -> {
documentSize += size.toLong()
}
else -> {}
}
}
}
return StorageBreakdown(
photoSize = photoSize,
videoSize = videoSize,
audioSize = audioSize,
documentSize = documentSize
)
}
data class MediaRecord constructor(
val attachment: DatabaseAttachment?,
val recipientId: RecipientId,
val threadRecipientId: RecipientId,
val threadId: Long,
val date: Long,
val isOutgoing: Boolean
) {
val contentType: String
get() = attachment!!.contentType
companion object {
@JvmStatic
fun from(cursor: Cursor): MediaRecord {
val attachments = SignalDatabase.attachments.getAttachments(cursor)
return MediaRecord(
attachment = if (attachments.isNotEmpty()) attachments[0] else null,
recipientId = RecipientId.from(cursor.requireLong(MessageTable.RECIPIENT_ID)),
threadId = cursor.requireLong(MessageTable.THREAD_ID),
threadRecipientId = RecipientId.from(cursor.requireLong(THREAD_RECIPIENT_ID)),
date = if (MessageTypes.isPushType(cursor.requireLong(MessageTable.TYPE))) {
cursor.requireLong(MessageTable.DATE_SENT)
} else {
cursor.requireLong(MessageTable.DATE_RECEIVED)
},
isOutgoing = MessageTypes.isOutgoingMessageType(cursor.requireLong(MessageTable.TYPE))
)
}
}
}
enum class Sorting(order: String) {
Newest(
"""
${AttachmentTable.TABLE_NAME}.${AttachmentTable.MMS_ID} DESC,
${AttachmentTable.TABLE_NAME}.${AttachmentTable.DISPLAY_ORDER} DESC,
${AttachmentTable.TABLE_NAME}.${AttachmentTable.ROW_ID} DESC
""".toSingleLine()
),
Oldest(
"""
${AttachmentTable.TABLE_NAME}.${AttachmentTable.MMS_ID} ASC,
${AttachmentTable.TABLE_NAME}.${AttachmentTable.DISPLAY_ORDER} DESC,
${AttachmentTable.TABLE_NAME}.${AttachmentTable.ROW_ID} ASC
""".toSingleLine()
),
Largest(
"""
${AttachmentTable.TABLE_NAME}.${AttachmentTable.SIZE} DESC,
${AttachmentTable.TABLE_NAME}.${AttachmentTable.DISPLAY_ORDER} DESC
""".toSingleLine()
);
private val postFix: String
init {
postFix = " ORDER BY $order"
}
fun applyToQuery(query: String): String {
return query + postFix
}
val isRelatedToFileSize: Boolean
get() = this == Largest
companion object {
fun deserialize(code: Int): Sorting {
return when (code) {
0 -> Newest
1 -> Oldest
2 -> Largest
else -> throw IllegalArgumentException("Unknown code: $code")
}
}
}
}
data class StorageBreakdown(
val photoSize: Long,
val videoSize: Long,
val audioSize: Long,
val documentSize: Long
)
}