Prevent using `archive` table if it doesn't exist

This closes #773
This commit is contained in:
Ensar Sarajčić 2023-10-03 09:38:29 +02:00
parent 30b54076ce
commit 0e68da2710
7 changed files with 85 additions and 30 deletions

View File

@ -187,6 +187,7 @@ class MainActivity : SimpleActivity() {
binding.mainMenu.getToolbar().menu.apply {
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(com.simplemobiletools.commons.R.bool.hide_google_relations)
findItem(R.id.show_recycle_bin).isVisible = config.useRecycleBin
findItem(R.id.show_archived).isVisible = config.useThreadsArchive
}
}

View File

@ -249,11 +249,12 @@ class ThreadActivity : SimpleActivity() {
private fun refreshMenuItems() {
val firstPhoneNumber = participants.firstOrNull()?.phoneNumbers?.firstOrNull()?.value
val useArchive = config.useThreadsArchive
binding.threadToolbar.menu.apply {
findItem(R.id.delete).isVisible = threadItems.isNotEmpty()
findItem(R.id.restore).isVisible = threadItems.isNotEmpty() && isRecycleBin
findItem(R.id.archive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == false && !isRecycleBin
findItem(R.id.unarchive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == true && !isRecycleBin
findItem(R.id.archive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == false && !isRecycleBin && useArchive
findItem(R.id.unarchive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == true && !isRecycleBin && useArchive
findItem(R.id.rename_conversation).isVisible = participants.size > 1 && conversation != null && !isRecycleBin
findItem(R.id.conversation_details).isVisible = conversation != null && !isRecycleBin
findItem(R.id.block_number).title = addLockedLabelIfNeeded(com.simplemobiletools.commons.R.string.block_number)

View File

@ -28,6 +28,7 @@ class ConversationsAdapter(
val isSingleSelection = isOneItemSelected()
val selectedConversation = selectedItems.firstOrNull() ?: return
val isGroupConversation = selectedConversation.isGroupConversation
val useArchive = activity.config.useThreadsArchive
menu.apply {
findItem(R.id.cab_block_number).title = activity.addLockedLabelIfNeeded(com.simplemobiletools.commons.R.string.block_number)
@ -38,6 +39,7 @@ class ConversationsAdapter(
findItem(R.id.cab_rename_conversation).isVisible = isSingleSelection && isGroupConversation
findItem(R.id.cab_mark_as_read).isVisible = selectedItems.any { !it.read }
findItem(R.id.cab_mark_as_unread).isVisible = selectedItems.any { it.read }
findItem(R.id.cab_archive).isVisible = useArchive
checkPinBtnVisibility(this)
}
}

View File

@ -6,6 +6,7 @@ import android.content.ContentResolver
import android.content.ContentValues
import android.content.Context
import android.database.Cursor
import android.database.sqlite.SQLiteException
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
@ -262,16 +263,21 @@ fun Context.getMMSSender(msgId: Long): String {
}
fun Context.getConversations(threadId: Long? = null, privateContacts: ArrayList<SimpleContact> = ArrayList()): ArrayList<Conversation> {
val useArchive = config.useThreadsArchive
val uri = Uri.parse("${Threads.CONTENT_URI}?simple=true")
val projection = arrayOf(
val projection = mutableListOf(
Threads._ID,
Threads.SNIPPET,
Threads.DATE,
Threads.READ,
Threads.RECIPIENT_IDS,
Threads.ARCHIVED
)
if (useArchive) {
projection += Threads.ARCHIVED
}
var selection = "${Threads.MESSAGE_COUNT} > ?"
var selectionArgs = arrayOf("0")
if (threadId != null) {
@ -284,39 +290,68 @@ fun Context.getConversations(threadId: Long? = null, privateContacts: ArrayList<
val conversations = ArrayList<Conversation>()
val simpleContactHelper = SimpleContactsHelper(this)
val blockedNumbers = getBlockedNumbers()
queryCursor(uri, projection, selection, selectionArgs, sortOrder, true) { cursor ->
val id = cursor.getLongValue(Threads._ID)
var snippet = cursor.getStringValue(Threads.SNIPPET) ?: ""
if (snippet.isEmpty()) {
snippet = getThreadSnippet(id)
}
try {
queryCursorUnsafe(uri, projection.toTypedArray(), selection, selectionArgs, sortOrder) { cursor ->
val id = cursor.getLongValue(Threads._ID)
var snippet = cursor.getStringValue(Threads.SNIPPET) ?: ""
if (snippet.isEmpty()) {
snippet = getThreadSnippet(id)
}
var date = cursor.getLongValue(Threads.DATE)
if (date.toString().length > 10) {
date /= 1000
}
var date = cursor.getLongValue(Threads.DATE)
if (date.toString().length > 10) {
date /= 1000
}
val rawIds = cursor.getStringValue(Threads.RECIPIENT_IDS)
val recipientIds = rawIds.split(" ").filter { it.areDigitsOnly() }.map { it.toInt() }.toMutableList()
val phoneNumbers = getThreadPhoneNumbers(recipientIds)
if (phoneNumbers.isEmpty() || phoneNumbers.any { isNumberBlocked(it, blockedNumbers) }) {
return@queryCursor
}
val rawIds = cursor.getStringValue(Threads.RECIPIENT_IDS)
val recipientIds = rawIds.split(" ").filter { it.areDigitsOnly() }.map { it.toInt() }.toMutableList()
val phoneNumbers = getThreadPhoneNumbers(recipientIds)
if (phoneNumbers.isEmpty() || phoneNumbers.any { isNumberBlocked(it, blockedNumbers) }) {
return@queryCursorUnsafe
}
val names = getThreadContactNames(phoneNumbers, privateContacts)
val title = TextUtils.join(", ", names.toTypedArray())
val photoUri = if (phoneNumbers.size == 1) simpleContactHelper.getPhotoUriFromPhoneNumber(phoneNumbers.first()) else ""
val isGroupConversation = phoneNumbers.size > 1
val read = cursor.getIntValue(Threads.READ) == 1
val archived = cursor.getIntValue(Threads.ARCHIVED) == 1
val conversation = Conversation(id, snippet, date.toInt(), read, title, photoUri, isGroupConversation, phoneNumbers.first(), isArchived = archived)
conversations.add(conversation)
val names = getThreadContactNames(phoneNumbers, privateContacts)
val title = TextUtils.join(", ", names.toTypedArray())
val photoUri = if (phoneNumbers.size == 1) simpleContactHelper.getPhotoUriFromPhoneNumber(phoneNumbers.first()) else ""
val isGroupConversation = phoneNumbers.size > 1
val read = cursor.getIntValue(Threads.READ) == 1
val archived = if (useArchive) cursor.getIntValue(Threads.ARCHIVED) == 1 else false
val conversation = Conversation(id, snippet, date.toInt(), read, title, photoUri, isGroupConversation, phoneNumbers.first(), isArchived = archived)
conversations.add(conversation)
}
} catch (sqliteException: SQLiteException) {
if (sqliteException.message?.contains("no such column: archived") == true && useArchive) {
config.useThreadsArchive = false
return getConversations(threadId, privateContacts)
} else {
showErrorToast(sqliteException)
}
} catch (e: Exception) {
showErrorToast(e)
}
conversations.sortByDescending { it.date }
return conversations
}
private fun Context.queryCursorUnsafe(
uri: Uri,
projection: Array<String>,
selection: String? = null,
selectionArgs: Array<String>? = null,
sortOrder: String? = null,
callback: (cursor: Cursor) -> Unit
) {
val cursor = contentResolver.query(uri, projection, selection, selectionArgs, sortOrder)
cursor?.use {
if (cursor.moveToFirst()) {
do {
callback(cursor)
} while (cursor.moveToNext())
}
}
}
fun Context.getConversationIds(): List<Long> {
val uri = Uri.parse("${Threads.CONTENT_URI}?simple=true")
val projection = arrayOf(Threads._ID)
@ -713,7 +748,16 @@ fun Context.updateConversationArchivedStatus(threadId: Long, archived: Boolean)
}
val selection = "${Threads._ID} = ?"
val selectionArgs = arrayOf(threadId.toString())
contentResolver.update(uri, values, selection, selectionArgs)
try {
contentResolver.update(uri, values, selection, selectionArgs)
} catch (sqliteException: SQLiteException) {
if (sqliteException.message?.contains("no such column: archived") == true && config.useThreadsArchive) {
config.useThreadsArchive = false
return
} else {
throw sqliteException
}
}
if (archived) {
conversationsDB.moveToArchive(threadId)
} else {

View File

@ -111,4 +111,8 @@ class Config(context: Context) : BaseConfig(context) {
var lastRecycleBinCheck: Long
get() = prefs.getLong(LAST_RECYCLE_BIN_CHECK, 0L)
set(lastRecycleBinCheck) = prefs.edit().putLong(LAST_RECYCLE_BIN_CHECK, lastRecycleBinCheck).apply()
var useThreadsArchive: Boolean
get() = prefs.getBoolean(USE_THREADS_ARCHIVE, true)
set(useThreadsArchive) = prefs.edit().putBoolean(USE_THREADS_ARCHIVE, useThreadsArchive).apply()
}

View File

@ -43,6 +43,7 @@ const val MESSAGE_ID = "message_id"
const val USE_RECYCLE_BIN = "use_recycle_bin"
const val LAST_RECYCLE_BIN_CHECK = "last_recycle_bin_check"
const val IS_RECYCLE_BIN = "is_recycle_bin"
const val USE_THREADS_ARCHIVE = "use_threads_archive"
private const val PATH = "com.simplemobiletools.smsmessenger.action."
const val MARK_AS_READ = PATH + "mark_as_read"

View File

@ -113,7 +113,9 @@ class SmsReceiver : BroadcastReceiver() {
subscriptionId
)
context.messagesDB.insertOrUpdate(message)
context.updateConversationArchivedStatus(threadId, false)
if (context.config.useThreadsArchive) {
context.updateConversationArchivedStatus(threadId, false)
}
refreshMessages()
context.showReceivedMessageNotification(newMessageId, address, body, threadId, bitmap)
}