Skip to content

Commit 1d804eb

Browse files
authored
Merge pull request #775 from esensar/fix/missing-archive-table
Prevent using `archive` table if it doesn't exist
2 parents 30b5407 + 625b515 commit 1d804eb

File tree

7 files changed

+85
-30
lines changed

7 files changed

+85
-30
lines changed

app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/MainActivity.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ class MainActivity : SimpleActivity() {
187187
binding.mainMenu.getToolbar().menu.apply {
188188
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(com.simplemobiletools.commons.R.bool.hide_google_relations)
189189
findItem(R.id.show_recycle_bin).isVisible = config.useRecycleBin
190+
findItem(R.id.show_archived).isVisible = config.isArchiveAvailable
190191
}
191192
}
192193

app/src/main/kotlin/com/simplemobiletools/smsmessenger/activities/ThreadActivity.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,12 @@ class ThreadActivity : SimpleActivity() {
249249

250250
private fun refreshMenuItems() {
251251
val firstPhoneNumber = participants.firstOrNull()?.phoneNumbers?.firstOrNull()?.value
252+
val archiveAvailable = config.isArchiveAvailable
252253
binding.threadToolbar.menu.apply {
253254
findItem(R.id.delete).isVisible = threadItems.isNotEmpty()
254255
findItem(R.id.restore).isVisible = threadItems.isNotEmpty() && isRecycleBin
255-
findItem(R.id.archive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == false && !isRecycleBin
256-
findItem(R.id.unarchive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == true && !isRecycleBin
256+
findItem(R.id.archive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == false && !isRecycleBin && archiveAvailable
257+
findItem(R.id.unarchive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == true && !isRecycleBin && archiveAvailable
257258
findItem(R.id.rename_conversation).isVisible = participants.size > 1 && conversation != null && !isRecycleBin
258259
findItem(R.id.conversation_details).isVisible = conversation != null && !isRecycleBin
259260
findItem(R.id.block_number).title = addLockedLabelIfNeeded(com.simplemobiletools.commons.R.string.block_number)

app/src/main/kotlin/com/simplemobiletools/smsmessenger/adapters/ConversationsAdapter.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ class ConversationsAdapter(
2828
val isSingleSelection = isOneItemSelected()
2929
val selectedConversation = selectedItems.firstOrNull() ?: return
3030
val isGroupConversation = selectedConversation.isGroupConversation
31+
val archiveAvailable = activity.config.isArchiveAvailable
3132

3233
menu.apply {
3334
findItem(R.id.cab_block_number).title = activity.addLockedLabelIfNeeded(com.simplemobiletools.commons.R.string.block_number)
@@ -38,6 +39,7 @@ class ConversationsAdapter(
3839
findItem(R.id.cab_rename_conversation).isVisible = isSingleSelection && isGroupConversation
3940
findItem(R.id.cab_mark_as_read).isVisible = selectedItems.any { !it.read }
4041
findItem(R.id.cab_mark_as_unread).isVisible = selectedItems.any { it.read }
42+
findItem(R.id.cab_archive).isVisible = archiveAvailable
4143
checkPinBtnVisibility(this)
4244
}
4345
}

app/src/main/kotlin/com/simplemobiletools/smsmessenger/extensions/Context.kt

Lines changed: 71 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import android.content.ContentResolver
66
import android.content.ContentValues
77
import android.content.Context
88
import android.database.Cursor
9+
import android.database.sqlite.SQLiteException
910
import android.graphics.Bitmap
1011
import android.graphics.BitmapFactory
1112
import android.net.Uri
@@ -262,16 +263,21 @@ fun Context.getMMSSender(msgId: Long): String {
262263
}
263264

264265
fun Context.getConversations(threadId: Long? = null, privateContacts: ArrayList<SimpleContact> = ArrayList()): ArrayList<Conversation> {
266+
val archiveAvailable = config.isArchiveAvailable
267+
265268
val uri = Uri.parse("${Threads.CONTENT_URI}?simple=true")
266-
val projection = arrayOf(
269+
val projection = mutableListOf(
267270
Threads._ID,
268271
Threads.SNIPPET,
269272
Threads.DATE,
270273
Threads.READ,
271274
Threads.RECIPIENT_IDS,
272-
Threads.ARCHIVED
273275
)
274276

277+
if (archiveAvailable) {
278+
projection += Threads.ARCHIVED
279+
}
280+
275281
var selection = "${Threads.MESSAGE_COUNT} > ?"
276282
var selectionArgs = arrayOf("0")
277283
if (threadId != null) {
@@ -284,39 +290,68 @@ fun Context.getConversations(threadId: Long? = null, privateContacts: ArrayList<
284290
val conversations = ArrayList<Conversation>()
285291
val simpleContactHelper = SimpleContactsHelper(this)
286292
val blockedNumbers = getBlockedNumbers()
287-
queryCursor(uri, projection, selection, selectionArgs, sortOrder, true) { cursor ->
288-
val id = cursor.getLongValue(Threads._ID)
289-
var snippet = cursor.getStringValue(Threads.SNIPPET) ?: ""
290-
if (snippet.isEmpty()) {
291-
snippet = getThreadSnippet(id)
292-
}
293+
try {
294+
queryCursorUnsafe(uri, projection.toTypedArray(), selection, selectionArgs, sortOrder) { cursor ->
295+
val id = cursor.getLongValue(Threads._ID)
296+
var snippet = cursor.getStringValue(Threads.SNIPPET) ?: ""
297+
if (snippet.isEmpty()) {
298+
snippet = getThreadSnippet(id)
299+
}
293300

294-
var date = cursor.getLongValue(Threads.DATE)
295-
if (date.toString().length > 10) {
296-
date /= 1000
297-
}
301+
var date = cursor.getLongValue(Threads.DATE)
302+
if (date.toString().length > 10) {
303+
date /= 1000
304+
}
298305

299-
val rawIds = cursor.getStringValue(Threads.RECIPIENT_IDS)
300-
val recipientIds = rawIds.split(" ").filter { it.areDigitsOnly() }.map { it.toInt() }.toMutableList()
301-
val phoneNumbers = getThreadPhoneNumbers(recipientIds)
302-
if (phoneNumbers.isEmpty() || phoneNumbers.any { isNumberBlocked(it, blockedNumbers) }) {
303-
return@queryCursor
304-
}
306+
val rawIds = cursor.getStringValue(Threads.RECIPIENT_IDS)
307+
val recipientIds = rawIds.split(" ").filter { it.areDigitsOnly() }.map { it.toInt() }.toMutableList()
308+
val phoneNumbers = getThreadPhoneNumbers(recipientIds)
309+
if (phoneNumbers.isEmpty() || phoneNumbers.any { isNumberBlocked(it, blockedNumbers) }) {
310+
return@queryCursorUnsafe
311+
}
305312

306-
val names = getThreadContactNames(phoneNumbers, privateContacts)
307-
val title = TextUtils.join(", ", names.toTypedArray())
308-
val photoUri = if (phoneNumbers.size == 1) simpleContactHelper.getPhotoUriFromPhoneNumber(phoneNumbers.first()) else ""
309-
val isGroupConversation = phoneNumbers.size > 1
310-
val read = cursor.getIntValue(Threads.READ) == 1
311-
val archived = cursor.getIntValue(Threads.ARCHIVED) == 1
312-
val conversation = Conversation(id, snippet, date.toInt(), read, title, photoUri, isGroupConversation, phoneNumbers.first(), isArchived = archived)
313-
conversations.add(conversation)
313+
val names = getThreadContactNames(phoneNumbers, privateContacts)
314+
val title = TextUtils.join(", ", names.toTypedArray())
315+
val photoUri = if (phoneNumbers.size == 1) simpleContactHelper.getPhotoUriFromPhoneNumber(phoneNumbers.first()) else ""
316+
val isGroupConversation = phoneNumbers.size > 1
317+
val read = cursor.getIntValue(Threads.READ) == 1
318+
val archived = if (archiveAvailable) cursor.getIntValue(Threads.ARCHIVED) == 1 else false
319+
val conversation = Conversation(id, snippet, date.toInt(), read, title, photoUri, isGroupConversation, phoneNumbers.first(), isArchived = archived)
320+
conversations.add(conversation)
321+
}
322+
} catch (sqliteException: SQLiteException) {
323+
if (sqliteException.message?.contains("no such column: archived") == true && archiveAvailable) {
324+
config.isArchiveAvailable = false
325+
return getConversations(threadId, privateContacts)
326+
} else {
327+
showErrorToast(sqliteException)
328+
}
329+
} catch (e: Exception) {
330+
showErrorToast(e)
314331
}
315332

316333
conversations.sortByDescending { it.date }
317334
return conversations
318335
}
319336

337+
private fun Context.queryCursorUnsafe(
338+
uri: Uri,
339+
projection: Array<String>,
340+
selection: String? = null,
341+
selectionArgs: Array<String>? = null,
342+
sortOrder: String? = null,
343+
callback: (cursor: Cursor) -> Unit
344+
) {
345+
val cursor = contentResolver.query(uri, projection, selection, selectionArgs, sortOrder)
346+
cursor?.use {
347+
if (cursor.moveToFirst()) {
348+
do {
349+
callback(cursor)
350+
} while (cursor.moveToNext())
351+
}
352+
}
353+
}
354+
320355
fun Context.getConversationIds(): List<Long> {
321356
val uri = Uri.parse("${Threads.CONTENT_URI}?simple=true")
322357
val projection = arrayOf(Threads._ID)
@@ -713,7 +748,16 @@ fun Context.updateConversationArchivedStatus(threadId: Long, archived: Boolean)
713748
}
714749
val selection = "${Threads._ID} = ?"
715750
val selectionArgs = arrayOf(threadId.toString())
716-
contentResolver.update(uri, values, selection, selectionArgs)
751+
try {
752+
contentResolver.update(uri, values, selection, selectionArgs)
753+
} catch (sqliteException: SQLiteException) {
754+
if (sqliteException.message?.contains("no such column: archived") == true && config.isArchiveAvailable) {
755+
config.isArchiveAvailable = false
756+
return
757+
} else {
758+
throw sqliteException
759+
}
760+
}
717761
if (archived) {
718762
conversationsDB.moveToArchive(threadId)
719763
} else {

app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Config.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,4 +111,8 @@ class Config(context: Context) : BaseConfig(context) {
111111
var lastRecycleBinCheck: Long
112112
get() = prefs.getLong(LAST_RECYCLE_BIN_CHECK, 0L)
113113
set(lastRecycleBinCheck) = prefs.edit().putLong(LAST_RECYCLE_BIN_CHECK, lastRecycleBinCheck).apply()
114+
115+
var isArchiveAvailable: Boolean
116+
get() = prefs.getBoolean(IS_ARCHIVE_AVAILABLE, true)
117+
set(isArchiveAvailable) = prefs.edit().putBoolean(IS_ARCHIVE_AVAILABLE, isArchiveAvailable).apply()
114118
}

app/src/main/kotlin/com/simplemobiletools/smsmessenger/helpers/Constants.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ const val MESSAGE_ID = "message_id"
4343
const val USE_RECYCLE_BIN = "use_recycle_bin"
4444
const val LAST_RECYCLE_BIN_CHECK = "last_recycle_bin_check"
4545
const val IS_RECYCLE_BIN = "is_recycle_bin"
46+
const val IS_ARCHIVE_AVAILABLE = "is_archive_available"
4647

4748
private const val PATH = "com.simplemobiletools.smsmessenger.action."
4849
const val MARK_AS_READ = PATH + "mark_as_read"

app/src/main/kotlin/com/simplemobiletools/smsmessenger/receivers/SmsReceiver.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ class SmsReceiver : BroadcastReceiver() {
113113
subscriptionId
114114
)
115115
context.messagesDB.insertOrUpdate(message)
116-
context.updateConversationArchivedStatus(threadId, false)
116+
if (context.config.isArchiveAvailable) {
117+
context.updateConversationArchivedStatus(threadId, false)
118+
}
117119
refreshMessages()
118120
context.showReceivedMessageNotification(newMessageId, address, body, threadId, bitmap)
119121
}

0 commit comments

Comments
 (0)