Skip to content

Commit 8d09a68

Browse files
committed
Fix AI messages not being taken into account when saving a draft in some cases
The bug would happen in this situation: * When generating a message with AI, as AiPropositionFragment is navigated to, NewMessageFragment would export his body in the `subjectAndBodyChannel`. * When inserting the AI proposition, we would navigate back to NewMessageFragment. * When we want to now save or send the draft we will receive values through the channel but the channel's value was never consumed and the previous body is still there even though we want to wait for the new body. This commit introduces a `channelExpirationIdTarget` that will let us know if a message is too old and needs to be discarded while we wait for the correct message to get through the channel
1 parent d38278b commit 8d09a68

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageFragment.kt

+5
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,11 @@ class NewMessageFragment : Fragment() {
582582
}
583583
}
584584

585+
override fun onStart() {
586+
super.onStart()
587+
newMessageViewModel.discardOldBodyAndSubjectChannelMessages()
588+
}
589+
585590
override fun onStop() {
586591
/**
587592
* When the Activity is being stopped, we save the Draft.

app/src/main/java/com/infomaniak/mail/ui/newMessage/NewMessageViewModel.kt

+23-4
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,13 @@ class NewMessageViewModel @Inject constructor(
116116

117117
val editorBodyLoader = SingleLiveEvent<BodyContentPayload>()
118118

119-
private val _subjectAndBodyChannel: Channel<Pair<String, String>> = Channel(capacity = CONFLATED)
120-
private val subjectAndBodyChannel: ReceiveChannel<Pair<String, String>> = _subjectAndBodyChannel
119+
// 1. Navigating to AiPropositionFragment causes NewMessageFragment to export its body to `subjectAndBodyChannel`.
120+
// 2. Inserting the AI proposition navigates back to NewMessageFragment.
121+
// 3. When saving or sending the draft now, the channel still holds the previous body as it wasn't consumed.
122+
// channelExpirationIdTarget lets us identify and discard outdated messages, ensuring the correct message is processed.
123+
private var channelExpirationIdTarget = 0
124+
private val _subjectAndBodyChannel: Channel<Triple<String, String, Int>> = Channel(capacity = CONFLATED)
125+
private val subjectAndBodyChannel: ReceiveChannel<Triple<String, String, Int>> = _subjectAndBodyChannel
121126
private var subjectAndBodyJob: Job? = null
122127

123128
var isAutoCompletionOpened = false
@@ -754,14 +759,28 @@ class NewMessageViewModel @Inject constructor(
754759

755760
fun saveBodyAndSubject(subject: String, html: String) {
756761
globalCoroutineScope.launch {
757-
_subjectAndBodyChannel.send(subject to html)
762+
_subjectAndBodyChannel.send(Triple(subject, html, channelExpirationIdTarget))
758763
}
759764
}
760765

766+
fun discardOldBodyAndSubjectChannelMessages() {
767+
channelExpirationIdTarget++
768+
}
769+
761770
fun waitForBodyAndSubjectToExecuteDraftAction(draftSaveConfiguration: DraftSaveConfiguration) {
762771
subjectAndBodyJob?.cancel()
763772
subjectAndBodyJob = globalCoroutineScope.launch {
764-
val (subject, body) = subjectAndBodyChannel.receive()
773+
val subject: String
774+
val body: String
775+
while (true) {
776+
val (receivedSubject, receivedBody, expirationId) = subjectAndBodyChannel.receive()
777+
if (expirationId == channelExpirationIdTarget) {
778+
subject = receivedSubject
779+
body = receivedBody
780+
break
781+
}
782+
}
783+
765784
draftSaveConfiguration.addSubjectAndBody(subject, body)
766785
executeDraftAction(draftSaveConfiguration)
767786
}

0 commit comments

Comments
 (0)