Clear drafts instead of deleting them

Closes https://github.com/FossifyOrg/Messages/issues/13
This commit is contained in:
Naveen Singh 2025-01-04 03:23:59 +05:30
parent 4434d187bc
commit f343085703
No known key found for this signature in database
GPG key ID: AF5D43C216778C0B
3 changed files with 65 additions and 45 deletions

View file

@ -117,7 +117,6 @@ import org.fossify.messages.extensions.createTemporaryThread
import org.fossify.messages.extensions.deleteConversation import org.fossify.messages.extensions.deleteConversation
import org.fossify.messages.extensions.deleteMessage import org.fossify.messages.extensions.deleteMessage
import org.fossify.messages.extensions.deleteScheduledMessage import org.fossify.messages.extensions.deleteScheduledMessage
import org.fossify.messages.extensions.deleteSmsDraft
import org.fossify.messages.extensions.dialNumber import org.fossify.messages.extensions.dialNumber
import org.fossify.messages.extensions.emptyMessagesRecycleBinForConversation import org.fossify.messages.extensions.emptyMessagesRecycleBinForConversation
import org.fossify.messages.extensions.getAddresses import org.fossify.messages.extensions.getAddresses
@ -282,7 +281,7 @@ class ThreadActivity : SimpleActivity() {
) )
val smsDraft = getSmsDraft(threadId) val smsDraft = getSmsDraft(threadId)
if (smsDraft != null) { if (!smsDraft.isNullOrEmpty()) {
binding.messageHolder.threadTypeMessage.setText(smsDraft) binding.messageHolder.threadTypeMessage.setText(smsDraft)
} }
isActivityVisible = true isActivityVisible = true
@ -307,17 +306,16 @@ class ThreadActivity : SimpleActivity() {
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
val draftMessage = binding.messageHolder.threadTypeMessage.value saveDraftMessage()
if (draftMessage.isNotEmpty() && getAttachmentSelections().isEmpty()) {
saveSmsDraft(draftMessage, threadId)
} else {
deleteSmsDraft(threadId)
}
bus?.post(Events.RefreshMessages()) bus?.post(Events.RefreshMessages())
isActivityVisible = false isActivityVisible = false
} }
override fun onStop() {
super.onStop()
saveDraftMessage()
}
override fun onBackPressed() { override fun onBackPressed() {
isAttachmentPickerVisible = false isAttachmentPickerVisible = false
if (binding.messageHolder.attachmentPickerHolder.isVisible()) { if (binding.messageHolder.attachmentPickerHolder.isVisible()) {
@ -332,6 +330,15 @@ class ThreadActivity : SimpleActivity() {
bus?.unregister(this) bus?.unregister(this)
} }
private fun saveDraftMessage() {
val draftMessage = binding.messageHolder.threadTypeMessage.value
if (getAttachmentSelections().isEmpty()) {
saveSmsDraft(draftMessage, threadId)
} else {
saveSmsDraft("", threadId)
}
}
private fun refreshMenuItems() { private fun refreshMenuItems() {
val firstPhoneNumber = participants.firstOrNull()?.phoneNumbers?.firstOrNull()?.value val firstPhoneNumber = participants.firstOrNull()?.phoneNumbers?.firstOrNull()?.value
val archiveAvailable = config.isArchiveAvailable val archiveAvailable = config.isArchiveAvailable

View file

@ -1,5 +1,6 @@
package org.fossify.messages.adapters package org.fossify.messages.adapters
import android.annotation.SuppressLint
import android.graphics.Typeface import android.graphics.Typeface
import android.os.Parcelable import android.os.Parcelable
import android.util.TypedValue import android.util.TypedValue
@ -10,7 +11,11 @@ import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller import com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller
import org.fossify.commons.adapters.MyRecyclerViewListAdapter import org.fossify.commons.adapters.MyRecyclerViewListAdapter
import org.fossify.commons.extensions.* import org.fossify.commons.extensions.applyColorFilter
import org.fossify.commons.extensions.beVisibleIf
import org.fossify.commons.extensions.formatDateOrTime
import org.fossify.commons.extensions.getTextSize
import org.fossify.commons.extensions.setupViewBackground
import org.fossify.commons.helpers.SimpleContactsHelper import org.fossify.commons.helpers.SimpleContactsHelper
import org.fossify.commons.helpers.ensureBackgroundThread import org.fossify.commons.helpers.ensureBackgroundThread
import org.fossify.commons.views.MyRecyclerView import org.fossify.commons.views.MyRecyclerView
@ -22,11 +27,20 @@ import org.fossify.messages.models.Conversation
@Suppress("LeakingThis") @Suppress("LeakingThis")
abstract class BaseConversationsAdapter( abstract class BaseConversationsAdapter(
activity: SimpleActivity, recyclerView: MyRecyclerView, onRefresh: () -> Unit, itemClick: (Any) -> Unit activity: SimpleActivity,
) : MyRecyclerViewListAdapter<Conversation>(activity, recyclerView, ConversationDiffCallback(), itemClick, onRefresh), recyclerView: MyRecyclerView,
onRefresh: () -> Unit,
itemClick: (Any) -> Unit
) : MyRecyclerViewListAdapter<Conversation>(
activity,
recyclerView,
ConversationDiffCallback(),
itemClick,
onRefresh
),
RecyclerViewFastScroller.OnPopupTextUpdate { RecyclerViewFastScroller.OnPopupTextUpdate {
private var fontSize = activity.getTextSize() private var fontSize = activity.getTextSize()
private var drafts = HashMap<Long, String?>() private var drafts = HashMap<Long, String>()
private var recyclerViewState: Parcelable? = null private var recyclerViewState: Parcelable? = null
@ -39,24 +53,32 @@ abstract class BaseConversationsAdapter(
registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() { registerAdapterDataObserver(object : RecyclerView.AdapterDataObserver() {
override fun onChanged() = restoreRecyclerViewState() override fun onChanged() = restoreRecyclerViewState()
override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) = restoreRecyclerViewState() override fun onItemRangeMoved(fromPosition: Int, toPosition: Int, itemCount: Int) =
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) = restoreRecyclerViewState() restoreRecyclerViewState()
override fun onItemRangeInserted(positionStart: Int, itemCount: Int) =
restoreRecyclerViewState()
}) })
} }
@SuppressLint("NotifyDataSetChanged")
fun updateFontSize() { fun updateFontSize() {
fontSize = activity.getTextSize() fontSize = activity.getTextSize()
notifyDataSetChanged() notifyDataSetChanged()
} }
fun updateConversations(newConversations: ArrayList<Conversation>, commitCallback: (() -> Unit)? = null) { fun updateConversations(
newConversations: ArrayList<Conversation>,
commitCallback: (() -> Unit)? = null
) {
saveRecyclerViewState() saveRecyclerViewState()
submitList(newConversations.toList(), commitCallback) submitList(newConversations.toList(), commitCallback)
} }
@SuppressLint("NotifyDataSetChanged")
fun updateDrafts() { fun updateDrafts() {
ensureBackgroundThread { ensureBackgroundThread {
val newDrafts = HashMap<Long, String?>() val newDrafts = HashMap<Long, String>()
fetchDrafts(newDrafts) fetchDrafts(newDrafts)
if (drafts.hashCode() != newDrafts.hashCode()) { if (drafts.hashCode() != newDrafts.hashCode()) {
drafts = newDrafts drafts = newDrafts
@ -69,7 +91,8 @@ abstract class BaseConversationsAdapter(
override fun getSelectableItemCount() = itemCount override fun getSelectableItemCount() = itemCount
protected fun getSelectedItems() = currentList.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation> protected fun getSelectedItems() =
currentList.filter { selectedKeys.contains(it.hashCode()) } as ArrayList<Conversation>
override fun getIsItemSelectable(position: Int) = true override fun getIsItemSelectable(position: Int) = true
@ -88,7 +111,11 @@ abstract class BaseConversationsAdapter(
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val conversation = getItem(position) val conversation = getItem(position)
holder.bindView(conversation, allowSingleClick = true, allowLongClick = true) { itemView, _ -> holder.bindView(
conversation,
allowSingleClick = true,
allowLongClick = true
) { itemView, _ ->
setupView(itemView, conversation) setupView(itemView, conversation)
} }
bindViewHolder(holder) bindViewHolder(holder)
@ -104,7 +131,7 @@ abstract class BaseConversationsAdapter(
} }
} }
private fun fetchDrafts(drafts: HashMap<Long, String?>) { private fun fetchDrafts(drafts: HashMap<Long, String>) {
drafts.clear() drafts.clear()
for ((threadId, draft) in activity.getAllDrafts()) { for ((threadId, draft) in activity.getAllDrafts()) {
drafts[threadId] = draft drafts[threadId] = draft
@ -115,7 +142,7 @@ abstract class BaseConversationsAdapter(
ItemConversationBinding.bind(view).apply { ItemConversationBinding.bind(view).apply {
root.setupViewBackground(activity) root.setupViewBackground(activity)
val smsDraft = drafts[conversation.threadId] val smsDraft = drafts[conversation.threadId]
draftIndicator.beVisibleIf(smsDraft != null) draftIndicator.beVisibleIf(!smsDraft.isNullOrEmpty())
draftIndicator.setTextColor(properPrimaryColor) draftIndicator.setTextColor(properPrimaryColor)
pinIndicator.beVisibleIf(activity.config.pinnedConversations.contains(conversation.threadId.toString())) pinIndicator.beVisibleIf(activity.config.pinnedConversations.contains(conversation.threadId.toString()))
@ -160,7 +187,12 @@ abstract class BaseConversationsAdapter(
null null
} }
SimpleContactsHelper(activity).loadContactImage(conversation.photoUri, conversationImage, conversation.title, placeholder) SimpleContactsHelper(activity).loadContactImage(
conversation.photoUri,
conversationImage,
conversation.title,
placeholder
)
} }
} }

View file

@ -1064,8 +1064,8 @@ fun Context.getSmsDraft(threadId: Long): String? {
return null return null
} }
fun Context.getAllDrafts(): HashMap<Long, String?> { fun Context.getAllDrafts(): HashMap<Long, String> {
val drafts = HashMap<Long, String?>() val drafts = HashMap<Long, String>()
val uri = Sms.Draft.CONTENT_URI val uri = Sms.Draft.CONTENT_URI
val projection = arrayOf(Sms.BODY, Sms.THREAD_ID) val projection = arrayOf(Sms.BODY, Sms.THREAD_ID)
@ -1075,20 +1075,19 @@ fun Context.getAllDrafts(): HashMap<Long, String?> {
while (it.moveToNext()) { while (it.moveToNext()) {
val threadId = it.getLongValue(Sms.THREAD_ID) val threadId = it.getLongValue(Sms.THREAD_ID)
val draft = it.getStringValue(Sms.BODY) val draft = it.getStringValue(Sms.BODY)
if (draft != null) { if (!draft.isNullOrEmpty()) {
drafts[threadId] = draft drafts[threadId] = draft
} }
} }
} }
} catch (e: Exception) { } catch (e: Exception) {
e.printStackTrace()
} }
return drafts return drafts
} }
fun Context.saveSmsDraft(body: String, threadId: Long) { fun Context.saveSmsDraft(body: String, threadId: Long) {
deleteSmsDraft(threadId)
val uri = Sms.Draft.CONTENT_URI val uri = Sms.Draft.CONTENT_URI
val contentValues = ContentValues().apply { val contentValues = ContentValues().apply {
put(Sms.BODY, body) put(Sms.BODY, body)
@ -1104,24 +1103,6 @@ fun Context.saveSmsDraft(body: String, threadId: Long) {
} }
} }
fun Context.deleteSmsDraft(threadId: Long) {
val uri = Sms.Draft.CONTENT_URI
val projection = arrayOf(Sms._ID)
val selection = "${Sms.THREAD_ID} = ?"
val selectionArgs = arrayOf(threadId.toString())
queryCursor(
uri = uri,
projection = projection,
selection = selection,
selectionArgs = selectionArgs,
showErrors = true
) { cursor ->
val draftId = cursor.getLongValue(Sms._ID)
val draftUri = Uri.withAppendedPath(Sms.CONTENT_URI, "/${draftId}")
contentResolver.delete(draftUri, null, null)
}
}
fun Context.updateLastConversationMessage(threadId: Long) { fun Context.updateLastConversationMessage(threadId: Long) {
updateLastConversationMessage(setOf(threadId)) updateLastConversationMessage(setOf(threadId))
} }