diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/model/OutgoingMessageInfo.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/model/OutgoingMessageInfo.kt index 47e3545f1..6d3aa27d6 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/model/OutgoingMessageInfo.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/api/email/model/OutgoingMessageInfo.kt @@ -43,6 +43,7 @@ data class OutgoingMessageInfo( @Expose val signature: String? = null, @Expose val quotedTextForReply: String? = null, @Expose val draftId: String? = null, + @Expose val draftThreadId: Long? = null, ) : Parcelable { @IgnoredOnParcel @@ -91,6 +92,7 @@ data class OutgoingMessageInfo( if (signature != other.signature) return false if (quotedTextForReply != other.quotedTextForReply) return false if (draftId != other.draftId) return false + if (draftThreadId != other.draftThreadId) return false return true } @@ -113,6 +115,7 @@ data class OutgoingMessageInfo( result = 31 * result + (signature?.hashCode() ?: 0) result = 31 * result + (quotedTextForReply?.hashCode() ?: 0) result = 31 * result + (draftId?.hashCode() ?: 0) + result = 31 * result + (draftThreadId?.hashCode() ?: 0) return result } @@ -146,7 +149,8 @@ data class OutgoingMessageInfo( }, password = password, attachmentsDirectory = UUID.randomUUID().toString(), - draftId = draftId + draftId = draftId, + threadId = draftThreadId ) } } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/database/dao/MessageDao.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/database/dao/MessageDao.kt index 188f067fb..073cf0661 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/database/dao/MessageDao.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/database/dao/MessageDao.kt @@ -179,6 +179,11 @@ abstract class MessageDao : BaseDao { label: String = JavaEmailConstants.FOLDER_OUTBOX ): List + @Query("SELECT * FROM messages WHERE folder = :label") + abstract fun getAllOutboxMessagesFlow( + label: String = JavaEmailConstants.FOLDER_OUTBOX + ): Flow> + @Query( "SELECT * FROM messages " + "WHERE account = :account AND folder = :label AND state IN (:msgStates)" diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/CreateOutgoingMessageViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/CreateOutgoingMessageViewModel.kt index 5220db2e8..b3db572fe 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/CreateOutgoingMessageViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/CreateOutgoingMessageViewModel.kt @@ -66,17 +66,24 @@ class CreateOutgoingMessageViewModel( val activeAccount = getActiveAccountSuspend() ?: throw IllegalStateException("No active account") - val replyTo = outgoingMessageInfo.replyToMessageEntityId?.let { - roomDatabase.msgDao().getMsgById(it)?.replyToAddresses + val replyToMessageEntity = outgoingMessageInfo.replyToMessageEntityId?.let { + roomDatabase.msgDao().getMsgById(it) } - messageEntity = outgoingMessageInfo.toMessageEntity( + val template = outgoingMessageInfo.toMessageEntity( folder = JavaEmailConstants.FOLDER_OUTBOX, flags = Flags(Flags.Flag.SEEN), - replyTo = replyTo, + replyTo = replyToMessageEntity?.replyToAddresses, password = outgoingMessageInfo.password?.let { KeyStoreCryptoManager.encrypt(String(it)).toByteArray() } ) + + messageEntity = if (replyToMessageEntity != null) { + template.copy(threadId = replyToMessageEntity.threadId) + } else { + template + } + val messageId = roomDatabase.msgDao().insertSuspend(messageEntity) messageEntity = messageEntity.copy(id = messageId, uid = messageId) roomDatabase.msgDao().updateSuspend(messageEntity) diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/ThreadDetailsViewModel.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/ThreadDetailsViewModel.kt index 3a811e8bc..6306b1b46 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/ThreadDetailsViewModel.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/jetpack/viewmodel/ThreadDetailsViewModel.kt @@ -83,6 +83,8 @@ class ThreadDetailsViewModel( val sessionFromRecipientsStateFlow: StateFlow> = sessionFromRecipientsMutableStateFlow.asStateFlow() + val allOutboxMessagesFlow = roomDatabase.msgDao().getAllOutboxMessagesFlow() + @OptIn(ExperimentalCoroutinesApi::class) val localFolderFlow: StateFlow = threadMessageEntityFlow.mapLatest { threadMessageEntity -> diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/CreateMessageFragment.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/CreateMessageFragment.kt index 07bb99e3c..364c94d03 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/CreateMessageFragment.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/CreateMessageFragment.kt @@ -320,7 +320,10 @@ class CreateMessageFragment : BaseFragment(), MessageType.REPLY, MessageType.REPLY_ALL ) - } + }, + draftThreadId = if (args.incomingMessageInfo?.msgEntity?.isDraft == true) { + args.incomingMessageInfo?.msgEntity?.threadId + } else null ) ) } diff --git a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/ThreadDetailsFragment.kt b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/ThreadDetailsFragment.kt index 567b05f06..636de9d38 100644 --- a/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/ThreadDetailsFragment.kt +++ b/FlowCrypt/src/main/java/com/flowcrypt/email/ui/activity/fragment/ThreadDetailsFragment.kt @@ -491,6 +491,20 @@ class ThreadDetailsFragment : BaseFragment(), Prog } } + launchAndRepeatWithViewLifecycle { + threadDetailsViewModel.allOutboxMessagesFlow.collect { messageEntities -> + val threadId = + threadDetailsViewModel.threadMessageEntityFlow.value?.threadId ?: return@collect + val draftsToBeDeletedInLocalCache = messageEntities.filter { + it.threadId == threadId && !it.draftId.isNullOrEmpty() + } + + draftsToBeDeletedInLocalCache.forEach { + it.draftId?.let { draftId -> deleteDraftFromLocalCache(draftId) } + } + } + } + launchAndRepeatWithViewLifecycle { threadDetailsViewModel.messageActionsAvailabilityStateFlow.collect { activity?.invalidateOptionsMenu()