diff --git a/mail-detail/presentation/src/main/kotlin/ch/protonmail/android/maildetail/presentation/viewmodel/RawMessageDataViewModel.kt b/mail-detail/presentation/src/main/kotlin/ch/protonmail/android/maildetail/presentation/viewmodel/RawMessageDataViewModel.kt index 0ebed14826..33980fa4ef 100644 --- a/mail-detail/presentation/src/main/kotlin/ch/protonmail/android/maildetail/presentation/viewmodel/RawMessageDataViewModel.kt +++ b/mail-detail/presentation/src/main/kotlin/ch/protonmail/android/maildetail/presentation/viewmodel/RawMessageDataViewModel.kt @@ -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()) } ) } diff --git a/mail-detail/presentation/src/test/kotlin/ch/protonmail/android/maildetail/presentation/viewmodel/RawMessageDataViewModelTest.kt b/mail-detail/presentation/src/test/kotlin/ch/protonmail/android/maildetail/presentation/viewmodel/RawMessageDataViewModelTest.kt index 290524ed12..ab39775963 100644 --- a/mail-detail/presentation/src/test/kotlin/ch/protonmail/android/maildetail/presentation/viewmodel/RawMessageDataViewModelTest.kt +++ b/mail-detail/presentation/src/test/kotlin/ch/protonmail/android/maildetail/presentation/viewmodel/RawMessageDataViewModelTest.kt @@ -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(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(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(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(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 { diff --git a/mail-message/data/src/main/kotlin/ch/protonmail/android/mailmessage/data/local/MessageBodyDataSource.kt b/mail-message/data/src/main/kotlin/ch/protonmail/android/mailmessage/data/local/MessageBodyDataSource.kt index 3c3639bcfa..e87ed945d6 100644 --- a/mail-message/data/src/main/kotlin/ch/protonmail/android/mailmessage/data/local/MessageBodyDataSource.kt +++ b/mail-message/data/src/main/kotlin/ch/protonmail/android/mailmessage/data/local/MessageBodyDataSource.kt @@ -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 - suspend fun getRawHeaders(userId: UserId, messageId: LocalMessageId): Either + suspend fun getRawHeaders(userId: UserId, messageId: LocalMessageId): Either - suspend fun getRawBody(userId: UserId, messageId: LocalMessageId): Either + suspend fun getRawBody(userId: UserId, messageId: LocalMessageId): Either suspend fun unsubscribeFromNewsletter(userId: UserId, messageId: LocalMessageId): Either } diff --git a/mail-message/data/src/main/kotlin/ch/protonmail/android/mailmessage/data/local/RustMessageBodyDataSource.kt b/mail-message/data/src/main/kotlin/ch/protonmail/android/mailmessage/data/local/RustMessageBodyDataSource.kt index 29f2871e85..c7a74e818f 100644 --- a/mail-message/data/src/main/kotlin/ch/protonmail/android/mailmessage/data/local/RustMessageBodyDataSource.kt +++ b/mail-message/data/src/main/kotlin/ch/protonmail/android/mailmessage/data/local/RustMessageBodyDataSource.kt @@ -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 = + override suspend fun getRawHeaders(userId: UserId, messageId: LocalMessageId): Either = 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 = + override suspend fun getRawBody(userId: UserId, messageId: LocalMessageId): Either = withContext(ioDispatcher) { return@withContext getDecryptedMessageWrapper(userId, messageId) .flatMap { decryptedMessage -> - decryptedMessage.rawBody().right() + RawMessageData(decryptedMessage.rawBody()).right() } } diff --git a/mail-message/data/src/main/kotlin/ch/protonmail/android/mailmessage/data/repository/RustMessageBodyRepository.kt b/mail-message/data/src/main/kotlin/ch/protonmail/android/mailmessage/data/repository/RustMessageBodyRepository.kt index 937f34b598..54dfb625eb 100644 --- a/mail-message/data/src/main/kotlin/ch/protonmail/android/mailmessage/data/repository/RustMessageBodyRepository.kt +++ b/mail-message/data/src/main/kotlin/ch/protonmail/android/mailmessage/data/repository/RustMessageBodyRepository.kt @@ -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 = + override suspend fun getRawHeaders(userId: UserId, messageId: MessageId): Either = messageBodyDataSource.getRawHeaders(userId, messageId.toLocalMessageId()) - override suspend fun getRawBody(userId: UserId, messageId: MessageId): Either = + override suspend fun getRawBody(userId: UserId, messageId: MessageId): Either = messageBodyDataSource.getRawBody(userId, messageId.toLocalMessageId()) diff --git a/mail-message/data/src/test/kotlin/ch/protonmail/android/mailmessage/data/local/RustMessageBodyDataSourceTest.kt b/mail-message/data/src/test/kotlin/ch/protonmail/android/mailmessage/data/local/RustMessageBodyDataSourceTest.kt index 03427a61bd..b388717a54 100644 --- a/mail-message/data/src/test/kotlin/ch/protonmail/android/mailmessage/data/local/RustMessageBodyDataSourceTest.kt +++ b/mail-message/data/src/test/kotlin/ch/protonmail/android/mailmessage/data/local/RustMessageBodyDataSourceTest.kt @@ -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 diff --git a/mail-message/domain/src/main/kotlin/ch/protonmail/android/mailmessage/domain/model/RawMessageData.kt b/mail-message/domain/src/main/kotlin/ch/protonmail/android/mailmessage/domain/model/RawMessageData.kt new file mode 100644 index 0000000000..853fefc043 --- /dev/null +++ b/mail-message/domain/src/main/kotlin/ch/protonmail/android/mailmessage/domain/model/RawMessageData.kt @@ -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 . + */ + +package ch.protonmail.android.mailmessage.domain.model + +data class RawMessageData( + val value: String +) diff --git a/mail-message/domain/src/main/kotlin/ch/protonmail/android/mailmessage/domain/repository/MessageBodyRepository.kt b/mail-message/domain/src/main/kotlin/ch/protonmail/android/mailmessage/domain/repository/MessageBodyRepository.kt index da9f62e8ff..e212e8a6cc 100644 --- a/mail-message/domain/src/main/kotlin/ch/protonmail/android/mailmessage/domain/repository/MessageBodyRepository.kt +++ b/mail-message/domain/src/main/kotlin/ch/protonmail/android/mailmessage/domain/repository/MessageBodyRepository.kt @@ -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 - suspend fun getRawHeaders(userId: UserId, messageId: MessageId): Either + suspend fun getRawHeaders(userId: UserId, messageId: MessageId): Either - suspend fun getRawBody(userId: UserId, messageId: MessageId): Either + suspend fun getRawBody(userId: UserId, messageId: MessageId): Either suspend fun unsubscribeFromNewsletter(userId: UserId, messageId: MessageId): Either } diff --git a/mail-message/domain/src/test/kotlin/ch/protonmail/android/mailmessage/domain/usecase/GetRawMessageBodyTest.kt b/mail-message/domain/src/test/kotlin/ch/protonmail/android/mailmessage/domain/usecase/GetRawMessageBodyTest.kt index 438108544e..b88ca0c892 100644 --- a/mail-message/domain/src/test/kotlin/ch/protonmail/android/mailmessage/domain/usecase/GetRawMessageBodyTest.kt +++ b/mail-message/domain/src/test/kotlin/ch/protonmail/android/mailmessage/domain/usecase/GetRawMessageBodyTest.kt @@ -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 diff --git a/mail-message/domain/src/test/kotlin/ch/protonmail/android/mailmessage/domain/usecase/GetRawMessageHeadersTest.kt b/mail-message/domain/src/test/kotlin/ch/protonmail/android/mailmessage/domain/usecase/GetRawMessageHeadersTest.kt index d6b23c959b..2204624576 100644 --- a/mail-message/domain/src/test/kotlin/ch/protonmail/android/mailmessage/domain/usecase/GetRawMessageHeadersTest.kt +++ b/mail-message/domain/src/test/kotlin/ch/protonmail/android/mailmessage/domain/usecase/GetRawMessageHeadersTest.kt @@ -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