From a7ddf1f4ea985c8a63af60a9375ef7f23aa06635 Mon Sep 17 00:00:00 2001 From: Maciej Surmacz Date: Wed, 5 Jul 2023 13:19:22 +0200 Subject: [PATCH] Fetches the remote draft right before sending The remote attachments are added to the local ones in order to avoid sending failures wherein the attachments on the BE are different than the ones on the client side. MAILAND-3070 --- .../repository/MessageDetailsRepository.kt | 11 +++++++++-- .../android/compose/send/SendMessageWorker.kt | 16 ++++++++++++++-- .../compose/send/SendMessageWorkerTest.kt | 4 +++- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/ch/protonmail/android/activities/messageDetails/repository/MessageDetailsRepository.kt b/app/src/main/java/ch/protonmail/android/activities/messageDetails/repository/MessageDetailsRepository.kt index 02d37dea6..94099ef3c 100644 --- a/app/src/main/java/ch/protonmail/android/activities/messageDetails/repository/MessageDetailsRepository.kt +++ b/app/src/main/java/ch/protonmail/android/activities/messageDetails/repository/MessageDetailsRepository.kt @@ -24,6 +24,8 @@ import androidx.annotation.WorkerThread import androidx.lifecycle.LiveData import androidx.room.Transaction import ch.protonmail.android.activities.messageDetails.IntentExtrasData +import ch.protonmail.android.api.ProtonMailApiManager +import ch.protonmail.android.api.interceptors.UserIdTag import ch.protonmail.android.api.models.DatabaseProvider import ch.protonmail.android.api.models.User import ch.protonmail.android.attachments.DownloadEmbeddedAttachmentsWorker @@ -71,7 +73,8 @@ class MessageDetailsRepository @Inject constructor( private val userManager: UserManager, private val databaseProvider: DatabaseProvider, private val attachmentsWorker: DownloadEmbeddedAttachmentsWorker.Enqueuer, - private val labelRepository: LabelRepository + private val labelRepository: LabelRepository, + private val protonMailApiManager: ProtonMailApiManager ) { private var requestedUserId: UserId? = null @@ -92,7 +95,8 @@ class MessageDetailsRepository @Inject constructor( attachmentsWorker: DownloadEmbeddedAttachmentsWorker.Enqueuer, labelRepository: LabelRepository, @Assisted userId: UserId, - ) : this(applicationContext, userManager, databaseProvider, attachmentsWorker, labelRepository) { + protonMailApiManager: ProtonMailApiManager + ) : this(applicationContext, userManager, databaseProvider, attachmentsWorker, labelRepository, protonMailApiManager) { requestedUserId = userId } @@ -346,6 +350,9 @@ class MessageDetailsRepository @Inject constructor( fun findAllPendingUploadsAsync(): LiveData> = pendingActionDao.findAllPendingUploadsAsync() + suspend fun getRemoteMessageDetails(messageId: String, userId: UserId): Message = + protonMailApiManager.fetchMessageDetails(messageId, UserIdTag(userId)).message + @AssistedInject.Factory interface AssistedFactory { diff --git a/app/src/main/java/ch/protonmail/android/compose/send/SendMessageWorker.kt b/app/src/main/java/ch/protonmail/android/compose/send/SendMessageWorker.kt index d4fe28806..d24724b9c 100644 --- a/app/src/main/java/ch/protonmail/android/compose/send/SendMessageWorker.kt +++ b/app/src/main/java/ch/protonmail/android/compose/send/SendMessageWorker.kt @@ -68,6 +68,7 @@ import ch.protonmail.android.data.local.model.Message import ch.protonmail.android.pendingaction.data.worker.CleanUpPendingSendWorker import ch.protonmail.android.usecase.compose.SaveDraft import ch.protonmail.android.usecase.compose.SaveDraftResult +import ch.protonmail.android.utils.TryWithRetry import ch.protonmail.android.utils.notifier.UserNotifier import ch.protonmail.android.worker.repository.WorkerRepository import dagger.assisted.Assisted @@ -115,7 +116,8 @@ class SendMessageWorker @AssistedInject constructor( private val userNotifier: UserNotifier, private val databaseProvider: DatabaseProvider, private val workerRepository: WorkerRepository, - private val getCleanUpPendingSendWorkName: CleanUpPendingSendWorker.ProvideUniqueName + private val getCleanUpPendingSendWorkName: CleanUpPendingSendWorker.ProvideUniqueName, + private val tryWithRetry: TryWithRetry ) : CoroutineWorker(context, params) { override suspend fun doWork(): Result { @@ -145,7 +147,7 @@ class SendMessageWorker @AssistedInject constructor( is SaveDraftResult.Success -> { val messageId = result.draftId Timber.i("Send Message Worker saved draft successfully for messageId $messageId") - val savedDraftMessage = messageDetailsRepository.findMessageById(messageId).first() + val savedDraftMessage = getRefreshedDraft(messageId, userId) ?: return retryOrFail(userId, SavedDraftMessageNotFound, message) Timber.d("Send Message Worker fetching send preferences for messageId $messageId") @@ -202,6 +204,16 @@ class SendMessageWorker @AssistedInject constructor( } } + private suspend fun getRefreshedDraft(messageId: String, userId: UserId): Message? { + val localDraft = messageDetailsRepository.findMessageById(messageId).first() ?: return null + tryWithRetry { + messageDetailsRepository.getRemoteMessageDetails(messageId, userId) + }.map { remoteDraft -> + localDraft.attachments = localDraft.attachments.plus(remoteDraft.attachments) + } + return localDraft + } + private suspend fun handleSendMessageResponse( userId: UserId, messageId: String, diff --git a/app/src/test/java/ch/protonmail/android/compose/send/SendMessageWorkerTest.kt b/app/src/test/java/ch/protonmail/android/compose/send/SendMessageWorkerTest.kt index 7c01a7044..89c16b089 100644 --- a/app/src/test/java/ch/protonmail/android/compose/send/SendMessageWorkerTest.kt +++ b/app/src/test/java/ch/protonmail/android/compose/send/SendMessageWorkerTest.kt @@ -57,6 +57,7 @@ import ch.protonmail.android.testdata.UserTestData.userId import ch.protonmail.android.testdata.WorkerTestData import ch.protonmail.android.usecase.compose.SaveDraft import ch.protonmail.android.usecase.compose.SaveDraftResult +import ch.protonmail.android.utils.TryWithRetry import ch.protonmail.android.utils.notifier.UserNotifier import ch.protonmail.android.worker.repository.WorkerRepository import io.mockk.Called @@ -142,7 +143,8 @@ class SendMessageWorkerTest : CoroutinesTest by CoroutinesTest() { userNotifier = userNotifier, databaseProvider = databaseProvider, workerRepository = workerRepository, - getCleanUpPendingSendWorkName = provideUniqueCleanUpName + getCleanUpPendingSendWorkName = provideUniqueCleanUpName, + tryWithRetry = TryWithRetry() ) @Test