Add a data class to encapsulate raw message data

ET-5543
ET-5545
This commit is contained in:
Stefanija Boshkovska
2026-01-02 08:24:38 +00:00
committed by Niccolò Forlini
parent ed006489f0
commit d1ebd90165
10 changed files with 51 additions and 20 deletions
@@ -64,11 +64,11 @@ class RawMessageDataViewModel @Inject constructor(
val event = when (rawMessageDataType) {
RawMessageDataType.Headers -> getRawMessageHeaders(primaryUserId.first(), messageId).fold(
ifLeft = { RawMessageDataState.Error(rawMessageDataType) },
ifRight = { RawMessageDataState.Data(rawMessageDataType, it, Effect.empty()) }
ifRight = { RawMessageDataState.Data(rawMessageDataType, it.value, Effect.empty()) }
)
RawMessageDataType.HTML -> getRawMessageBody(primaryUserId.first(), messageId).fold(
ifLeft = { RawMessageDataState.Error(rawMessageDataType) },
ifRight = { RawMessageDataState.Data(rawMessageDataType, it, Effect.empty()) }
ifRight = { RawMessageDataState.Data(rawMessageDataType, it.value, Effect.empty()) }
)
}
@@ -33,6 +33,7 @@ import ch.protonmail.android.maildetail.presentation.viewmodel.RawMessageDataVie
import ch.protonmail.android.maildetail.presentation.viewmodel.RawMessageDataViewModelTest.TestData.RAW_DATA_TYPE_HEADERS
import ch.protonmail.android.maildetail.presentation.viewmodel.RawMessageDataViewModelTest.TestData.RAW_DATA_TYPE_HTML
import ch.protonmail.android.mailmessage.domain.model.MessageId
import ch.protonmail.android.mailmessage.domain.model.RawMessageData
import ch.protonmail.android.mailmessage.domain.usecase.GetRawMessageBody
import ch.protonmail.android.mailmessage.domain.usecase.GetRawMessageHeaders
import ch.protonmail.android.mailsession.domain.usecase.ObservePrimaryUserId
@@ -83,7 +84,7 @@ class RawMessageDataViewModelTest {
val messageId = MessageId(MESSAGE_ID)
val rawHeaders = "raw headers"
every { savedStateHandle.get<String>(RawMessageDataScreen.RAW_DATA_TYPE_KEY) } returns RAW_DATA_TYPE_HEADERS
coEvery { getRawMessageHeaders(UserIdTestData.userId, messageId) } returns rawHeaders.right()
coEvery { getRawMessageHeaders(UserIdTestData.userId, messageId) } returns RawMessageData(rawHeaders).right()
// When
rawMessageDataViewModel.state.test {
@@ -120,7 +121,7 @@ class RawMessageDataViewModelTest {
val messageId = MessageId(MESSAGE_ID)
val rawBody = "raw body"
every { savedStateHandle.get<String>(RawMessageDataScreen.RAW_DATA_TYPE_KEY) } returns RAW_DATA_TYPE_HTML
coEvery { getRawMessageBody(UserIdTestData.userId, messageId) } returns rawBody.right()
coEvery { getRawMessageBody(UserIdTestData.userId, messageId) } returns RawMessageData(rawBody).right()
// When
rawMessageDataViewModel.state.test {
@@ -157,7 +158,7 @@ class RawMessageDataViewModelTest {
val messageId = MessageId(MESSAGE_ID)
val rawBody = "raw body"
every { savedStateHandle.get<String>(RawMessageDataScreen.RAW_DATA_TYPE_KEY) } returns RAW_DATA_TYPE_HTML
coEvery { getRawMessageBody(UserIdTestData.userId, messageId) } returns rawBody.right()
coEvery { getRawMessageBody(UserIdTestData.userId, messageId) } returns RawMessageData(rawBody).right()
coEvery { downloadRawMessageData("html", rawBody) } returns Unit.right()
rawMessageDataViewModel.state.test {
@@ -180,7 +181,7 @@ class RawMessageDataViewModelTest {
val messageId = MessageId(MESSAGE_ID)
val rawHeaders = "raw headers"
every { savedStateHandle.get<String>(RawMessageDataScreen.RAW_DATA_TYPE_KEY) } returns RAW_DATA_TYPE_HEADERS
coEvery { getRawMessageHeaders(UserIdTestData.userId, messageId) } returns rawHeaders.right()
coEvery { getRawMessageHeaders(UserIdTestData.userId, messageId) } returns RawMessageData(rawHeaders).right()
coEvery { downloadRawMessageData("headers", rawHeaders) } returns DataError.Local.Unknown.left()
rawMessageDataViewModel.state.test {
@@ -25,6 +25,7 @@ import ch.protonmail.android.mailcommon.domain.model.DataError
import ch.protonmail.android.mailmessage.domain.model.AttachmentDataError
import ch.protonmail.android.mailmessage.domain.model.MessageBody
import ch.protonmail.android.mailmessage.domain.model.MessageBodyTransformations
import ch.protonmail.android.mailmessage.domain.model.RawMessageData
import me.proton.core.domain.entity.UserId
import uniffi.proton_mail_uniffi.ImagePolicy
@@ -43,9 +44,9 @@ interface MessageBodyDataSource {
imagePolicy: ImagePolicy
): Either<AttachmentDataError, LocalAttachmentData>
suspend fun getRawHeaders(userId: UserId, messageId: LocalMessageId): Either<DataError, String>
suspend fun getRawHeaders(userId: UserId, messageId: LocalMessageId): Either<DataError, RawMessageData>
suspend fun getRawBody(userId: UserId, messageId: LocalMessageId): Either<DataError, String>
suspend fun getRawBody(userId: UserId, messageId: LocalMessageId): Either<DataError, RawMessageData>
suspend fun unsubscribeFromNewsletter(userId: UserId, messageId: LocalMessageId): Either<DataError, Unit>
}
@@ -35,6 +35,7 @@ import ch.protonmail.android.mailmessage.data.wrapper.DecryptedMessageWrapper
import ch.protonmail.android.mailmessage.domain.model.AttachmentDataError
import ch.protonmail.android.mailmessage.domain.model.MessageBody
import ch.protonmail.android.mailmessage.domain.model.MessageBodyTransformations
import ch.protonmail.android.mailmessage.domain.model.RawMessageData
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
import me.proton.core.domain.entity.UserId
@@ -87,19 +88,19 @@ class RustMessageBodyDataSource @Inject constructor(
}
}
override suspend fun getRawHeaders(userId: UserId, messageId: LocalMessageId): Either<DataError, String> =
override suspend fun getRawHeaders(userId: UserId, messageId: LocalMessageId): Either<DataError, RawMessageData> =
withContext(ioDispatcher) {
return@withContext getDecryptedMessageWrapper(userId, messageId)
.flatMap { decryptedMessage ->
decryptedMessage.rawHeaders().right()
RawMessageData(decryptedMessage.rawHeaders()).right()
}
}
override suspend fun getRawBody(userId: UserId, messageId: LocalMessageId): Either<DataError, String> =
override suspend fun getRawBody(userId: UserId, messageId: LocalMessageId): Either<DataError, RawMessageData> =
withContext(ioDispatcher) {
return@withContext getDecryptedMessageWrapper(userId, messageId)
.flatMap { decryptedMessage ->
decryptedMessage.rawBody().right()
RawMessageData(decryptedMessage.rawBody()).right()
}
}
@@ -27,6 +27,7 @@ import ch.protonmail.android.mailmessage.domain.model.MessageBodyImage
import ch.protonmail.android.mailmessage.domain.model.MessageBody
import ch.protonmail.android.mailmessage.domain.model.MessageBodyTransformations
import ch.protonmail.android.mailmessage.domain.model.MessageId
import ch.protonmail.android.mailmessage.domain.model.RawMessageData
import ch.protonmail.android.mailmessage.domain.repository.MessageBodyRepository
import me.proton.core.domain.entity.UserId
import timber.log.Timber
@@ -58,10 +59,10 @@ class RustMessageBodyRepository @Inject constructor(
}
}
override suspend fun getRawHeaders(userId: UserId, messageId: MessageId): Either<DataError, String> =
override suspend fun getRawHeaders(userId: UserId, messageId: MessageId): Either<DataError, RawMessageData> =
messageBodyDataSource.getRawHeaders(userId, messageId.toLocalMessageId())
override suspend fun getRawBody(userId: UserId, messageId: MessageId): Either<DataError, String> =
override suspend fun getRawBody(userId: UserId, messageId: MessageId): Either<DataError, RawMessageData> =
messageBodyDataSource.getRawBody(userId, messageId.toLocalMessageId())
@@ -31,6 +31,7 @@ import ch.protonmail.android.mailmessage.data.usecase.CreateRustMessageBodyAcces
import ch.protonmail.android.mailmessage.data.wrapper.DecryptedMessageWrapper
import ch.protonmail.android.mailmessage.domain.model.AttachmentDataError
import ch.protonmail.android.mailmessage.domain.model.MessageBodyTransformations
import ch.protonmail.android.mailmessage.domain.model.RawMessageData
import ch.protonmail.android.mailsession.domain.repository.UserSessionRepository
import ch.protonmail.android.mailsession.domain.wrapper.MailUserSessionWrapper
import ch.protonmail.android.testdata.message.rust.LocalMessageIdSample
@@ -241,7 +242,7 @@ class RustMessageBodyDataSourceTest {
// Then
coVerify { rustMailboxFactory.createAllMail(userId) }
coVerify { createRustMessageBodyAccessor(mailbox, messageId) }
assertEquals(result, rawHeaders.right())
assertEquals(result, RawMessageData(rawHeaders).right())
}
@Test
@@ -285,7 +286,7 @@ class RustMessageBodyDataSourceTest {
// Then
coVerify { rustMailboxFactory.createAllMail(userId) }
coVerify { createRustMessageBodyAccessor(mailbox, messageId) }
assertEquals(result, rawBody.right())
assertEquals(result, RawMessageData(rawBody).right())
}
@Test
@@ -0,0 +1,23 @@
/*
* Copyright (c) 2025 Proton Technologies AG
* This file is part of Proton Technologies AG and Proton Mail.
*
* Proton Mail is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Proton Mail is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Proton Mail. If not, see <https://www.gnu.org/licenses/>.
*/
package ch.protonmail.android.mailmessage.domain.model
data class RawMessageData(
val value: String
)
@@ -25,6 +25,7 @@ import ch.protonmail.android.mailmessage.domain.model.MessageBodyImage
import ch.protonmail.android.mailmessage.domain.model.MessageBody
import ch.protonmail.android.mailmessage.domain.model.MessageBodyTransformations
import ch.protonmail.android.mailmessage.domain.model.MessageId
import ch.protonmail.android.mailmessage.domain.model.RawMessageData
import me.proton.core.domain.entity.UserId
interface MessageBodyRepository {
@@ -42,9 +43,9 @@ interface MessageBodyRepository {
shouldLoadImagesSafely: Boolean
): Either<AttachmentDataError, MessageBodyImage>
suspend fun getRawHeaders(userId: UserId, messageId: MessageId): Either<DataError, String>
suspend fun getRawHeaders(userId: UserId, messageId: MessageId): Either<DataError, RawMessageData>
suspend fun getRawBody(userId: UserId, messageId: MessageId): Either<DataError, String>
suspend fun getRawBody(userId: UserId, messageId: MessageId): Either<DataError, RawMessageData>
suspend fun unsubscribeFromNewsletter(userId: UserId, messageId: MessageId): Either<DataError, Unit>
}
@@ -19,6 +19,7 @@
package ch.protonmail.android.mailmessage.domain.usecase
import arrow.core.right
import ch.protonmail.android.mailmessage.domain.model.RawMessageData
import ch.protonmail.android.mailmessage.domain.repository.MessageBodyRepository
import ch.protonmail.android.mailmessage.domain.sample.MessageIdSample
import ch.protonmail.android.testdata.user.UserIdTestData
@@ -40,7 +41,7 @@ class GetRawMessageBodyTest {
// Given
val userId = UserIdTestData.userId
val messageId = MessageIdSample.AugWeatherForecast
val rawBody = "raw body"
val rawBody = RawMessageData("raw body")
coEvery { messageBodyRepository.getRawBody(userId, messageId) } returns rawBody.right()
// When
@@ -19,6 +19,7 @@
package ch.protonmail.android.mailmessage.domain.usecase
import arrow.core.right
import ch.protonmail.android.mailmessage.domain.model.RawMessageData
import ch.protonmail.android.mailmessage.domain.repository.MessageBodyRepository
import ch.protonmail.android.mailmessage.domain.sample.MessageIdSample
import ch.protonmail.android.testdata.user.UserIdTestData
@@ -40,7 +41,7 @@ class GetRawMessageHeadersTest {
// Given
val userId = UserIdTestData.userId
val messageId = MessageIdSample.AugWeatherForecast
val rawHeaders = "raw headers"
val rawHeaders = RawMessageData("raw headers")
coEvery { messageBodyRepository.getRawHeaders(userId, messageId) } returns rawHeaders.right()
// When