mirror of
https://github.com/SimpleMobileTools/Simple-SMS-Messenger.git
synced 2025-02-16 11:40:51 +01:00
Add separate screen for recycle bin messages
This commit is contained in:
parent
31be5d3d95
commit
3f06b521bf
@ -191,6 +191,7 @@ class MainActivity : SimpleActivity() {
|
|||||||
private fun refreshMenuItems() {
|
private fun refreshMenuItems() {
|
||||||
main_menu.getToolbar().menu.apply {
|
main_menu.getToolbar().menu.apply {
|
||||||
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(R.bool.hide_google_relations)
|
findItem(R.id.more_apps_from_us).isVisible = !resources.getBoolean(R.bool.hide_google_relations)
|
||||||
|
findItem(R.id.show_recycle_bin).isVisible = config.useRecycleBin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import com.simplemobiletools.commons.extensions.*
|
|||||||
import com.simplemobiletools.commons.helpers.*
|
import com.simplemobiletools.commons.helpers.*
|
||||||
import com.simplemobiletools.smsmessenger.R
|
import com.simplemobiletools.smsmessenger.R
|
||||||
import com.simplemobiletools.smsmessenger.adapters.ConversationsAdapter
|
import com.simplemobiletools.smsmessenger.adapters.ConversationsAdapter
|
||||||
|
import com.simplemobiletools.smsmessenger.adapters.RecycleBinConversationsAdapter
|
||||||
import com.simplemobiletools.smsmessenger.extensions.*
|
import com.simplemobiletools.smsmessenger.extensions.*
|
||||||
import com.simplemobiletools.smsmessenger.helpers.*
|
import com.simplemobiletools.smsmessenger.helpers.*
|
||||||
import com.simplemobiletools.smsmessenger.models.Conversation
|
import com.simplemobiletools.smsmessenger.models.Conversation
|
||||||
@ -97,11 +98,11 @@ class RecycleBinConversationsActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getOrCreateConversationsAdapter(): ConversationsAdapter {
|
private fun getOrCreateConversationsAdapter(): RecycleBinConversationsAdapter {
|
||||||
var currAdapter = conversations_list.adapter
|
var currAdapter = conversations_list.adapter
|
||||||
if (currAdapter == null) {
|
if (currAdapter == null) {
|
||||||
hideKeyboard()
|
hideKeyboard()
|
||||||
currAdapter = ConversationsAdapter(
|
currAdapter = RecycleBinConversationsAdapter(
|
||||||
activity = this,
|
activity = this,
|
||||||
recyclerView = conversations_list,
|
recyclerView = conversations_list,
|
||||||
onRefresh = { notifyDatasetChanged() },
|
onRefresh = { notifyDatasetChanged() },
|
||||||
@ -113,7 +114,7 @@ class RecycleBinConversationsActivity : SimpleActivity() {
|
|||||||
conversations_list.scheduleLayoutAnimation()
|
conversations_list.scheduleLayoutAnimation()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return currAdapter as ConversationsAdapter
|
return currAdapter as RecycleBinConversationsAdapter
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupConversations(conversations: ArrayList<Conversation>) {
|
private fun setupConversations(conversations: ArrayList<Conversation>) {
|
||||||
@ -150,6 +151,7 @@ class RecycleBinConversationsActivity : SimpleActivity() {
|
|||||||
putExtra(THREAD_ID, conversation.threadId)
|
putExtra(THREAD_ID, conversation.threadId)
|
||||||
putExtra(THREAD_TITLE, conversation.title)
|
putExtra(THREAD_TITLE, conversation.title)
|
||||||
putExtra(WAS_PROTECTION_HANDLED, true)
|
putExtra(WAS_PROTECTION_HANDLED, true)
|
||||||
|
putExtra(IS_RECYCLE_BIN, true)
|
||||||
startActivity(this)
|
startActivity(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,6 +105,7 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
private var allMessagesFetched = false
|
private var allMessagesFetched = false
|
||||||
private var oldestMessageDate = -1
|
private var oldestMessageDate = -1
|
||||||
private var wasProtectionHandled = false
|
private var wasProtectionHandled = false
|
||||||
|
private var isRecycleBin = false
|
||||||
|
|
||||||
private var isScheduledMessage: Boolean = false
|
private var isScheduledMessage: Boolean = false
|
||||||
private var scheduledMessage: Message? = null
|
private var scheduledMessage: Message? = null
|
||||||
@ -140,6 +141,7 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
intent.getStringExtra(THREAD_TITLE)?.let {
|
intent.getStringExtra(THREAD_TITLE)?.let {
|
||||||
thread_toolbar.title = it
|
thread_toolbar.title = it
|
||||||
}
|
}
|
||||||
|
isRecycleBin = intent.getBooleanExtra(IS_RECYCLE_BIN, false)
|
||||||
wasProtectionHandled = intent.getBooleanExtra(WAS_PROTECTION_HANDLED, false)
|
wasProtectionHandled = intent.getBooleanExtra(WAS_PROTECTION_HANDLED, false)
|
||||||
|
|
||||||
bus = EventBus.getDefault()
|
bus = EventBus.getDefault()
|
||||||
@ -163,6 +165,7 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
setupAttachmentPickerView()
|
setupAttachmentPickerView()
|
||||||
setupKeyboardListener()
|
setupKeyboardListener()
|
||||||
hideAttachmentPicker()
|
hideAttachmentPicker()
|
||||||
|
maybeSetupRecycleBinView()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
@ -247,20 +250,21 @@ 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.restore).isVisible = threadItems.isNotEmpty() && isRecycleBin
|
||||||
findItem(R.id.unarchive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == true
|
findItem(R.id.archive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == false && !isRecycleBin
|
||||||
findItem(R.id.rename_conversation).isVisible = participants.size > 1 && conversation != null
|
findItem(R.id.unarchive).isVisible = threadItems.isNotEmpty() && conversation?.isArchived == true && !isRecycleBin
|
||||||
findItem(R.id.conversation_details).isVisible = conversation != null
|
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(R.string.block_number)
|
findItem(R.id.block_number).title = addLockedLabelIfNeeded(R.string.block_number)
|
||||||
findItem(R.id.block_number).isVisible = isNougatPlus()
|
findItem(R.id.block_number).isVisible = isNougatPlus() && !isRecycleBin
|
||||||
findItem(R.id.dial_number).isVisible = participants.size == 1 && !isSpecialNumber()
|
findItem(R.id.dial_number).isVisible = participants.size == 1 && !isSpecialNumber() && !isRecycleBin
|
||||||
findItem(R.id.manage_people).isVisible = !isSpecialNumber()
|
findItem(R.id.manage_people).isVisible = !isSpecialNumber() && !isRecycleBin
|
||||||
findItem(R.id.mark_as_unread).isVisible = threadItems.isNotEmpty()
|
findItem(R.id.mark_as_unread).isVisible = threadItems.isNotEmpty() && !isRecycleBin
|
||||||
|
|
||||||
// allow saving number in cases when we dont have it stored yet and it is a casual readable number
|
// allow saving number in cases when we dont have it stored yet and it is a casual readable number
|
||||||
findItem(R.id.add_number_to_contact).isVisible = participants.size == 1 && participants.first().name == firstPhoneNumber && firstPhoneNumber.any {
|
findItem(R.id.add_number_to_contact).isVisible = participants.size == 1 && participants.first().name == firstPhoneNumber && firstPhoneNumber.any {
|
||||||
it.isDigit()
|
it.isDigit()
|
||||||
}
|
} && !isRecycleBin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -273,6 +277,7 @@ 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.restore -> askConfirmRestoreAll()
|
||||||
R.id.archive -> archiveConversation()
|
R.id.archive -> archiveConversation()
|
||||||
R.id.unarchive -> unarchiveConversation()
|
R.id.unarchive -> unarchiveConversation()
|
||||||
R.id.rename_conversation -> renameConversation()
|
R.id.rename_conversation -> renameConversation()
|
||||||
@ -306,7 +311,11 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
private fun setupCachedMessages(callback: () -> Unit) {
|
private fun setupCachedMessages(callback: () -> Unit) {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
messages = try {
|
messages = try {
|
||||||
messagesDB.getThreadMessages(threadId).toMutableList() as ArrayList<Message>
|
if (isRecycleBin) {
|
||||||
|
messagesDB.getThreadMessagesFromRecycleBin(threadId).toMutableList() as ArrayList<Message>
|
||||||
|
} else {
|
||||||
|
messagesDB.getThreadMessages(threadId).toMutableList() as ArrayList<Message>
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
ArrayList()
|
ArrayList()
|
||||||
}
|
}
|
||||||
@ -341,7 +350,10 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor)
|
privateContacts = MyContactsContentProvider.getSimpleContacts(this, privateCursor)
|
||||||
|
|
||||||
val cachedMessagesCode = messages.clone().hashCode()
|
val cachedMessagesCode = messages.clone().hashCode()
|
||||||
messages = getMessages(threadId, true)
|
if (!isRecycleBin) {
|
||||||
|
val recycledMessages = messagesDB.getThreadMessagesFromRecycleBin(threadId).map { it.id }
|
||||||
|
messages = getMessages(threadId, true).filter { !recycledMessages.contains(it.id) }.toMutableList() as ArrayList<Message>
|
||||||
|
}
|
||||||
|
|
||||||
val hasParticipantWithoutName = participants.any { contact ->
|
val hasParticipantWithoutName = participants.any { contact ->
|
||||||
contact.phoneNumbers.map { it.normalizedNumber }.contains(contact.name)
|
contact.phoneNumbers.map { it.normalizedNumber }.contains(contact.name)
|
||||||
@ -389,8 +401,10 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
participants.add(contact)
|
participants.add(contact)
|
||||||
}
|
}
|
||||||
|
|
||||||
messages.chunked(30).forEach { currentMessages ->
|
if (!isRecycleBin) {
|
||||||
messagesDB.insertMessages(*currentMessages.toTypedArray())
|
messages.chunked(30).forEach { currentMessages ->
|
||||||
|
messagesDB.insertMessages(*currentMessages.toTypedArray())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setupAttachmentSizes()
|
setupAttachmentSizes()
|
||||||
@ -409,7 +423,8 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
activity = this,
|
activity = this,
|
||||||
recyclerView = thread_messages_list,
|
recyclerView = thread_messages_list,
|
||||||
itemClick = { handleItemClick(it) },
|
itemClick = { handleItemClick(it) },
|
||||||
deleteMessages = { messages, toRecycleBin -> deleteMessages(messages, toRecycleBin) }
|
isRecycleBin = isRecycleBin,
|
||||||
|
deleteMessages = { messages, toRecycleBin, fromRecycleBin -> deleteMessages(messages, toRecycleBin, fromRecycleBin) }
|
||||||
)
|
)
|
||||||
|
|
||||||
thread_messages_list.adapter = currAdapter
|
thread_messages_list.adapter = currAdapter
|
||||||
@ -496,7 +511,7 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun deleteMessages(messagesToRemove: List<Message>, toRecycleBin: Boolean) {
|
private fun deleteMessages(messagesToRemove: List<Message>, toRecycleBin: Boolean, fromRecycleBin: Boolean) {
|
||||||
val deletePosition = threadItems.indexOf(messagesToRemove.first())
|
val deletePosition = threadItems.indexOf(messagesToRemove.first())
|
||||||
messages.removeAll(messagesToRemove.toSet())
|
messages.removeAll(messagesToRemove.toSet())
|
||||||
threadItems = getThreadItems()
|
threadItems = getThreadItems()
|
||||||
@ -515,12 +530,13 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
messagesToRemove.forEach { message ->
|
messagesToRemove.forEach { message ->
|
||||||
val messageId = message.id
|
val messageId = message.id
|
||||||
if (message.isScheduled) {
|
if (message.isScheduled) {
|
||||||
// TODO: Moving scheduled messages to recycle bin maybe doesn't make sense
|
|
||||||
deleteScheduledMessage(messageId)
|
deleteScheduledMessage(messageId)
|
||||||
cancelScheduleSendPendingIntent(messageId)
|
cancelScheduleSendPendingIntent(messageId)
|
||||||
} else {
|
} else {
|
||||||
if (toRecycleBin) {
|
if (toRecycleBin) {
|
||||||
moveMessageToRecycleBin(messageId)
|
moveMessageToRecycleBin(messageId)
|
||||||
|
} else if (fromRecycleBin) {
|
||||||
|
restoreMessageFromRecycleBin(messageId)
|
||||||
} else {
|
} else {
|
||||||
deleteMessage(messageId, message.isMMS)
|
deleteMessage(messageId, message.isMMS)
|
||||||
}
|
}
|
||||||
@ -792,7 +808,7 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun maybeDisableShortCodeReply() {
|
private fun maybeDisableShortCodeReply() {
|
||||||
if (isSpecialNumber()) {
|
if (isSpecialNumber() && !isRecycleBin) {
|
||||||
thread_send_message_holder.beGone()
|
thread_send_message_holder.beGone()
|
||||||
reply_disabled_info_holder.beVisible()
|
reply_disabled_info_holder.beVisible()
|
||||||
val textColor = getProperTextColor()
|
val textColor = getProperTextColor()
|
||||||
@ -922,7 +938,23 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
val confirmationMessage = R.string.delete_whole_conversation_confirmation
|
val confirmationMessage = R.string.delete_whole_conversation_confirmation
|
||||||
ConfirmationDialog(this, getString(confirmationMessage)) {
|
ConfirmationDialog(this, getString(confirmationMessage)) {
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
deleteConversation(threadId)
|
if (isRecycleBin) {
|
||||||
|
emptyMessagesRecycleBinForConversation(threadId)
|
||||||
|
} else {
|
||||||
|
deleteConversation(threadId)
|
||||||
|
}
|
||||||
|
runOnUiThread {
|
||||||
|
refreshMessages()
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun askConfirmRestoreAll() {
|
||||||
|
ConfirmationDialog(this, "Restore all messages from this conversation?") {
|
||||||
|
ensureBackgroundThread {
|
||||||
|
restoreAllMessagesFromRecycleBinForConversation(threadId)
|
||||||
runOnUiThread {
|
runOnUiThread {
|
||||||
refreshMessages()
|
refreshMessages()
|
||||||
finish()
|
finish()
|
||||||
@ -1485,6 +1517,10 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.ASYNC)
|
@Subscribe(threadMode = ThreadMode.ASYNC)
|
||||||
fun refreshMessages(event: Events.RefreshMessages) {
|
fun refreshMessages(event: Events.RefreshMessages) {
|
||||||
|
if (isRecycleBin) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
refreshedSinceSent = true
|
refreshedSinceSent = true
|
||||||
allMessagesFetched = false
|
allMessagesFetched = false
|
||||||
oldestMessageDate = -1
|
oldestMessageDate = -1
|
||||||
@ -1747,6 +1783,12 @@ class ThreadActivity : SimpleActivity() {
|
|||||||
animateAttachmentButton(rotation = -135f)
|
animateAttachmentButton(rotation = -135f)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun maybeSetupRecycleBinView() {
|
||||||
|
if (isRecycleBin) {
|
||||||
|
thread_send_message_holder.beGone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun hideAttachmentPicker() {
|
private fun hideAttachmentPicker() {
|
||||||
attachment_picker_divider.beGone()
|
attachment_picker_divider.beGone()
|
||||||
attachment_picker_holder.apply {
|
attachment_picker_holder.apply {
|
||||||
|
@ -0,0 +1,107 @@
|
|||||||
|
package com.simplemobiletools.smsmessenger.adapters
|
||||||
|
|
||||||
|
import android.view.Menu
|
||||||
|
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||||
|
import com.simplemobiletools.commons.extensions.notificationManager
|
||||||
|
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||||
|
import com.simplemobiletools.commons.views.MyRecyclerView
|
||||||
|
import com.simplemobiletools.smsmessenger.R
|
||||||
|
import com.simplemobiletools.smsmessenger.activities.SimpleActivity
|
||||||
|
import com.simplemobiletools.smsmessenger.extensions.deleteConversation
|
||||||
|
import com.simplemobiletools.smsmessenger.extensions.restoreAllMessagesFromRecycleBinForConversation
|
||||||
|
import com.simplemobiletools.smsmessenger.helpers.refreshMessages
|
||||||
|
import com.simplemobiletools.smsmessenger.models.Conversation
|
||||||
|
|
||||||
|
class RecycleBinConversationsAdapter(
|
||||||
|
activity: SimpleActivity, recyclerView: MyRecyclerView, onRefresh: () -> Unit, itemClick: (Any) -> Unit
|
||||||
|
) : BaseConversationsAdapter(activity, recyclerView, onRefresh, itemClick) {
|
||||||
|
override fun getActionMenuId() = R.menu.cab_recycle_bin_conversations
|
||||||
|
|
||||||
|
override fun prepareActionMode(menu: Menu) {}
|
||||||
|
|
||||||
|
override fun actionItemPressed(id: Int) {
|
||||||
|
if (selectedKeys.isEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
when (id) {
|
||||||
|
R.id.cab_delete -> askConfirmDelete()
|
||||||
|
R.id.cab_restore -> askConfirmRestore()
|
||||||
|
R.id.cab_select_all -> selectAll()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun askConfirmDelete() {
|
||||||
|
val itemsCnt = selectedKeys.size
|
||||||
|
val items = resources.getQuantityString(R.plurals.delete_conversations, itemsCnt, itemsCnt)
|
||||||
|
|
||||||
|
val baseString = R.string.deletion_confirmation
|
||||||
|
val question = String.format(resources.getString(baseString), items)
|
||||||
|
|
||||||
|
ConfirmationDialog(activity, question) {
|
||||||
|
ensureBackgroundThread {
|
||||||
|
deleteConversations()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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())
|
||||||
|
}
|
||||||
|
|
||||||
|
removeConversationsFromList(conversationsToRemove)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun askConfirmRestore() {
|
||||||
|
val itemsCnt = selectedKeys.size
|
||||||
|
val items = resources.getQuantityString(R.plurals.delete_conversations, itemsCnt, itemsCnt)
|
||||||
|
|
||||||
|
val question = String.format("Are you sure you want to restore %s?", items)
|
||||||
|
|
||||||
|
ConfirmationDialog(activity, question) {
|
||||||
|
ensureBackgroundThread {
|
||||||
|
restoreConversations()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun restoreConversations() {
|
||||||
|
if (selectedKeys.isEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val conversationsToRemove = currentList.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation>
|
||||||
|
conversationsToRemove.forEach {
|
||||||
|
activity.restoreAllMessagesFromRecycleBinForConversation(it.threadId)
|
||||||
|
}
|
||||||
|
|
||||||
|
removeConversationsFromList(conversationsToRemove)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun removeConversationsFromList(removedConversations: List<Conversation>) {
|
||||||
|
val newList = try {
|
||||||
|
currentList.toMutableList().apply { removeAll(removedConversations) }
|
||||||
|
} catch (ignored: Exception) {
|
||||||
|
currentList.toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
|
activity.runOnUiThread {
|
||||||
|
if (newList.none { selectedKeys.contains(it.hashCode()) }) {
|
||||||
|
refreshMessages()
|
||||||
|
finishActMode()
|
||||||
|
} else {
|
||||||
|
submitList(newList)
|
||||||
|
if (newList.isEmpty()) {
|
||||||
|
refreshMessages()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -23,6 +23,7 @@ import com.bumptech.glide.request.RequestListener
|
|||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
import com.bumptech.glide.request.target.Target
|
import com.bumptech.glide.request.target.Target
|
||||||
import com.simplemobiletools.commons.adapters.MyRecyclerViewListAdapter
|
import com.simplemobiletools.commons.adapters.MyRecyclerViewListAdapter
|
||||||
|
import com.simplemobiletools.commons.dialogs.ConfirmationDialog
|
||||||
import com.simplemobiletools.commons.extensions.*
|
import com.simplemobiletools.commons.extensions.*
|
||||||
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
|
import com.simplemobiletools.commons.helpers.SimpleContactsHelper
|
||||||
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
import com.simplemobiletools.commons.helpers.ensureBackgroundThread
|
||||||
@ -58,7 +59,8 @@ class ThreadAdapter(
|
|||||||
activity: SimpleActivity,
|
activity: SimpleActivity,
|
||||||
recyclerView: MyRecyclerView,
|
recyclerView: MyRecyclerView,
|
||||||
itemClick: (Any) -> Unit,
|
itemClick: (Any) -> Unit,
|
||||||
val deleteMessages: (messages: List<Message>, toRecycleBin: Boolean) -> Unit
|
val isRecycleBin: Boolean,
|
||||||
|
val deleteMessages: (messages: List<Message>, toRecycleBin: Boolean, fromRecycleBin: Boolean) -> Unit
|
||||||
) : MyRecyclerViewListAdapter<ThreadItem>(activity, recyclerView, ThreadItemDiffCallback(), itemClick) {
|
) : MyRecyclerViewListAdapter<ThreadItem>(activity, recyclerView, ThreadItemDiffCallback(), itemClick) {
|
||||||
private var fontSize = activity.getTextSize()
|
private var fontSize = activity.getTextSize()
|
||||||
|
|
||||||
@ -84,6 +86,7 @@ class ThreadAdapter(
|
|||||||
findItem(R.id.cab_forward_message).isVisible = isOneItemSelected
|
findItem(R.id.cab_forward_message).isVisible = isOneItemSelected
|
||||||
findItem(R.id.cab_select_text).isVisible = isOneItemSelected && hasText
|
findItem(R.id.cab_select_text).isVisible = isOneItemSelected && hasText
|
||||||
findItem(R.id.cab_properties).isVisible = isOneItemSelected
|
findItem(R.id.cab_properties).isVisible = isOneItemSelected
|
||||||
|
findItem(R.id.cab_restore).isVisible = isRecycleBin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,6 +102,7 @@ class ThreadAdapter(
|
|||||||
R.id.cab_forward_message -> forwardMessage()
|
R.id.cab_forward_message -> forwardMessage()
|
||||||
R.id.cab_select_text -> selectText()
|
R.id.cab_select_text -> selectText()
|
||||||
R.id.cab_delete -> askConfirmDelete()
|
R.id.cab_delete -> askConfirmDelete()
|
||||||
|
R.id.cab_restore -> askConfirmRestore()
|
||||||
R.id.cab_select_all -> selectAll()
|
R.id.cab_select_all -> selectAll()
|
||||||
R.id.cab_properties -> showMessageDetails()
|
R.id.cab_properties -> showMessageDetails()
|
||||||
}
|
}
|
||||||
@ -206,12 +210,36 @@ class ThreadAdapter(
|
|||||||
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, activity.config.useRecycleBin) { skipRecycleBin ->
|
DeleteConfirmationDialog(activity, question, activity.config.useRecycleBin && !isRecycleBin) { skipRecycleBin ->
|
||||||
ensureBackgroundThread {
|
ensureBackgroundThread {
|
||||||
val messagesToRemove = getSelectedItems()
|
val messagesToRemove = getSelectedItems()
|
||||||
if (messagesToRemove.isNotEmpty()) {
|
if (messagesToRemove.isNotEmpty()) {
|
||||||
val toRecycleBin = !skipRecycleBin && activity.config.useRecycleBin
|
val toRecycleBin = !skipRecycleBin && activity.config.useRecycleBin && !isRecycleBin
|
||||||
deleteMessages(messagesToRemove.filterIsInstance<Message>(), toRecycleBin)
|
deleteMessages(messagesToRemove.filterIsInstance<Message>(), toRecycleBin, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun askConfirmRestore() {
|
||||||
|
val itemsCnt = selectedKeys.size
|
||||||
|
|
||||||
|
// not sure how we can get UnknownFormatConversionException here, so show the error and hope that someone reports it
|
||||||
|
val items = try {
|
||||||
|
resources.getQuantityString(R.plurals.delete_messages, itemsCnt, itemsCnt)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
activity.showErrorToast(e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val baseString = R.string.deletion_confirmation
|
||||||
|
val question = String.format("Are you sure you want to restore %s?", items)
|
||||||
|
|
||||||
|
ConfirmationDialog(activity, question) {
|
||||||
|
ensureBackgroundThread {
|
||||||
|
val messagesToRestore = getSelectedItems()
|
||||||
|
if (messagesToRestore.isNotEmpty()) {
|
||||||
|
deleteMessages(messagesToRestore.filterIsInstance<Message>(), false, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -679,6 +679,17 @@ fun Context.emptyMessagesRecycleBin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Context.emptyMessagesRecycleBinForConversation(threadId: Long) {
|
||||||
|
val messages = messagesDB.getThreadMessagesFromRecycleBin(threadId)
|
||||||
|
for (message in messages) {
|
||||||
|
deleteMessage(message.id, message.isMMS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Context.restoreAllMessagesFromRecycleBinForConversation(threadId: Long) {
|
||||||
|
messagesDB.deleteThreadMessagesFromRecycleBin(threadId)
|
||||||
|
}
|
||||||
|
|
||||||
fun Context.moveMessageToRecycleBin(id: Long) {
|
fun Context.moveMessageToRecycleBin(id: Long) {
|
||||||
try {
|
try {
|
||||||
messagesDB.insertRecycleBinEntry(RecycleBinMessage(id, System.currentTimeMillis()))
|
messagesDB.insertRecycleBinEntry(RecycleBinMessage(id, System.currentTimeMillis()))
|
||||||
@ -687,6 +698,14 @@ fun Context.moveMessageToRecycleBin(id: Long) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun Context.restoreMessageFromRecycleBin(id: Long) {
|
||||||
|
try {
|
||||||
|
messagesDB.deleteFromRecycleBin(id)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
showErrorToast(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun Context.updateConversationArchivedStatus(threadId: Long, archived: Boolean) {
|
fun Context.updateConversationArchivedStatus(threadId: Long, archived: Boolean) {
|
||||||
val uri = Threads.CONTENT_URI
|
val uri = Threads.CONTENT_URI
|
||||||
val values = ContentValues().apply {
|
val values = ContentValues().apply {
|
||||||
|
@ -42,7 +42,7 @@ const val IS_MMS = "is_mms"
|
|||||||
const val MESSAGE_ID = "message_id"
|
const val MESSAGE_ID = "message_id"
|
||||||
const val USE_RECYCLE_BIN = "use_recycle_bin"
|
const val USE_RECYCLE_BIN = "use_recycle_bin"
|
||||||
const val LAST_RECYCLE_BIN_CHECK = "last_recycle_bin_check"
|
const val LAST_RECYCLE_BIN_CHECK = "last_recycle_bin_check"
|
||||||
const val USE_ARCHIVE = "use_archive"
|
const val IS_RECYCLE_BIN = "is_recycle_bin"
|
||||||
|
|
||||||
private const val PATH = "com.simplemobiletools.smsmessenger.action."
|
private const val PATH = "com.simplemobiletools.smsmessenger.action."
|
||||||
const val MARK_AS_READ = PATH + "mark_as_read"
|
const val MARK_AS_READ = PATH + "mark_as_read"
|
||||||
|
@ -30,6 +30,9 @@ interface MessagesDao {
|
|||||||
@Query("SELECT messages.* FROM messages LEFT OUTER JOIN recycle_bin_messages ON messages.id = recycle_bin_messages.id WHERE recycle_bin_messages.id IS NULL AND thread_id = :threadId")
|
@Query("SELECT messages.* FROM messages LEFT OUTER JOIN recycle_bin_messages ON messages.id = recycle_bin_messages.id WHERE recycle_bin_messages.id IS NULL AND thread_id = :threadId")
|
||||||
fun getThreadMessages(threadId: Long): List<Message>
|
fun getThreadMessages(threadId: Long): List<Message>
|
||||||
|
|
||||||
|
@Query("SELECT messages.* FROM messages LEFT OUTER JOIN recycle_bin_messages ON messages.id = recycle_bin_messages.id WHERE recycle_bin_messages.id IS NOT NULL AND thread_id = :threadId")
|
||||||
|
fun getThreadMessagesFromRecycleBin(threadId: Long): List<Message>
|
||||||
|
|
||||||
@Query("SELECT messages.* FROM messages LEFT OUTER JOIN recycle_bin_messages ON messages.id = recycle_bin_messages.id WHERE recycle_bin_messages.id IS NULL AND thread_id = :threadId AND is_scheduled = 1")
|
@Query("SELECT messages.* FROM messages LEFT OUTER JOIN recycle_bin_messages ON messages.id = recycle_bin_messages.id WHERE recycle_bin_messages.id IS NULL AND thread_id = :threadId AND is_scheduled = 1")
|
||||||
fun getScheduledThreadMessages(threadId: Long): List<Message>
|
fun getScheduledThreadMessages(threadId: Long): List<Message>
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
<item
|
<item
|
||||||
android:id="@+id/cab_restore"
|
android:id="@+id/cab_restore"
|
||||||
android:showAsAction="never"
|
android:showAsAction="never"
|
||||||
android:title="Restore this message"
|
android:title="Restore all messages from this conversation"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/cab_select_all"
|
android:id="@+id/cab_select_all"
|
||||||
|
@ -31,6 +31,11 @@
|
|||||||
android:icon="@drawable/ic_info_vector"
|
android:icon="@drawable/ic_info_vector"
|
||||||
android:title="@string/properties"
|
android:title="@string/properties"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/cab_restore"
|
||||||
|
android:showAsAction="never"
|
||||||
|
android:title="Restore this message"
|
||||||
|
app:showAsAction="never" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/cab_forward_message"
|
android:id="@+id/cab_forward_message"
|
||||||
android:showAsAction="never"
|
android:showAsAction="never"
|
||||||
|
@ -47,6 +47,11 @@
|
|||||||
android:showAsAction="never"
|
android:showAsAction="never"
|
||||||
android:title="@string/block_number"
|
android:title="@string/block_number"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/restore"
|
||||||
|
android:showAsAction="never"
|
||||||
|
android:title="Restore all messages from this conversation"
|
||||||
|
app:showAsAction="never" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/mark_as_unread"
|
android:id="@+id/mark_as_unread"
|
||||||
android:showAsAction="never"
|
android:showAsAction="never"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user