Implement archive functionality using system API

This commit is contained in:
Ensar Sarajčić 2023-07-17 16:43:31 +02:00
parent 4d13fa1079
commit 857a4f0b93
17 changed files with 127 additions and 218 deletions

View File

@ -64,7 +64,6 @@ class MainActivity : SimpleActivity() {
updateMaterialActivityViews(main_coordinator, conversations_list, useTransparentNavigation = true, useTopSearchMenu = true) updateMaterialActivityViews(main_coordinator, conversations_list, useTransparentNavigation = true, useTopSearchMenu = true)
if (savedInstanceState == null) { if (savedInstanceState == null) {
checkAndDeleteOldArchivedConversations()
handleAppPasswordProtection { handleAppPasswordProtection {
wasProtectionHandled = it wasProtectionHandled = it
if (it) { if (it) {

View File

@ -11,15 +11,12 @@ import com.simplemobiletools.commons.helpers.*
import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.commons.models.RadioItem
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.extensions.config import com.simplemobiletools.smsmessenger.extensions.config
import com.simplemobiletools.smsmessenger.extensions.conversationsDB
import com.simplemobiletools.smsmessenger.extensions.removeAllArchivedConversations
import com.simplemobiletools.smsmessenger.helpers.* import com.simplemobiletools.smsmessenger.helpers.*
import kotlinx.android.synthetic.main.activity_settings.* import kotlinx.android.synthetic.main.activity_settings.*
import java.util.* import java.util.*
class SettingsActivity : SimpleActivity() { class SettingsActivity : SimpleActivity() {
private var blockedNumbersAtPause = -1 private var blockedNumbersAtPause = -1
private var archiveConversations = 0
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
isMaterialActivity = true isMaterialActivity = true
@ -50,8 +47,6 @@ class SettingsActivity : SimpleActivity() {
setupGroupMessageAsMMS() setupGroupMessageAsMMS()
setupLockScreenVisibility() setupLockScreenVisibility()
setupMMSFileSizeLimit() setupMMSFileSizeLimit()
setupUseRecycleBin()
setupEmptyRecycleBin()
setupAppPasswordProtection() setupAppPasswordProtection()
updateTextColors(settings_nested_scrollview) updateTextColors(settings_nested_scrollview)
@ -64,7 +59,6 @@ class SettingsActivity : SimpleActivity() {
settings_general_settings_label, settings_general_settings_label,
settings_outgoing_messages_label, settings_outgoing_messages_label,
settings_notifications_label, settings_notifications_label,
settings_archive_label,
settings_security_label settings_security_label
).forEach { ).forEach {
it.setTextColor(getProperPrimaryColor()) it.setTextColor(getProperPrimaryColor())
@ -250,43 +244,6 @@ class SettingsActivity : SimpleActivity() {
} }
} }
private fun setupUseRecycleBin() {
updateRecycleBinButtons()
settings_use_archive.isChecked = config.useArchive
settings_use_archive_holder.setOnClickListener {
settings_use_archive.toggle()
config.useArchive = settings_use_archive.isChecked
updateRecycleBinButtons()
}
}
private fun updateRecycleBinButtons() {
settings_empty_archive_holder.beVisibleIf(config.useArchive)
}
private fun setupEmptyRecycleBin() {
ensureBackgroundThread {
archiveConversations = conversationsDB.getArchivedCount()
runOnUiThread {
settings_empty_archive_size.text =
resources.getQuantityString(R.plurals.delete_conversations, archiveConversations, archiveConversations)
}
}
settings_empty_archive_holder.setOnClickListener {
if (archiveConversations == 0) {
toast(R.string.archive_is_empty)
} else {
ConfirmationDialog(this, "", R.string.empty_archive_confirmation, R.string.yes, R.string.no) {
removeAllArchivedConversations()
archiveConversations = 0
settings_empty_archive_size.text =
resources.getQuantityString(R.plurals.delete_conversations, archiveConversations, archiveConversations)
}
}
}
}
private fun setupAppPasswordProtection() { private fun setupAppPasswordProtection() {
settings_app_password_protection.isChecked = config.isAppPasswordProtectionOn settings_app_password_protection.isChecked = config.isAppPasswordProtectionOn
settings_app_password_protection_holder.setOnClickListener { settings_app_password_protection_holder.setOnClickListener {

View File

@ -55,7 +55,6 @@ import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.adapters.AttachmentsAdapter import com.simplemobiletools.smsmessenger.adapters.AttachmentsAdapter
import com.simplemobiletools.smsmessenger.adapters.AutoCompleteTextViewAdapter import com.simplemobiletools.smsmessenger.adapters.AutoCompleteTextViewAdapter
import com.simplemobiletools.smsmessenger.adapters.ThreadAdapter import com.simplemobiletools.smsmessenger.adapters.ThreadAdapter
import com.simplemobiletools.smsmessenger.dialogs.DeleteConfirmationDialog
import com.simplemobiletools.smsmessenger.dialogs.InvalidNumberDialog import com.simplemobiletools.smsmessenger.dialogs.InvalidNumberDialog
import com.simplemobiletools.smsmessenger.dialogs.RenameConversationDialog import com.simplemobiletools.smsmessenger.dialogs.RenameConversationDialog
import com.simplemobiletools.smsmessenger.dialogs.ScheduleMessageDialog import com.simplemobiletools.smsmessenger.dialogs.ScheduleMessageDialog
@ -245,6 +244,8 @@ class ThreadActivity : SimpleActivity() {
val firstPhoneNumber = participants.firstOrNull()?.phoneNumbers?.firstOrNull()?.value val firstPhoneNumber = participants.firstOrNull()?.phoneNumbers?.firstOrNull()?.value
thread_toolbar.menu.apply { thread_toolbar.menu.apply {
findItem(R.id.delete).isVisible = threadItems.isNotEmpty() findItem(R.id.delete).isVisible = threadItems.isNotEmpty()
findItem(R.id.archive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == false
findItem(R.id.unarchive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == true
findItem(R.id.rename_conversation).isVisible = participants.size > 1 && conversation != null findItem(R.id.rename_conversation).isVisible = participants.size > 1 && conversation != null
findItem(R.id.conversation_details).isVisible = conversation != null findItem(R.id.conversation_details).isVisible = conversation != null
findItem(R.id.block_number).title = addLockedLabelIfNeeded(R.string.block_number) findItem(R.id.block_number).title = addLockedLabelIfNeeded(R.string.block_number)
@ -269,6 +270,8 @@ class ThreadActivity : SimpleActivity() {
when (menuItem.itemId) { when (menuItem.itemId) {
R.id.block_number -> tryBlocking() R.id.block_number -> tryBlocking()
R.id.delete -> askConfirmDelete() R.id.delete -> askConfirmDelete()
R.id.archive -> archiveConversation()
R.id.unarchive -> unarchiveConversation()
R.id.rename_conversation -> renameConversation() R.id.rename_conversation -> renameConversation()
R.id.conversation_details -> showConversationDetails() R.id.conversation_details -> showConversationDetails()
R.id.add_number_to_contact -> addNumberToContact() R.id.add_number_to_contact -> addNumberToContact()
@ -889,18 +892,10 @@ class ThreadActivity : SimpleActivity() {
} }
private fun askConfirmDelete() { private fun askConfirmDelete() {
val confirmationMessage = if (config.useArchive) { val confirmationMessage = R.string.delete_whole_conversation_confirmation
R.string.archive_whole_conversation_confirmation ConfirmationDialog(this, getString(confirmationMessage)) {
} else {
R.string.delete_whole_conversation_confirmation
}
DeleteConfirmationDialog(this, getString(confirmationMessage), config.useArchive) { skipRecycleBin ->
ensureBackgroundThread { ensureBackgroundThread {
if (skipRecycleBin || config.useArchive.not()) { deleteConversation(threadId)
deleteConversation(threadId)
} else {
moveConversationToRecycleBin(threadId)
}
runOnUiThread { runOnUiThread {
refreshMessages() refreshMessages()
finish() finish()
@ -909,6 +904,26 @@ class ThreadActivity : SimpleActivity() {
} }
} }
private fun archiveConversation() {
ensureBackgroundThread {
updateConversationArchivedStatus(threadId, true)
runOnUiThread {
refreshMessages()
finish()
}
}
}
private fun unarchiveConversation() {
ensureBackgroundThread {
updateConversationArchivedStatus(threadId, false)
runOnUiThread {
refreshMessages()
finish()
}
}
}
private fun dialNumber() { private fun dialNumber() {
val phoneNumber = participants.first().phoneNumbers.first().normalizedNumber val phoneNumber = participants.first().phoneNumbers.first().normalizedNumber
dialNumber(phoneNumber) dialNumber(phoneNumber)
@ -1337,7 +1352,7 @@ class ThreadActivity : SimpleActivity() {
} }
} }
messagesDB.insertOrUpdate(message) messagesDB.insertOrUpdate(message)
conversationsDB.deleteThreadFromArchivedConversations(message.threadId) updateConversationArchivedStatus(message.threadId, false)
} }
// show selected contacts, properly split to new lines when appropriate // show selected contacts, properly split to new lines when appropriate

View File

@ -1,14 +1,14 @@
package com.simplemobiletools.smsmessenger.adapters package com.simplemobiletools.smsmessenger.adapters
import android.view.Menu import android.view.Menu
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
import com.simplemobiletools.commons.extensions.notificationManager import com.simplemobiletools.commons.extensions.notificationManager
import com.simplemobiletools.commons.helpers.ensureBackgroundThread import com.simplemobiletools.commons.helpers.ensureBackgroundThread
import com.simplemobiletools.commons.views.MyRecyclerView import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.activities.SimpleActivity import com.simplemobiletools.smsmessenger.activities.SimpleActivity
import com.simplemobiletools.smsmessenger.dialogs.DeleteConfirmationDialog
import com.simplemobiletools.smsmessenger.extensions.conversationsDB
import com.simplemobiletools.smsmessenger.extensions.deleteConversation import com.simplemobiletools.smsmessenger.extensions.deleteConversation
import com.simplemobiletools.smsmessenger.extensions.updateConversationArchivedStatus
import com.simplemobiletools.smsmessenger.helpers.refreshMessages import com.simplemobiletools.smsmessenger.helpers.refreshMessages
import com.simplemobiletools.smsmessenger.models.Conversation import com.simplemobiletools.smsmessenger.models.Conversation
@ -38,7 +38,7 @@ class ArchivedConversationsAdapter(
val baseString = R.string.deletion_confirmation val baseString = R.string.deletion_confirmation
val question = String.format(resources.getString(baseString), items) val question = String.format(resources.getString(baseString), items)
DeleteConfirmationDialog(activity, question, showSkipArchiveOption = false) { _ -> ConfirmationDialog(activity, question) {
ensureBackgroundThread { ensureBackgroundThread {
deleteConversations() deleteConversations()
} }
@ -66,7 +66,7 @@ class ArchivedConversationsAdapter(
val conversationsToUnarchive = currentList.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation> val conversationsToUnarchive = currentList.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation>
conversationsToUnarchive.forEach { conversationsToUnarchive.forEach {
activity.conversationsDB.deleteThreadFromArchivedConversations(it.threadId) activity.updateConversationArchivedStatus(it.threadId, false)
} }
removeConversationsFromList(conversationsToUnarchive) removeConversationsFromList(conversationsToUnarchive)

View File

@ -12,7 +12,6 @@ import com.simplemobiletools.commons.helpers.isNougatPlus
import com.simplemobiletools.commons.views.MyRecyclerView import com.simplemobiletools.commons.views.MyRecyclerView
import com.simplemobiletools.smsmessenger.R import com.simplemobiletools.smsmessenger.R
import com.simplemobiletools.smsmessenger.activities.SimpleActivity import com.simplemobiletools.smsmessenger.activities.SimpleActivity
import com.simplemobiletools.smsmessenger.dialogs.DeleteConfirmationDialog
import com.simplemobiletools.smsmessenger.dialogs.RenameConversationDialog import com.simplemobiletools.smsmessenger.dialogs.RenameConversationDialog
import com.simplemobiletools.smsmessenger.extensions.* import com.simplemobiletools.smsmessenger.extensions.*
import com.simplemobiletools.smsmessenger.helpers.refreshMessages import com.simplemobiletools.smsmessenger.helpers.refreshMessages
@ -54,6 +53,7 @@ class ConversationsAdapter(
R.id.cab_dial_number -> dialNumber() R.id.cab_dial_number -> dialNumber()
R.id.cab_copy_number -> copyNumberToClipboard() R.id.cab_copy_number -> copyNumberToClipboard()
R.id.cab_delete -> askConfirmDelete() R.id.cab_delete -> askConfirmDelete()
R.id.cab_archive -> ensureBackgroundThread { archiveConversations() }
R.id.cab_rename_conversation -> renameConversation(getSelectedItems().first()) R.id.cab_rename_conversation -> renameConversation(getSelectedItems().first())
R.id.cab_mark_as_read -> markAsRead() R.id.cab_mark_as_read -> markAsRead()
R.id.cab_mark_as_unread -> markAsUnread() R.id.cab_mark_as_unread -> markAsUnread()
@ -118,32 +118,54 @@ class ConversationsAdapter(
val itemsCnt = selectedKeys.size val itemsCnt = selectedKeys.size
val items = resources.getQuantityString(R.plurals.delete_conversations, itemsCnt, itemsCnt) val items = resources.getQuantityString(R.plurals.delete_conversations, itemsCnt, itemsCnt)
val baseString = if (activity.config.useArchive) { val baseString = R.string.deletion_confirmation
R.string.archive_confirmation
} else {
R.string.deletion_confirmation
}
val question = String.format(resources.getString(baseString), items) val question = String.format(resources.getString(baseString), items)
DeleteConfirmationDialog(activity, question, activity.config.useArchive) { skipRecycleBin -> ConfirmationDialog(activity, question) {
ensureBackgroundThread { ensureBackgroundThread {
deleteConversations(skipRecycleBin) deleteConversations()
} }
} }
} }
private fun deleteConversations(skipRecycleBin: Boolean) { private fun archiveConversations() {
if (selectedKeys.isEmpty()) { if (selectedKeys.isEmpty()) {
return return
} }
val conversationsToRemove = currentList.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation> val conversationsToRemove = currentList.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation>
conversationsToRemove.forEach { conversationsToRemove.forEach {
if (skipRecycleBin || activity.config.useArchive.not()) { activity.updateConversationArchivedStatus(it.threadId, true)
activity.deleteConversation(it.threadId) activity.notificationManager.cancel(it.threadId.hashCode())
}
val newList = try {
currentList.toMutableList().apply { removeAll(conversationsToRemove) }
} catch (ignored: Exception) {
currentList.toMutableList()
}
activity.runOnUiThread {
if (newList.none { selectedKeys.contains(it.hashCode()) }) {
refreshMessages()
finishActMode()
} else { } else {
activity.moveConversationToRecycleBin(it.threadId) submitList(newList)
if (newList.isEmpty()) {
refreshMessages()
}
} }
}
}
private fun deleteConversations() {
if (selectedKeys.isEmpty()) {
return
}
val conversationsToRemove = currentList.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation>
conversationsToRemove.forEach {
activity.deleteConversation(it.threadId)
activity.notificationManager.cancel(it.threadId.hashCode()) activity.notificationManager.cancel(it.threadId.hashCode())
} }

View File

@ -14,7 +14,7 @@ import com.simplemobiletools.smsmessenger.interfaces.MessageAttachmentsDao
import com.simplemobiletools.smsmessenger.interfaces.MessagesDao import com.simplemobiletools.smsmessenger.interfaces.MessagesDao
import com.simplemobiletools.smsmessenger.models.* import com.simplemobiletools.smsmessenger.models.*
@Database(entities = [Conversation::class, ArchivedConversation::class, Attachment::class, MessageAttachment::class, Message::class], version = 8) @Database(entities = [Conversation::class, Attachment::class, MessageAttachment::class, Message::class], version = 8)
@TypeConverters(Converters::class) @TypeConverters(Converters::class)
abstract class MessagesDatabase : RoomDatabase() { abstract class MessagesDatabase : RoomDatabase() {
@ -117,8 +117,7 @@ abstract class MessagesDatabase : RoomDatabase() {
private val MIGRATION_7_8 = object : Migration(7, 8) { private val MIGRATION_7_8 = object : Migration(7, 8) {
override fun migrate(database: SupportSQLiteDatabase) { override fun migrate(database: SupportSQLiteDatabase) {
database.apply { database.apply {
execSQL("CREATE TABLE IF NOT EXISTS archived_conversations (`thread_id` INTEGER NOT NULL PRIMARY KEY, `deleted_ts` INTEGER NOT NULL)") execSQL("ALTER TABLE conversations ADD COLUMN archived INTEGER NOT NULL DEFAULT 0")
execSQL("CREATE UNIQUE INDEX IF NOT EXISTS `index_archived_conversations_thread_id` ON `archived_conversations` (`thread_id`)")
} }
} }
} }

View File

@ -1,39 +0,0 @@
package com.simplemobiletools.smsmessenger.dialogs
import android.app.Activity
import androidx.appcompat.app.AlertDialog
import com.simplemobiletools.commons.extensions.beGoneIf
import com.simplemobiletools.commons.extensions.getAlertDialogBuilder
import com.simplemobiletools.commons.extensions.setupDialogStuff
import com.simplemobiletools.smsmessenger.R
import kotlinx.android.synthetic.main.dialog_delete_confirmation.view.delete_remember_title
import kotlinx.android.synthetic.main.dialog_delete_confirmation.view.skip_the_archive_checkbox
class DeleteConfirmationDialog(
private val activity: Activity,
private val message: String,
private val showSkipArchiveOption: Boolean,
private val callback: (skipRecycleBin: Boolean) -> Unit
) {
private var dialog: AlertDialog? = null
val view = activity.layoutInflater.inflate(R.layout.dialog_delete_confirmation, null)!!
init {
view.delete_remember_title.text = message
view.skip_the_archive_checkbox.beGoneIf(!showSkipArchiveOption)
activity.getAlertDialogBuilder()
.setPositiveButton(R.string.yes) { _, _ -> dialogConfirmed() }
.setNegativeButton(R.string.no, null)
.apply {
activity.setupDialogStuff(view, this) { alertDialog ->
dialog = alertDialog
}
}
}
private fun dialogConfirmed() {
dialog?.dismiss()
callback(view.skip_the_archive_checkbox.isChecked)
}
}

View File

@ -238,7 +238,8 @@ fun Context.getConversations(threadId: Long? = null, privateContacts: ArrayList<
Threads.SNIPPET, Threads.SNIPPET,
Threads.DATE, Threads.DATE,
Threads.READ, Threads.READ,
Threads.RECIPIENT_IDS Threads.RECIPIENT_IDS,
Threads.ARCHIVED
) )
var selection = "${Threads.MESSAGE_COUNT} > ?" var selection = "${Threads.MESSAGE_COUNT} > ?"
@ -277,7 +278,8 @@ fun Context.getConversations(threadId: Long? = null, privateContacts: ArrayList<
val photoUri = if (phoneNumbers.size == 1) simpleContactHelper.getPhotoUriFromPhoneNumber(phoneNumbers.first()) else "" val photoUri = if (phoneNumbers.size == 1) simpleContactHelper.getPhotoUriFromPhoneNumber(phoneNumbers.first()) else ""
val isGroupConversation = phoneNumbers.size > 1 val isGroupConversation = phoneNumbers.size > 1
val read = cursor.getIntValue(Threads.READ) == 1 val read = cursor.getIntValue(Threads.READ) == 1
val conversation = Conversation(id, snippet, date.toInt(), read, title, photoUri, isGroupConversation, phoneNumbers.first()) 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) conversations.add(conversation)
} }
@ -581,21 +583,6 @@ fun Context.insertNewSMS(address: String, subject: String, body: String, date: L
} }
} }
fun Context.checkAndDeleteOldArchivedConversations(callback: (() -> Unit)? = null) {
if (config.useArchive && config.lastArchiveCheck < System.currentTimeMillis() - DAY_SECONDS * 1000) {
config.lastArchiveCheck = System.currentTimeMillis()
ensureBackgroundThread {
try {
for (conversation in conversationsDB.getOldArchived(System.currentTimeMillis() - MONTH_SECONDS * 1000L)) {
deleteConversation(conversation.threadId)
}
callback?.invoke()
} catch (e: Exception) {
}
}
}
}
fun Context.removeAllArchivedConversations(callback: (() -> Unit)? = null) { fun Context.removeAllArchivedConversations(callback: (() -> Unit)? = null) {
ensureBackgroundThread { ensureBackgroundThread {
try { try {
@ -631,13 +618,19 @@ fun Context.deleteConversation(threadId: Long) {
messagesDB.deleteThreadMessages(threadId) messagesDB.deleteThreadMessages(threadId)
} }
fun Context.moveConversationToRecycleBin(threadId: Long) { fun Context.updateConversationArchivedStatus(threadId: Long, archived: Boolean) {
conversationsDB.archiveConversation( val uri = Threads.CONTENT_URI
ArchivedConversation( val values = ContentValues().apply {
threadId = threadId, put(Threads.ARCHIVED, archived)
deletedTs = System.currentTimeMillis() }
) val selection = "${Threads._ID} = ?"
) val selectionArgs = arrayOf(threadId.toString())
contentResolver.update(uri, values, selection, selectionArgs)
if (archived) {
conversationsDB.moveToArchive(threadId)
} else {
conversationsDB.unarchive(threadId)
}
} }
fun Context.deleteMessage(id: Long, isMMS: Boolean) { fun Context.deleteMessage(id: Long, isMMS: Boolean) {
@ -968,7 +961,8 @@ fun Context.createTemporaryThread(message: Message, threadId: Long = generateRan
isGroupConversation = addresses.size > 1, isGroupConversation = addresses.size > 1,
phoneNumber = addresses.first(), phoneNumber = addresses.first(),
isScheduled = true, isScheduled = true,
usesCustomTitle = cachedConv?.usesCustomTitle == true usesCustomTitle = cachedConv?.usesCustomTitle == true,
isArchived = false
) )
try { try {
conversationsDB.insertOrUpdate(conversation) conversationsDB.insertOrUpdate(conversation)

View File

@ -1,7 +1,6 @@
package com.simplemobiletools.smsmessenger.interfaces package com.simplemobiletools.smsmessenger.interfaces
import androidx.room.* import androidx.room.*
import com.simplemobiletools.smsmessenger.models.ArchivedConversation
import com.simplemobiletools.smsmessenger.models.Conversation import com.simplemobiletools.smsmessenger.models.Conversation
@Dao @Dao
@ -9,21 +8,12 @@ interface ConversationsDao {
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertOrUpdate(conversation: Conversation): Long fun insertOrUpdate(conversation: Conversation): Long
@Query("SELECT conversations.* FROM conversations LEFT OUTER JOIN archived_conversations ON conversations.thread_id = archived_conversations.thread_id WHERE archived_conversations.deleted_ts is NULL") @Query("SELECT * FROM conversations WHERE archived = 0")
fun getNonArchived(): List<Conversation> fun getNonArchived(): List<Conversation>
@Query("SELECT conversations.* FROM archived_conversations INNER JOIN conversations ON conversations.thread_id = archived_conversations.thread_id") @Query("SELECT * FROM conversations WHERE archived = 1")
fun getAllArchived(): List<Conversation> fun getAllArchived(): List<Conversation>
@Query("SELECT COUNT(*) FROM archived_conversations")
fun getArchivedCount(): Int
@Query("SELECT * FROM archived_conversations WHERE deleted_ts < :timestamp")
fun getOldArchived(timestamp: Long): List<ArchivedConversation>
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun archiveConversation(archivedConversation: ArchivedConversation)
@Query("SELECT * FROM conversations WHERE thread_id = :threadId") @Query("SELECT * FROM conversations WHERE thread_id = :threadId")
fun getConversationWithThreadId(threadId: Long): Conversation? fun getConversationWithThreadId(threadId: Long): Conversation?
@ -39,15 +29,12 @@ interface ConversationsDao {
@Query("UPDATE conversations SET read = 0 WHERE thread_id = :threadId") @Query("UPDATE conversations SET read = 0 WHERE thread_id = :threadId")
fun markUnread(threadId: Long) fun markUnread(threadId: Long)
@Query("UPDATE conversations SET archived = 1 WHERE thread_id = :threadId")
fun moveToArchive(threadId: Long)
@Query("UPDATE conversations SET archived = 0 WHERE thread_id = :threadId")
fun unarchive(threadId: Long)
@Query("DELETE FROM conversations WHERE thread_id = :threadId") @Query("DELETE FROM conversations WHERE thread_id = :threadId")
fun deleteThreadFromConversations(threadId: Long) fun deleteThreadId(threadId: Long)
@Query("DELETE FROM archived_conversations WHERE thread_id = :threadId")
fun deleteThreadFromArchivedConversations(threadId: Long)
@Transaction
fun deleteThreadId(threadId: Long) {
deleteThreadFromConversations(threadId)
deleteThreadFromArchivedConversations(threadId)
}
} }

View File

@ -16,7 +16,8 @@ data class Conversation(
@ColumnInfo(name = "is_group_conversation") var isGroupConversation: Boolean, @ColumnInfo(name = "is_group_conversation") var isGroupConversation: Boolean,
@ColumnInfo(name = "phone_number") var phoneNumber: String, @ColumnInfo(name = "phone_number") var phoneNumber: String,
@ColumnInfo(name = "is_scheduled") var isScheduled: Boolean = false, @ColumnInfo(name = "is_scheduled") var isScheduled: Boolean = false,
@ColumnInfo(name = "uses_custom_title") var usesCustomTitle: Boolean = false @ColumnInfo(name = "uses_custom_title") var usesCustomTitle: Boolean = false,
@ColumnInfo(name = "archived") var isArchived: Boolean = false
) { ) {
companion object { companion object {

View File

@ -100,7 +100,7 @@ class SmsReceiver : BroadcastReceiver() {
subscriptionId subscriptionId
) )
context.messagesDB.insertOrUpdate(message) context.messagesDB.insertOrUpdate(message)
context.conversationsDB.deleteThreadFromArchivedConversations(threadId) context.updateConversationArchivedStatus(threadId, false)
refreshMessages() refreshMessages()
context.showReceivedMessageNotification(newMessageId, address, body, threadId, bitmap) context.showReceivedMessageNotification(newMessageId, address, body, threadId, bitmap)
} }

View File

@ -0,0 +1,3 @@
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M20.54,5.23l-1.39,-1.68C18.88,3.21 18.47,3 18,3H6c-0.47,0 -0.88,0.21 -1.16,0.55L3.46,5.23C3.17,5.57 3,6.02 3,6.5V19c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2V6.5c0,-0.48 -0.17,-0.93 -0.46,-1.27zM12,17.5L6.5,12H10v-2h4v2h3.5L12,17.5zM5.12,5l0.81,-1h12l0.94,1H5.12z"/>
</vector>

View File

@ -0,0 +1,3 @@
<vector android:height="24dp" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M20.55,5.22l-1.39,-1.68C18.88,3.21 18.47,3 18,3H6C5.53,3 5.12,3.21 4.85,3.55L3.46,5.22C3.17,5.57 3,6.01 3,6.5V19c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2V6.5C21,6.01 20.83,5.57 20.55,5.22zM12,9.5l5.5,5.5H14v2h-4v-2H6.5L12,9.5zM5.12,5l0.82,-1h12l0.93,1H5.12z"/>
</vector>

View File

@ -346,55 +346,6 @@
android:id="@+id/settings_outgoing_messages_divider" android:id="@+id/settings_outgoing_messages_divider"
layout="@layout/divider" /> layout="@layout/divider" />
<TextView
android:id="@+id/settings_archive_label"
style="@style/SettingsSectionLabelStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/archived_conversations" />
<RelativeLayout
android:id="@+id/settings_use_archive_holder"
style="@style/SettingsHolderCheckboxStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.simplemobiletools.commons.views.MyAppCompatCheckbox
android:id="@+id/settings_use_archive"
style="@style/SettingsCheckboxStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/archive_instead_of_delete" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/settings_empty_archive_holder"
style="@style/SettingsHolderTextViewStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/settings_empty_archive_label"
style="@style/SettingsTextLabelStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/empty_archive" />
<com.simplemobiletools.commons.views.MyTextView
android:id="@+id/settings_empty_archive_size"
style="@style/SettingsTextValueStyle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/settings_empty_archive_label"
tools:text="0 B" />
</RelativeLayout>
<include
android:id="@+id/settings_archive_divider"
layout="@layout/divider" />
<TextView <TextView
android:id="@+id/settings_security_label" android:id="@+id/settings_security_label"
style="@style/SettingsSectionLabelStyle" style="@style/SettingsSectionLabelStyle"

View File

@ -9,14 +9,15 @@
android:showAsAction="always" android:showAsAction="always"
android:title="@string/delete" android:title="@string/delete"
app:showAsAction="always" /> app:showAsAction="always" />
<item
android:id="@+id/cab_unarchive"
android:icon="@drawable/ic_unarchive_vector"
android:showAsAction="ifRoom"
android:title="@string/unarchive"
app:showAsAction="ifRoom" />
<item <item
android:id="@+id/cab_select_all" android:id="@+id/cab_select_all"
android:icon="@drawable/ic_select_all_vector" android:icon="@drawable/ic_select_all_vector"
android:title="@string/select_all" android:title="@string/select_all"
app:showAsAction="ifRoom" /> app:showAsAction="ifRoom" />
<item
android:id="@+id/cab_unarchive"
android:showAsAction="never"
android:title="@string/unarchive"
app:showAsAction="never" />
</menu> </menu>

View File

@ -26,6 +26,12 @@
android:icon="@drawable/ic_minus_circle_vector" android:icon="@drawable/ic_minus_circle_vector"
android:title="@string/block_number" android:title="@string/block_number"
app:showAsAction="ifRoom" /> app:showAsAction="ifRoom" />
<item
android:id="@+id/cab_archive"
android:icon="@drawable/ic_archive_vector"
android:showAsAction="ifRoom"
android:title="@string/archive"
app:showAsAction="ifRoom" />
<item <item
android:id="@+id/cab_copy_number" android:id="@+id/cab_copy_number"
android:showAsAction="never" android:showAsAction="never"

View File

@ -23,6 +23,16 @@
android:icon="@drawable/ic_edit_vector" android:icon="@drawable/ic_edit_vector"
android:title="@string/rename_conversation" android:title="@string/rename_conversation"
app:showAsAction="always" /> app:showAsAction="always" />
<item
android:id="@+id/archive"
android:icon="@drawable/ic_archive_vector"
android:title="@string/archive"
app:showAsAction="ifRoom" />
<item
android:id="@+id/unarchive"
android:icon="@drawable/ic_unarchive_vector"
android:title="@string/unarchive"
app:showAsAction="ifRoom" />
<item <item
android:id="@+id/conversation_details" android:id="@+id/conversation_details"
android:icon="@drawable/ic_info_vector" android:icon="@drawable/ic_info_vector"