From 75a10f71c3a7e268ba26657118d258bc59e03f30 Mon Sep 17 00:00:00 2001 From: 0x330a <92654767+0x330a@users.noreply.github.com> Date: Wed, 23 Nov 2022 14:02:51 +1100 Subject: [PATCH] feat: add in remove attachments but not link previews --- .../securesms/MediaOverviewActivity.java | 8 +- .../database/AttachmentDatabase.java | 4 - .../securesms/database/MediaDatabase.java | 6 +- .../securesms/database/MmsDatabase.kt | 74 ++++++++++++++----- .../securesms/database/SmsDatabase.java | 7 +- .../securesms/database/Storage.kt | 19 ++++- .../libsession/database/StorageProtocol.kt | 3 +- 7 files changed, 89 insertions(+), 32 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java index eed421c8d5..f87bc43849 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MediaOverviewActivity.java @@ -52,6 +52,7 @@ import androidx.viewpager.widget.ViewPager; import com.codewaves.stickyheadergrid.StickyHeaderGridLayoutManager; import com.google.android.material.tabs.TabLayout; +import org.session.libsession.database.StorageProtocol; import org.session.libsession.messaging.MessagingModuleConfiguration; import org.session.libsession.messaging.messages.control.DataExtractionNotification; import org.session.libsession.messaging.sending_receiving.MessageSender; @@ -68,7 +69,6 @@ import org.thoughtcrime.securesms.database.MediaDatabase; import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader; import org.thoughtcrime.securesms.database.loaders.BucketedThreadMediaLoader.BucketedThreadMedia; import org.thoughtcrime.securesms.database.loaders.ThreadMediaLoader; -import org.thoughtcrime.securesms.dependencies.DatabaseComponent; import org.thoughtcrime.securesms.mms.GlideApp; import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.util.AttachmentUtil; @@ -164,7 +164,11 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i if (v.getId() == R.id.clearMedia) { FragmentManager fm = getSupportFragmentManager(); ClearAllMediaDialog dialog = new ClearAllMediaDialog(() -> { - MediaDatabase mediaDb = DatabaseComponent.get(this).mediaDatabase(); + StorageProtocol storage = MessagingModuleConfiguration.getShared().getStorage(); + Long threadId = storage.getThreadId(recipient); + if (threadId != null) { + storage.clearMedia(threadId, null); + } return Unit.INSTANCE; }); dialog.show(fm, "ClearAllMedia"); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java index 8c9916b87c..8806316bce 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java @@ -943,10 +943,6 @@ public class AttachmentDatabase extends Database { @SuppressLint("NewApi") private ThumbnailData generateVideoThumbnail(AttachmentId attachmentId) { - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - Log.w(TAG, "Video thumbnails not supported..."); - return null; - } DataInfo dataInfo = getAttachmentDataFileInfo(attachmentId, DATA); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MediaDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MediaDatabase.java index f16d663a10..c87e491bc8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MediaDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MediaDatabase.java @@ -44,7 +44,8 @@ public class MediaDatabase extends Database { + MmsDatabase.TABLE_NAME + "." + MmsDatabase.MESSAGE_BOX + ", " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.DATE_SENT + ", " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.DATE_RECEIVED + ", " - + MmsDatabase.TABLE_NAME + "." + MmsDatabase.ADDRESS + " " + + MmsDatabase.TABLE_NAME + "." + MmsDatabase.ADDRESS + ", " + + MmsDatabase.TABLE_NAME + "." + MmsDatabase.LINK_PREVIEWS + " " + "FROM " + AttachmentDatabase.TABLE_NAME + " LEFT JOIN " + MmsDatabase.TABLE_NAME + " ON " + AttachmentDatabase.TABLE_NAME + "." + AttachmentDatabase.MMS_ID + " = " + MmsDatabase.TABLE_NAME + "." + MmsDatabase.ID + " " + "WHERE " + AttachmentDatabase.MMS_ID + " IN (SELECT " + MmsSmsColumns.ID @@ -52,7 +53,8 @@ public class MediaDatabase extends Database { + " WHERE " + MmsDatabase.THREAD_ID + " = ?) AND (%s) AND " + AttachmentDatabase.DATA + " IS NOT NULL AND " + AttachmentDatabase.QUOTE + " = 0 AND " - + AttachmentDatabase.STICKER_PACK_ID + " IS NULL " + + AttachmentDatabase.STICKER_PACK_ID + " IS NULL AND " + + MmsDatabase.LINK_PREVIEWS + " IS NULL " + "ORDER BY " + AttachmentDatabase.TABLE_NAME + "." + AttachmentDatabase.ROW_ID + " DESC"; private static final String GALLERY_MEDIA_QUERY = String.format(BASE_MEDIA_QUERY, AttachmentDatabase.CONTENT_TYPE + " LIKE 'image/%' OR " + AttachmentDatabase.CONTENT_TYPE + " LIKE 'video/%'"); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt index d82c6bb278..59d9e35337 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.kt @@ -933,23 +933,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa } } - private fun deleteQuotedFromMessages(toDeleteRecords: List) { - if (toDeleteRecords.isEmpty()) return - val queryBuilder = StringBuilder() - for (i in toDeleteRecords.indices) { - queryBuilder.append("$QUOTE_ID = ").append(toDeleteRecords[i].getId()) - if (i + 1 < toDeleteRecords.size) { - queryBuilder.append(" OR ") - } - } - val query = queryBuilder.toString() - val db = databaseHelper.writableDatabase - val values = ContentValues(2) - values.put(QUOTE_MISSING, 1) - values.put(QUOTE_AUTHOR, "") - db!!.update(TABLE_NAME, values, query, null) - } - /** * Delete all the messages in single queries where possible * @param messageIds a String array representation of regularly Long types representing message IDs @@ -1016,6 +999,62 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa deleteThreads(setOf(threadId)) } + fun deleteMediaFor(threadId: Long, fromUser: String? = null) { + val db = databaseHelper.writableDatabase + val whereString = + if (fromUser == null) "$THREAD_ID = ? AND $LINK_PREVIEWS IS NULL" + else "$THREAD_ID = ? AND $ADDRESS = ? AND $LINK_PREVIEWS IS NULL" + val whereArgs = if (fromUser == null) arrayOf(threadId.toString()) else arrayOf(threadId.toString(), fromUser) + var cursor: Cursor? = null + try { + cursor = db.query(TABLE_NAME, arrayOf(ID), whereString, whereArgs, null, null, null, null) + val toDeleteStringMessageIds = mutableListOf() + while (cursor.moveToNext()) { + toDeleteStringMessageIds += cursor.getLong(0).toString() // get the ID as a string + } + // TODO: this can probably be optimized out, + // currently attachmentDB uses MmsID not threadID which makes it difficult to delete + // and clean up on threadID alone + toDeleteStringMessageIds.toList().chunked(50).forEach { sublist -> + deleteMessages(sublist.toTypedArray()) + } + } finally { + cursor?.close() + } + val threadDb = get(context).threadDatabase() + threadDb.update(threadId, false) + notifyConversationListeners(threadId) + notifyStickerListeners() + notifyStickerPackListeners() + } + + fun deleteMessagesFrom(threadId: Long, fromUser: String) { // copied from deleteThreads implementation + val db = databaseHelper.writableDatabase + var cursor: Cursor? = null + val whereString = "$THREAD_ID = ? AND $ADDRESS = ?" + try { + cursor = + db!!.query(TABLE_NAME, arrayOf(ID), whereString, arrayOf(threadId.toString(), fromUser), null, null, null) + val toDeleteStringMessageIds = mutableListOf() + while (cursor.moveToNext()) { + toDeleteStringMessageIds += cursor.getLong(0).toString() // get the ID as a string + } + // TODO: this can probably be optimized out, + // currently attachmentDB uses MmsID not threadID which makes it difficult to delete + // and clean up on threadID alone + toDeleteStringMessageIds.toList().chunked(50).forEach { sublist -> + deleteMessages(sublist.toTypedArray()) + } + } finally { + cursor?.close() + } + val threadDb = get(context).threadDatabase() + threadDb.update(threadId, false) + notifyConversationListeners(threadId) + notifyStickerListeners() + notifyStickerPackListeners() + } + private fun getSerializedSharedContacts( insertedAttachmentIds: Map, contacts: List @@ -1159,7 +1198,6 @@ class MmsDatabase(context: Context, databaseHelper: SQLCipherOpenHelper) : Messa return false } - /*package*/ private fun deleteThreads(threadIds: Set) { val db = databaseHelper.writableDatabase val where = StringBuilder() diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java index 67243f73b6..1188784529 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -638,11 +638,16 @@ public class SmsDatabase extends MessagingDatabase { } } - /*package */void deleteThread(long threadId) { + void deleteThread(long threadId) { SQLiteDatabase db = databaseHelper.getWritableDatabase(); db.delete(TABLE_NAME, THREAD_ID + " = ?", new String[] {threadId+""}); } + void deleteMessagesFrom(long threadId, String fromUser) { + SQLiteDatabase db = databaseHelper.getWritableDatabase(); + db.delete(TABLE_NAME, THREAD_ID+" = ? AND "+ADDRESS+" = ?", new String[]{threadId+"", fromUser}); + } + /*package*/void deleteMessagesInThreadBeforeDate(long threadId, long date) { SQLiteDatabase db = databaseHelper.getWritableDatabase(); String where = THREAD_ID + " = ? AND (CASE " + TYPE; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 1bb8661289..122d85223a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -731,13 +731,24 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, return threadDb.getPinned(threadID) } - override fun clearMessages(threadID: Long): Boolean { + override fun clearMessages(threadID: Long, fromUser: Address?): Boolean { val smsDb = DatabaseComponent.get(context).smsDatabase() val mmsDb = DatabaseComponent.get(context).mmsDatabase() val threadDb = DatabaseComponent.get(context).threadDatabase() - smsDb.deleteThread(threadID) - mmsDb.deleteThread(threadID) // threadDB update called from within - threadDb.update(threadID, false) + if (fromUser == null) { + smsDb.deleteThread(threadID) + mmsDb.deleteThread(threadID) // threadDB update called from within + } else { + smsDb.deleteMessagesFrom(threadID, fromUser.serialize()) + mmsDb.deleteMessagesFrom(threadID, fromUser.serialize()) + threadDb.update(threadID, false) + } + return true + } + + override fun clearMedia(threadID: Long, fromUser: Address?): Boolean { + val mmsDb = DatabaseComponent.get(context).mmsDatabase() + mmsDb.deleteMediaFor(threadID, fromUser?.serialize()) return true } diff --git a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt index 4474bc4f3b..17fbdf75db 100644 --- a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt @@ -155,7 +155,8 @@ interface StorageProtocol { fun getMessageCount(threadID: Long): Long fun setThreadPinned(threadID: Long, isPinned: Boolean) fun isThreadPinned(threadID: Long): Boolean - fun clearMessages(threadID: Long): Boolean + fun clearMessages(threadID: Long, fromUser: Address? = null): Boolean + fun clearMedia(threadID: Long, fromUser: Address? = null): Boolean // Contacts fun getContactWithSessionID(sessionID: String): Contact?