Naveen Singh 2025-01-05 03:32:10 +05:30
parent 55c4e84ddc
commit f661e126df
No known key found for this signature in database
GPG key ID: AF5D43C216778C0B
6 changed files with 118 additions and 49 deletions

View file

@ -365,9 +365,8 @@ class MainActivity : SimpleActivity() {
)
}
if (conv != null) {
val lastModified = maxOf(cachedConv.date, conv.date)
val conversation = conv.copy(date = lastModified)
insertOrUpdateConversation(conversation)
// FIXME: Scheduled message date is being reset here.
insertOrUpdateConversation(conv)
}
}

View file

@ -117,6 +117,7 @@ import org.fossify.messages.extensions.createTemporaryThread
import org.fossify.messages.extensions.deleteConversation
import org.fossify.messages.extensions.deleteMessage
import org.fossify.messages.extensions.deleteScheduledMessage
import org.fossify.messages.extensions.deleteSmsDraft
import org.fossify.messages.extensions.dialNumber
import org.fossify.messages.extensions.emptyMessagesRecycleBinForConversation
import org.fossify.messages.extensions.getAddresses
@ -280,10 +281,6 @@ class ThreadActivity : SimpleActivity() {
statusBarColor = getProperBackgroundColor()
)
val smsDraft = getSmsDraft(threadId)
if (!smsDraft.isNullOrEmpty()) {
binding.messageHolder.threadTypeMessage.setText(smsDraft)
}
isActivityVisible = true
notificationManager.cancel(threadId.hashCode())
@ -296,6 +293,13 @@ class ThreadActivity : SimpleActivity() {
setupThreadTitle()
}
}
val smsDraft = getSmsDraft(threadId)
if (smsDraft.isNotEmpty()) {
runOnUiThread {
binding.messageHolder.threadTypeMessage.setText(smsDraft)
}
}
}
val bottomBarColor = getBottomBarColor()
@ -332,10 +336,12 @@ class ThreadActivity : SimpleActivity() {
private fun saveDraftMessage() {
val draftMessage = binding.messageHolder.threadTypeMessage.value
if (getAttachmentSelections().isEmpty()) {
saveSmsDraft(draftMessage, threadId)
} else {
saveSmsDraft("", threadId)
ensureBackgroundThread {
if (draftMessage.isNotEmpty() && getAttachmentSelections().isEmpty()) {
saveSmsDraft(draftMessage, threadId)
} else {
deleteSmsDraft(threadId)
}
}
}

View file

@ -10,11 +10,27 @@ import androidx.sqlite.db.SupportSQLiteDatabase
import org.fossify.messages.helpers.Converters
import org.fossify.messages.interfaces.AttachmentsDao
import org.fossify.messages.interfaces.ConversationsDao
import org.fossify.messages.interfaces.DraftsDao
import org.fossify.messages.interfaces.MessageAttachmentsDao
import org.fossify.messages.interfaces.MessagesDao
import org.fossify.messages.models.*
import org.fossify.messages.models.Attachment
import org.fossify.messages.models.Conversation
import org.fossify.messages.models.Draft
import org.fossify.messages.models.Message
import org.fossify.messages.models.MessageAttachment
import org.fossify.messages.models.RecycleBinMessage
@Database(entities = [Conversation::class, Attachment::class, MessageAttachment::class, Message::class, RecycleBinMessage::class], version = 8)
@Database(
entities = [
Conversation::class,
Attachment::class,
MessageAttachment::class,
Message::class,
RecycleBinMessage::class,
Draft::class
],
version = 9
)
@TypeConverters(Converters::class)
abstract class MessagesDatabase : RoomDatabase() {
@ -26,6 +42,8 @@ abstract class MessagesDatabase : RoomDatabase() {
abstract fun MessagesDao(): MessagesDao
abstract fun DraftsDao(): DraftsDao
companion object {
private var db: MessagesDatabase? = null
@ -33,7 +51,11 @@ abstract class MessagesDatabase : RoomDatabase() {
if (db == null) {
synchronized(MessagesDatabase::class) {
if (db == null) {
db = Room.databaseBuilder(context.applicationContext, MessagesDatabase::class.java, "conversations.db")
db = Room.databaseBuilder(
context = context.applicationContext,
klass = MessagesDatabase::class.java,
name = "conversations.db"
)
.fallbackToDestructiveMigration()
.addMigrations(MIGRATION_1_2)
.addMigrations(MIGRATION_2_3)
@ -42,6 +64,7 @@ abstract class MessagesDatabase : RoomDatabase() {
.addMigrations(MIGRATION_5_6)
.addMigrations(MIGRATION_6_7)
.addMigrations(MIGRATION_7_8)
.addMigrations(MIGRATION_8_9)
.build()
}
}
@ -69,7 +92,7 @@ abstract class MessagesDatabase : RoomDatabase() {
execSQL(
"INSERT OR IGNORE INTO conversations_new (thread_id, snippet, date, read, title, photo_uri, is_group_conversation, phone_number) " +
"SELECT thread_id, snippet, date, read, title, photo_uri, is_group_conversation, phone_number FROM conversations"
"SELECT thread_id, snippet, date, read, title, photo_uri, is_group_conversation, phone_number FROM conversations"
)
execSQL("DROP TABLE conversations")
@ -123,5 +146,13 @@ abstract class MessagesDatabase : RoomDatabase() {
}
}
}
private val MIGRATION_8_9 = object : Migration(8, 9) {
override fun migrate(db: SupportSQLiteDatabase) {
db.apply {
execSQL("CREATE TABLE IF NOT EXISTS `drafts` (`thread_id` INTEGER NOT NULL PRIMARY KEY, `body` TEXT NOT NULL, `date` INTEGER NOT NULL)")
}
}
}
}
}

View file

@ -59,6 +59,7 @@ import org.fossify.messages.helpers.NotificationHelper
import org.fossify.messages.helpers.generateRandomId
import org.fossify.messages.interfaces.AttachmentsDao
import org.fossify.messages.interfaces.ConversationsDao
import org.fossify.messages.interfaces.DraftsDao
import org.fossify.messages.interfaces.MessageAttachmentsDao
import org.fossify.messages.interfaces.MessagesDao
import org.fossify.messages.messaging.MessagingUtils
@ -66,6 +67,7 @@ import org.fossify.messages.messaging.MessagingUtils.Companion.ADDRESS_SEPARATOR
import org.fossify.messages.messaging.SmsSender
import org.fossify.messages.models.Attachment
import org.fossify.messages.models.Conversation
import org.fossify.messages.models.Draft
import org.fossify.messages.models.Message
import org.fossify.messages.models.MessageAttachment
import org.fossify.messages.models.NamePhoto
@ -85,6 +87,8 @@ val Context.messageAttachmentsDB: MessageAttachmentsDao get() = getMessagesDB().
val Context.messagesDB: MessagesDao get() = getMessagesDB().MessagesDao()
val Context.draftsDB: DraftsDao get() = getMessagesDB().DraftsDao()
val Context.notificationHelper get() = NotificationHelper(this)
val Context.messagingUtils get() = MessagingUtils(this)
@ -360,6 +364,12 @@ fun Context.getConversations(
date /= 1000
}
// drafts are stored locally they take priority over the original date
val draft = draftsDB.getDraftById(id)
if (draft != null) {
date = draft.date / 1000
}
val rawIds = cursor.getStringValue(Threads.RECIPIENT_IDS)
val recipientIds =
rawIds.split(" ").filter { it.areDigitsOnly() }.map { it.toInt() }.toMutableList()
@ -1045,40 +1055,21 @@ fun Context.removeDiacriticsIfNeeded(text: String): String {
return if (config.useSimpleCharacters) text.normalizeString() else text
}
fun Context.getSmsDraft(threadId: Long): String? {
val uri = Sms.Draft.CONTENT_URI
val projection = arrayOf(Sms.BODY)
val selection = "${Sms.THREAD_ID} = ?"
val selectionArgs = arrayOf(threadId.toString())
try {
val cursor = contentResolver.query(uri, projection, selection, selectionArgs, null)
cursor.use {
if (cursor?.moveToFirst() == true) {
return cursor.getString(0)
}
}
fun Context.getSmsDraft(threadId: Long): String {
val draft = try {
draftsDB.getDraftById(threadId)
} catch (e: Exception) {
null
}
return null
return draft?.body.orEmpty()
}
fun Context.getAllDrafts(): HashMap<Long, String> {
val drafts = HashMap<Long, String>()
val uri = Sms.Draft.CONTENT_URI
val projection = arrayOf(Sms.BODY, Sms.THREAD_ID)
try {
val cursor = contentResolver.query(uri, projection, null, null, null)
cursor?.use {
while (it.moveToNext()) {
val threadId = it.getLongValue(Sms.THREAD_ID)
val draft = it.getStringValue(Sms.BODY)
if (!draft.isNullOrEmpty()) {
drafts[threadId] = draft
}
}
draftsDB.getAll().forEach {
drafts[it.threadId] = it.body
}
} catch (e: Exception) {
e.printStackTrace()
@ -1088,17 +1079,25 @@ fun Context.getAllDrafts(): HashMap<Long, String> {
}
fun Context.saveSmsDraft(body: String, threadId: Long) {
val uri = Sms.Draft.CONTENT_URI
val contentValues = ContentValues().apply {
put(Sms.BODY, body)
put(Sms.DATE, System.currentTimeMillis().toString())
put(Sms.TYPE, Sms.MESSAGE_TYPE_DRAFT)
put(Sms.THREAD_ID, threadId)
}
val draft = Draft(
threadId = threadId,
body = body,
date = System.currentTimeMillis()
)
try {
contentResolver.insert(uri, contentValues)
draftsDB.insertOrUpdate(draft)
} catch (e: Exception) {
e.printStackTrace()
showErrorToast(e)
}
}
fun Context.deleteSmsDraft(threadId: Long) {
try {
draftsDB.delete(threadId)
} catch (e: Exception) {
e.printStackTrace()
showErrorToast(e)
}
}

View file

@ -0,0 +1,22 @@
package org.fossify.messages.interfaces
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import org.fossify.messages.models.Draft
@Dao
interface DraftsDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertOrUpdate(draft: Draft): Long
@Query("SELECT * FROM drafts")
fun getAll(): List<Draft>
@Query("SELECT * FROM drafts WHERE thread_id = :threadId")
fun getDraftById(threadId: Long): Draft?
@Query("DELETE FROM drafts WHERE thread_id = :threadId")
fun delete(threadId: Long): Int
}

View file

@ -0,0 +1,12 @@
package org.fossify.messages.models
import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity(tableName = "drafts")
data class Draft(
@ColumnInfo(name = "thread_id") @PrimaryKey val threadId: Long,
@ColumnInfo(name = "body") val body: String,
@ColumnInfo(name = "date") val date: Long,
)