diff --git a/.gitignore b/.gitignore
index eae4d3884..a53c79951 100644
--- a/.gitignore
+++ b/.gitignore
@@ -56,6 +56,7 @@ app/src/beta/google-services.json
.idea/**/usage.statistics.xml
.idea/**/dictionaries/**
.idea/assetWizardSettings.xml
+.idea/deploymentTargetDropDown.xml
# Do not exclude project Dictionary
!.idea/**/dictionaries/project.xml
.idea/**/shelf
@@ -126,6 +127,3 @@ fabric.properties
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
-# # # # # # # # #
-# IDEA SETTINGS #
-# # # # # # # # #
diff --git a/.idea/deploymentTargetDropDown.xml b/.idea/deploymentTargetDropDown.xml
deleted file mode 100644
index 5c46a1db3..000000000
--- a/.idea/deploymentTargetDropDown.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/java/ch/protonmail/android/attachments/UploadAttachments.kt b/app/src/main/java/ch/protonmail/android/attachments/UploadAttachments.kt
index 9b58009f3..fcaca0cf9 100644
--- a/app/src/main/java/ch/protonmail/android/attachments/UploadAttachments.kt
+++ b/app/src/main/java/ch/protonmail/android/attachments/UploadAttachments.kt
@@ -55,7 +55,7 @@ internal const val KEY_INPUT_UPLOAD_ATTACHMENTS_IS_MESSAGE_SENDING = "keyUploadA
internal const val KEY_OUTPUT_RESULT_UPLOAD_ATTACHMENTS_ERROR = "keyUploadAttachmentResultError"
private const val UPLOAD_ATTACHMENTS_WORK_NAME_PREFIX = "uploadAttachmentUniqueWorkName"
-private const val UPLOAD_ATTACHMENTS_MAX_RETRIES = 3
+private const val UPLOAD_ATTACHMENTS_MAX_RETRIES = 1
class UploadAttachments @WorkerInject constructor(
@Assisted context: Context,
@@ -214,7 +214,7 @@ class UploadAttachments @WorkerInject constructor(
KEY_INPUT_UPLOAD_ATTACHMENTS_IS_MESSAGE_SENDING to isMessageSending
)
)
- .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 2 * TEN_SECONDS, TimeUnit.SECONDS)
+ .setBackoffCriteria(BackoffPolicy.LINEAR, TEN_SECONDS, TimeUnit.SECONDS)
.build()
workManager.enqueueUniqueWork(
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 a986ee0f2..eb6779ee6 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
@@ -69,7 +69,10 @@ import ch.protonmail.android.usecase.compose.SaveDraft
import ch.protonmail.android.usecase.compose.SaveDraftResult
import ch.protonmail.android.utils.notifier.UserNotifier
import kotlinx.coroutines.CancellationException
+import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.withContext
+import me.proton.core.util.kotlin.EMPTY_STRING
import me.proton.core.util.kotlin.deserialize
import me.proton.core.util.kotlin.serialize
import timber.log.Timber
@@ -89,7 +92,7 @@ internal const val KEY_INPUT_SEND_MESSAGE_SECURITY_OPTIONS_SERIALIZED = "keySend
internal const val KEY_OUTPUT_RESULT_SEND_MESSAGE_ERROR_ENUM = "keySendMessageErrorResult"
private const val INPUT_MESSAGE_DB_ID_NOT_FOUND = -1L
-private const val SEND_MESSAGE_MAX_RETRIES = 3
+private const val SEND_MESSAGE_MAX_RETRIES = 2
private const val NO_CONTACTS_AUTO_SAVE = 0
private const val SEND_MESSAGE_WORK_NAME_PREFIX = "sendMessageUniqueWorkName"
private const val NO_SUBJECT = ""
@@ -109,8 +112,12 @@ class SendMessageWorker @WorkerInject constructor(
override suspend fun doWork(): Result {
val messageDatabaseId = getInputMessageDatabaseId()
- Timber.i("Send Message Worker executing with messageDatabaseId $messageDatabaseId")
+ val inputMessageId = getInputMessageId()
+ Timber.i(
+ "Send Message Worker executing with messageDatabaseId $messageDatabaseId - messageID $inputMessageId"
+ )
val message = messageDetailsRepository.findMessageByMessageDbId(messageDatabaseId)
+ ?: messageDetailsRepository.findMessageById(inputMessageId)
if (message == null) {
showSendMessageError(NO_SUBJECT)
pendingActionsDao.deletePendingSendByDbId(messageDatabaseId)
@@ -122,8 +129,7 @@ class SendMessageWorker @WorkerInject constructor(
val previousSenderAddressId = requireNotNull(getInputPreviousSenderAddressId())
val username = requireNotNull(getInputCurrentUsername())
- val result = saveDraft(message, previousSenderAddressId)
- return when (result) {
+ return when (val result = saveDraft(message, previousSenderAddressId)) {
is SaveDraftResult.Success -> {
val messageId = result.draftId
Timber.i("Send Message Worker saved draft successfully for messageId $messageId")
@@ -148,8 +154,10 @@ class SendMessageWorker @WorkerInject constructor(
}
return try {
- val response = apiManager.sendMessage(messageId, requestBody, RetrofitTag(username))
- handleSendMessageResponse(messageId, response, savedDraftMessage)
+ withContext(NonCancellable) {
+ val response = apiManager.sendMessage(messageId, requestBody, RetrofitTag(username))
+ handleSendMessageResponse(messageId, response, savedDraftMessage)
+ }
} catch (exception: IOException) {
retryOrFail(ErrorPerformingApiRequest, savedDraftMessage, exception)
} catch (exception: Exception) {
@@ -323,6 +331,9 @@ class SendMessageWorker @WorkerInject constructor(
private fun getInputParentId() = inputData.getString(KEY_INPUT_SEND_MESSAGE_MSG_PARENT_ID)
+ private fun getInputMessageId() =
+ inputData.getString(KEY_INPUT_SEND_MESSAGE_MESSAGE_ID) ?: EMPTY_STRING
+
private fun getInputMessageDatabaseId() =
inputData.getLong(KEY_INPUT_SEND_MESSAGE_MSG_DB_ID, INPUT_MESSAGE_DB_ID_NOT_FOUND)
@@ -359,16 +370,15 @@ class SendMessageWorker @WorkerInject constructor(
KEY_INPUT_SEND_MESSAGE_SECURITY_OPTIONS_SERIALIZED to securityOptions.serialize()
)
)
- .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 2 * TEN_SECONDS, TimeUnit.SECONDS)
+ .setBackoffCriteria(BackoffPolicy.LINEAR, TEN_SECONDS, TimeUnit.SECONDS)
.build()
workManager.enqueueUniqueWork(
- "${SEND_MESSAGE_WORK_NAME_PREFIX}-${requireNotNull(message.messageId)}",
+ "$SEND_MESSAGE_WORK_NAME_PREFIX-${requireNotNull(message.messageId)}",
ExistingWorkPolicy.REPLACE,
sendMessageRequest
)
return workManager.getWorkInfoByIdLiveData(sendMessageRequest.id).asFlow()
}
}
-
}
diff --git a/app/src/main/java/ch/protonmail/android/worker/drafts/CreateDraftWorker.kt b/app/src/main/java/ch/protonmail/android/worker/drafts/CreateDraftWorker.kt
index bf224a8a2..d9dfd371a 100644
--- a/app/src/main/java/ch/protonmail/android/worker/drafts/CreateDraftWorker.kt
+++ b/app/src/main/java/ch/protonmail/android/worker/drafts/CreateDraftWorker.kt
@@ -77,7 +77,7 @@ internal const val KEY_OUTPUT_RESULT_SAVE_DRAFT_ERROR_ENUM = "keySaveDraftErrorR
internal const val KEY_OUTPUT_RESULT_SAVE_DRAFT_MESSAGE_ID = "keySaveDraftSuccessResultDbId"
private const val INPUT_MESSAGE_DB_ID_NOT_FOUND = -1L
-private const val SAVE_DRAFT_MAX_RETRIES = 3
+private const val SAVE_DRAFT_MAX_RETRIES = 1
class CreateDraftWorker @WorkerInject constructor(
@Assisted context: Context,
@@ -336,7 +336,7 @@ class CreateDraftWorker @WorkerInject constructor(
KEY_INPUT_SAVE_DRAFT_PREV_SENDER_ADDR_ID to previousSenderAddressId
)
)
- .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 2 * TEN_SECONDS, TimeUnit.SECONDS)
+ .setBackoffCriteria(BackoffPolicy.LINEAR, TEN_SECONDS, TimeUnit.SECONDS)
.build()
val uniqueWorkId = "$SAVE_DRAFT_UNIQUE_WORK_ID_PREFIX-${message.messageId}"
diff --git a/app/src/test/java/ch/protonmail/android/attachments/UploadAttachmentsTest.kt b/app/src/test/java/ch/protonmail/android/attachments/UploadAttachmentsTest.kt
index fe51f039d..862e0d1f4 100644
--- a/app/src/test/java/ch/protonmail/android/attachments/UploadAttachmentsTest.kt
+++ b/app/src/test/java/ch/protonmail/android/attachments/UploadAttachmentsTest.kt
@@ -139,8 +139,8 @@ class UploadAttachmentsTest : CoroutinesTest {
assertEquals(true, actualIsMessageSending)
assertArrayEquals(attachmentIds.toTypedArray(), actualAttachmentIds)
assertEquals(NetworkType.CONNECTED, constraints.requiredNetworkType)
- assertEquals(BackoffPolicy.EXPONENTIAL, workSpec.backoffPolicy)
- assertEquals(20000, workSpec.backoffDelayDuration)
+ assertEquals(BackoffPolicy.LINEAR, workSpec.backoffPolicy)
+ assertEquals(10000, workSpec.backoffDelayDuration)
verify { workManager.getWorkInfoByIdLiveData(any()) }
}
}
@@ -261,7 +261,7 @@ class UploadAttachmentsTest : CoroutinesTest {
coEvery { attachmentsRepository.upload(attachment2, crypto) } answers {
AttachmentsRepository.Result.Failure("Failed to upload attachment2")
}
- every { parameters.runAttemptCount } returns 2
+ every { parameters.runAttemptCount } returns 0
val result = uploadAttachments.doWork()
@@ -325,7 +325,7 @@ class UploadAttachmentsTest : CoroutinesTest {
coEvery { attachmentsRepository.uploadPublicKey(message, crypto) } answers {
AttachmentsRepository.Result.Failure("Failed to upload public key")
}
- every { parameters.runAttemptCount } returns 2
+ every { parameters.runAttemptCount } returns 0
val result = uploadAttachments.doWork()
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 d26d051c9..a62b181ff 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
@@ -180,8 +180,8 @@ class SendMessageWorkerTest : CoroutinesTest {
assertEquals(previousSenderAddressId, actualPreviousSenderAddress)
assertEquals(securityOptions, actualMessageSecurityOptions?.deserialize(MessageSecurityOptions.serializer()))
assertEquals(NetworkType.CONNECTED, constraints.requiredNetworkType)
- assertEquals(BackoffPolicy.EXPONENTIAL, workSpec.backoffPolicy)
- assertEquals(20000, workSpec.backoffDelayDuration)
+ assertEquals(BackoffPolicy.LINEAR, workSpec.backoffPolicy)
+ assertEquals(10000, workSpec.backoffDelayDuration)
verify { workManager.getWorkInfoByIdLiveData(any()) }
}
}
@@ -220,12 +220,33 @@ class SendMessageWorkerTest : CoroutinesTest {
coVerify { saveDraft(expectedParameters) }
}
+ @Test
+ fun workerTriesFindingTheMessageByMessageIdWhenMessageIsNotFoundByDatabaseId() = runBlockingTest {
+ val messageDbId = 23712L
+ val messageId = "8322224-1341"
+ val message = Message(messageId = messageId)
+ val createdDraftId = "createdDraftId"
+ givenFullValidInput(messageDbId, messageId)
+ coEvery { messageDetailsRepository.findMessageByMessageDbId(messageDbId) } returns null
+ coEvery { messageDetailsRepository.findMessageById(messageId) } returns message
+ coEvery { messageDetailsRepository.findMessageById(createdDraftId) } returns null
+ coEvery { saveDraft.invoke(any()) } returns SaveDraftResult.Success(createdDraftId)
+
+ worker.doWork()
+
+ verify { userNotifier wasNot Called }
+ val paramsSlot = slot()
+ coVerify { saveDraft.invoke(capture(paramsSlot)) }
+ assertEquals(message, paramsSlot.captured.message)
+ }
+
@Test
fun workerNotifiesUserAndFailsWhenMessageIsNotFoundInTheDatabase() = runBlockingTest {
val messageDbId = 2373L
val messageId = "8322223"
givenFullValidInput(messageDbId, messageId)
coEvery { messageDetailsRepository.findMessageByMessageDbId(messageDbId) } returns null
+ coEvery { messageDetailsRepository.findMessageById(messageId) } returns null
every { context.getString(R.string.message_drafted) } returns "error message 9214"
val result = worker.doWork()
@@ -685,7 +706,7 @@ class SendMessageWorkerTest : CoroutinesTest {
coEvery { saveDraft(any()) } returns SaveDraftResult.Success(savedDraftMessageId)
every { sendPreferencesFactory.fetch(any()) } returns mapOf()
every { packageFactory.generatePackages(any(), any(), any(), any()) } throws exception
- every { parameters.runAttemptCount } returns 2
+ every { parameters.runAttemptCount } returns 1
mockkStatic(Timber::class)
val result = worker.doWork()
@@ -1027,3 +1048,4 @@ class SendMessageWorkerTest : CoroutinesTest {
}
}
}
+
diff --git a/app/src/test/java/ch/protonmail/android/worker/CreateDraftWorkerTest.kt b/app/src/test/java/ch/protonmail/android/worker/CreateDraftWorkerTest.kt
index 80775b20f..5989b084e 100644
--- a/app/src/test/java/ch/protonmail/android/worker/CreateDraftWorkerTest.kt
+++ b/app/src/test/java/ch/protonmail/android/worker/CreateDraftWorkerTest.kt
@@ -174,8 +174,8 @@ class CreateDraftWorkerTest : CoroutinesTest {
assertEquals(messageActionType.messageActionTypeValue, actualMessageActionType)
assertEquals(previousSenderAddressId, actualPreviousSenderAddress)
assertEquals(NetworkType.CONNECTED, constraints.requiredNetworkType)
- assertEquals(BackoffPolicy.EXPONENTIAL, workSpec.backoffPolicy)
- assertEquals(20000, workSpec.backoffDelayDuration)
+ assertEquals(BackoffPolicy.LINEAR, workSpec.backoffPolicy)
+ assertEquals(10000, workSpec.backoffDelayDuration)
verify { workManager.getWorkInfoByIdLiveData(any()) }
}
}
@@ -954,7 +954,7 @@ class CreateDraftWorkerTest : CoroutinesTest {
every { this@mockk.message.subject } returns "Subject001"
}
coEvery { apiManager.createDraft(any()) } throws IOException(errorMessage)
- every { parameters.runAttemptCount } returns 2
+ every { parameters.runAttemptCount } returns 0
val attachment = Attachment("attachment", keyPackets = "OriginalAttachmentPackets", inline = true)
val parentMessage = mockk {
coEvery { this@mockk.Attachments } returns listOf(attachment)