MailboxViewModel returns conversations as mailboxItems
when conversation view is enabled. Right now, the conversations returned are Fake (from FakeConversationsRepository) as the repository is still being implemented. Moreover, some of the fields of a MailboxUiItem are not being correctly mapped from conversations objects yet. MAILAND-1644
This commit is contained in:
parent
5a4ee61909
commit
4007127026
|
@ -48,9 +48,9 @@ import ch.protonmail.android.api.segments.event.FetchUpdatesJob;
|
|||
import ch.protonmail.android.core.ProtonMailApplication;
|
||||
import ch.protonmail.android.events.NoResultsEvent;
|
||||
import ch.protonmail.android.jobs.SearchMessagesJob;
|
||||
import ch.protonmail.android.mailbox.presentation.MailboxUiItem;
|
||||
import ch.protonmail.android.mailbox.presentation.MailboxViewModel;
|
||||
import ch.protonmail.android.mailbox.presentation.MailboxViewModelFactory;
|
||||
import ch.protonmail.android.mailbox.presentation.model.MailboxUiItem;
|
||||
import ch.protonmail.android.utils.AppUtil;
|
||||
import dagger.hilt.android.AndroidEntryPoint;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import ch.protonmail.android.data.local.model.Label
|
|||
import ch.protonmail.android.data.local.model.Message
|
||||
import ch.protonmail.android.data.local.model.PendingSend
|
||||
import ch.protonmail.android.data.local.model.PendingUpload
|
||||
import ch.protonmail.android.mailbox.presentation.MailboxUiItem
|
||||
import ch.protonmail.android.mailbox.presentation.model.MailboxUiItem
|
||||
import ch.protonmail.android.utils.ui.selection.SelectionModeEnum
|
||||
import kotlinx.android.synthetic.main.layout_sender_initial.view.*
|
||||
import kotlinx.android.synthetic.main.list_item_mailbox.view.*
|
||||
|
@ -179,7 +179,7 @@ class MessagesRecyclerViewAdapter(
|
|||
}
|
||||
|
||||
this.view.setOnClickListener {
|
||||
if (selectedMessageIds.isNotEmpty()) {
|
||||
if (selectedMailboxItemsIds.isNotEmpty()) {
|
||||
val messageId = it.tag as String
|
||||
selectOrDeselectMessage(messageId, position)
|
||||
} else {
|
||||
|
@ -187,7 +187,7 @@ class MessagesRecyclerViewAdapter(
|
|||
}
|
||||
}
|
||||
this.view.setOnLongClickListener {
|
||||
if (selectedMessageIds.isEmpty()) {
|
||||
if (selectedMailboxItemsIds.isEmpty()) {
|
||||
val messageId = it.tag as String
|
||||
return@setOnLongClickListener selectOrDeselectMessage(messageId, position)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
package ch.protonmail.android.api.models;
|
||||
|
||||
import ch.protonmail.android.data.local.model.Message;
|
||||
import ch.protonmail.android.mailbox.presentation.MailboxUiItem;
|
||||
import ch.protonmail.android.mailbox.presentation.model.MailboxUiItem;
|
||||
|
||||
public class SimpleMessage {
|
||||
|
||||
|
|
|
@ -33,6 +33,8 @@ import ch.protonmail.android.contacts.groups.edit.chooser.AddressChooserViewMode
|
|||
import ch.protonmail.android.core.ProtonMailApplication
|
||||
import ch.protonmail.android.core.UserManager
|
||||
import ch.protonmail.android.data.ContactsRepository
|
||||
import ch.protonmail.android.mailbox.domain.GetConversations
|
||||
import ch.protonmail.android.mailbox.presentation.ConversationModeEnabled
|
||||
import ch.protonmail.android.mailbox.presentation.MailboxViewModel
|
||||
import ch.protonmail.android.settings.pin.viewmodel.PinFragmentViewModelFactory
|
||||
import ch.protonmail.android.usecase.VerifyConnection
|
||||
|
@ -98,7 +100,9 @@ internal class ViewModelModule {
|
|||
contactsRepository: ContactsRepository,
|
||||
verifyConnection: VerifyConnection,
|
||||
networkConfigurator: NetworkConfigurator,
|
||||
messageServiceScheduler: MessagesService.Scheduler
|
||||
messageServiceScheduler: MessagesService.Scheduler,
|
||||
conversationModeEnabled: ConversationModeEnabled,
|
||||
getConversations: GetConversations
|
||||
) = MailboxViewModel(
|
||||
messageDetailsRepository,
|
||||
userManager,
|
||||
|
@ -108,6 +112,8 @@ internal class ViewModelModule {
|
|||
contactsRepository,
|
||||
verifyConnection,
|
||||
networkConfigurator,
|
||||
messageServiceScheduler
|
||||
messageServiceScheduler,
|
||||
conversationModeEnabled,
|
||||
getConversations
|
||||
)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2020 Proton Technologies AG
|
||||
*
|
||||
* This file is part of ProtonMail.
|
||||
*
|
||||
* ProtonMail 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.
|
||||
*
|
||||
* ProtonMail 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 ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.mailbox.data
|
||||
|
||||
import ch.protonmail.android.mailbox.domain.Conversation
|
||||
import ch.protonmail.android.mailbox.domain.ConversationsRepository
|
||||
import ch.protonmail.android.mailbox.domain.model.Correspondent
|
||||
import ch.protonmail.android.mailbox.domain.model.GetConversationsParameters
|
||||
import ch.protonmail.android.mailbox.domain.model.MessageEntity
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import me.proton.core.domain.arch.DataResult
|
||||
import me.proton.core.domain.arch.ResponseSource
|
||||
import javax.inject.Inject
|
||||
|
||||
class FakeConversationsRepository @Inject constructor() : ConversationsRepository {
|
||||
|
||||
override fun getConversations(params: GetConversationsParameters): Flow<DataResult<List<Conversation>>> {
|
||||
val sender = Correspondent("senderName", "sender@protonmail.com")
|
||||
val recipients = listOf(
|
||||
Correspondent("recipient", "recipient@protonmail.com"),
|
||||
Correspondent("recipient1", "recipient1@pm.ch")
|
||||
)
|
||||
val correspondent = Correspondent("conversation sender", "bomber@pm.me")
|
||||
return flowOf(
|
||||
DataResult.Success(
|
||||
ResponseSource.Local,
|
||||
listOf(
|
||||
Conversation(
|
||||
"conversationId",
|
||||
"A Fake conversation for you",
|
||||
listOf(correspondent),
|
||||
recipients,
|
||||
4,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
"senderAddressId",
|
||||
listOf(),
|
||||
listOf(
|
||||
MessageEntity(
|
||||
"messageId",
|
||||
"conversationId",
|
||||
"subject",
|
||||
true,
|
||||
sender,
|
||||
recipients,
|
||||
123421L,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
""
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getConversation(conversationId: String, messageId: String): Conversation? {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
}
|
|
@ -138,6 +138,7 @@ import ch.protonmail.android.jobs.PostTrashJobV2
|
|||
import ch.protonmail.android.jobs.PostUnreadJob
|
||||
import ch.protonmail.android.jobs.PostUnstarJob
|
||||
import ch.protonmail.android.mailbox.presentation.MailboxViewModel.MaxLabelsReached
|
||||
import ch.protonmail.android.mailbox.presentation.model.MailboxUiItem
|
||||
import ch.protonmail.android.prefs.SecureSharedPreferences
|
||||
import ch.protonmail.android.servers.notification.EXTRA_MAILBOX_LOCATION
|
||||
import ch.protonmail.android.settings.pin.EXTRA_TOTAL_COUNT_EVENT
|
||||
|
|
|
@ -20,6 +20,8 @@ package ch.protonmail.android.mailbox.presentation
|
|||
|
||||
import androidx.lifecycle.LiveData
|
||||
import androidx.lifecycle.MutableLiveData
|
||||
import androidx.lifecycle.asLiveData
|
||||
import androidx.lifecycle.map
|
||||
import androidx.lifecycle.switchMap
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import ch.protonmail.android.activities.messageDetails.repository.MessageDetailsRepository
|
||||
|
@ -37,6 +39,10 @@ import ch.protonmail.android.domain.entity.Id
|
|||
import ch.protonmail.android.jobs.ApplyLabelJob
|
||||
import ch.protonmail.android.jobs.FetchByLocationJob
|
||||
import ch.protonmail.android.jobs.RemoveLabelJob
|
||||
import ch.protonmail.android.mailbox.domain.GetConversations
|
||||
import ch.protonmail.android.mailbox.domain.GetConversationsResult
|
||||
import ch.protonmail.android.mailbox.presentation.model.MailboxUiItem
|
||||
import ch.protonmail.android.mailbox.presentation.model.MessageData
|
||||
import ch.protonmail.android.usecase.VerifyConnection
|
||||
import ch.protonmail.android.usecase.delete.DeleteMessage
|
||||
import ch.protonmail.android.utils.Event
|
||||
|
@ -67,7 +73,9 @@ class MailboxViewModel @Inject constructor(
|
|||
private val contactsRepository: ContactsRepository,
|
||||
verifyConnection: VerifyConnection,
|
||||
networkConfigurator: NetworkConfigurator,
|
||||
private val messageServiceScheduler: MessagesService.Scheduler
|
||||
private val messageServiceScheduler: MessagesService.Scheduler,
|
||||
private val conversationModeEnabled: ConversationModeEnabled,
|
||||
private val getConversations: GetConversations
|
||||
) : ConnectivityBaseViewModel(verifyConnection, networkConfigurator) {
|
||||
|
||||
var pendingSendsLiveData = messageDetailsRepository.findAllPendingSendsAsync()
|
||||
|
@ -199,6 +207,28 @@ class MailboxViewModel @Inject constructor(
|
|||
uuid: String,
|
||||
refreshMessages: Boolean,
|
||||
earliestTime: Long? = null
|
||||
): LiveData<List<MailboxUiItem>> {
|
||||
if (conversationModeEnabled(location)) {
|
||||
return getConversationsAsMailboxItems(location)
|
||||
}
|
||||
|
||||
return getMessagesAsMailboxItems(
|
||||
earliestTime,
|
||||
location,
|
||||
labelId,
|
||||
includeLabels,
|
||||
uuid,
|
||||
refreshMessages
|
||||
)
|
||||
}
|
||||
|
||||
private fun getMessagesAsMailboxItems(
|
||||
earliestTime: Long?,
|
||||
location: Constants.MessageLocationType,
|
||||
labelId: String?,
|
||||
includeLabels: Boolean,
|
||||
uuid: String,
|
||||
refreshMessages: Boolean
|
||||
): LiveData<List<MailboxUiItem>> {
|
||||
// When earliest time is valid the request is about paginated messages (page > 1)
|
||||
if (earliestTime != null) {
|
||||
|
@ -235,6 +265,33 @@ class MailboxViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun getConversationsAsMailboxItems(
|
||||
location: Constants.MessageLocationType
|
||||
): LiveData<List<MailboxUiItem>> {
|
||||
return getConversations(location).asLiveData().map { result ->
|
||||
if (result is GetConversationsResult.Success) {
|
||||
return@map result.conversations.map { conversation ->
|
||||
MailboxUiItem(
|
||||
conversation.id,
|
||||
conversation.senders.first().name,
|
||||
conversation.subject,
|
||||
0L,
|
||||
conversation.attachmentsCount > 0,
|
||||
false,
|
||||
conversation.unreadCount == 0,
|
||||
conversation.expirationTime,
|
||||
conversation.messagesCount,
|
||||
null,
|
||||
false,
|
||||
conversation.labelIds,
|
||||
conversation.receivers.joinToString { it.name }
|
||||
)
|
||||
}
|
||||
}
|
||||
return@map listOf()
|
||||
}
|
||||
}
|
||||
|
||||
fun messagesToMailboxItems(messages: List<Message>): LiveData<List<MailboxUiItem>> {
|
||||
val mailboxItems = MutableLiveData<List<MailboxUiItem>>()
|
||||
viewModelScope.launch(dispatchers.Io) {
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
* along with ProtonMail. If not, see https://www.gnu.org/licenses/.
|
||||
*/
|
||||
|
||||
package ch.protonmail.android.mailbox.presentation
|
||||
package ch.protonmail.android.mailbox.presentation.model
|
||||
|
||||
data class MailboxUiItem(
|
||||
val itemId: String,
|
||||
|
|
|
@ -30,7 +30,7 @@ import androidx.recyclerview.widget.RecyclerView
|
|||
import ch.protonmail.android.R
|
||||
import ch.protonmail.android.core.Constants
|
||||
import ch.protonmail.android.data.local.model.Label
|
||||
import ch.protonmail.android.mailbox.presentation.MailboxUiItem
|
||||
import ch.protonmail.android.mailbox.presentation.model.MailboxUiItem
|
||||
import ch.protonmail.android.utils.DateUtil
|
||||
import ch.protonmail.android.utils.UiUtil
|
||||
import kotlinx.android.synthetic.main.list_item_mailbox.view.*
|
||||
|
|
|
@ -34,9 +34,15 @@ import ch.protonmail.android.data.local.model.MessageSender
|
|||
import ch.protonmail.android.di.JobEntryPoint
|
||||
import ch.protonmail.android.domain.entity.Id
|
||||
import ch.protonmail.android.jobs.FetchByLocationJob
|
||||
import ch.protonmail.android.mailbox.presentation.MailboxUiItem
|
||||
import ch.protonmail.android.mailbox.domain.Conversation
|
||||
import ch.protonmail.android.mailbox.domain.GetConversations
|
||||
import ch.protonmail.android.mailbox.domain.GetConversationsResult
|
||||
import ch.protonmail.android.mailbox.domain.model.Correspondent
|
||||
import ch.protonmail.android.mailbox.domain.model.MessageEntity
|
||||
import ch.protonmail.android.mailbox.presentation.ConversationModeEnabled
|
||||
import ch.protonmail.android.mailbox.presentation.MailboxViewModel
|
||||
import ch.protonmail.android.mailbox.presentation.MessageData
|
||||
import ch.protonmail.android.mailbox.presentation.model.MailboxUiItem
|
||||
import ch.protonmail.android.mailbox.presentation.model.MessageData
|
||||
import ch.protonmail.android.testAndroid.lifecycle.testObserver
|
||||
import ch.protonmail.android.usecase.VerifyConnection
|
||||
import ch.protonmail.android.usecase.delete.DeleteMessage
|
||||
|
@ -44,9 +50,11 @@ import ch.protonmail.android.utils.MessageUtils
|
|||
import ch.protonmail.android.utils.MessageUtils.toContactsAndGroupsString
|
||||
import com.birbit.android.jobqueue.JobManager
|
||||
import dagger.hilt.EntryPoints
|
||||
import io.mockk.Called
|
||||
import io.mockk.MockKAnnotations
|
||||
import io.mockk.coEvery
|
||||
import io.mockk.coVerify
|
||||
import io.mockk.coVerifySequence
|
||||
import io.mockk.every
|
||||
import io.mockk.impl.annotations.RelaxedMockK
|
||||
import io.mockk.mockk
|
||||
|
@ -56,6 +64,7 @@ import io.mockk.unmockkStatic
|
|||
import io.mockk.verify
|
||||
import io.mockk.verifySequence
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.test.runBlockingTest
|
||||
import me.proton.core.test.kotlin.CoroutinesTest
|
||||
import org.junit.Rule
|
||||
import kotlin.test.BeforeTest
|
||||
|
@ -92,6 +101,12 @@ class MailboxViewModelTest : CoroutinesTest {
|
|||
@RelaxedMockK
|
||||
private lateinit var messageServiceScheduler: MessagesService.Scheduler
|
||||
|
||||
@RelaxedMockK
|
||||
private lateinit var conversationModeEnabled: ConversationModeEnabled
|
||||
|
||||
@RelaxedMockK
|
||||
private lateinit var getConversations: GetConversations
|
||||
|
||||
private lateinit var viewModel: MailboxViewModel
|
||||
|
||||
@BeforeTest
|
||||
|
@ -106,7 +121,9 @@ class MailboxViewModelTest : CoroutinesTest {
|
|||
contactsRepository,
|
||||
verifyConnection,
|
||||
networkConfigurator,
|
||||
messageServiceScheduler
|
||||
messageServiceScheduler,
|
||||
conversationModeEnabled,
|
||||
getConversations
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -503,6 +520,109 @@ class MailboxViewModelTest : CoroutinesTest {
|
|||
assertEquals(expected, actual.observedValues.first())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getMailboxItemsCallsGetConversationsUseCaseWhenConversationModeIsEnabled() = runBlockingTest {
|
||||
val location = Constants.MessageLocationType.INBOX
|
||||
val labelId = "labelId923842"
|
||||
val includeLabels = true
|
||||
val uuid = "9238423bbe2h3423489wssdf"
|
||||
val refreshMessages = false
|
||||
every { conversationModeEnabled(location) } returns true
|
||||
|
||||
viewModel.getMailboxItems(
|
||||
location,
|
||||
labelId,
|
||||
includeLabels,
|
||||
uuid,
|
||||
refreshMessages,
|
||||
123L
|
||||
)
|
||||
|
||||
coVerifySequence { getConversations(location) }
|
||||
verify { messageServiceScheduler wasNot Called }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getMailboxItemsReturnsMailboxItemsMappedFromConversationsWhenGetConversationsUseCaseSucceeds() =
|
||||
runBlockingTest {
|
||||
val location = Constants.MessageLocationType.INBOX
|
||||
val labelId = "labelId923842"
|
||||
val includeLabels = true
|
||||
val uuid = "9238423bbe2h3423489wssdf"
|
||||
val refreshMessages = false
|
||||
val sender = Correspondent("senderName", "sender@protonmail.com")
|
||||
val recipients = listOf(
|
||||
Correspondent("recipient", "recipient@protonmail.com"),
|
||||
Correspondent("recipient1", "recipient1@pm.ch")
|
||||
)
|
||||
val conversation = buildFakeConversation(sender, recipients)
|
||||
val successResult = GetConversationsResult.Success(listOf(conversation))
|
||||
every { conversationModeEnabled(location) } returns true
|
||||
coEvery { getConversations(location) } returns flowOf(successResult)
|
||||
|
||||
val actual = viewModel.getMailboxItems(
|
||||
location,
|
||||
labelId,
|
||||
includeLabels,
|
||||
uuid,
|
||||
refreshMessages,
|
||||
).testObserver()
|
||||
|
||||
val expected = listOf(
|
||||
MailboxUiItem(
|
||||
"conversationId",
|
||||
"senderName",
|
||||
"subject",
|
||||
0,
|
||||
hasAttachments = true,
|
||||
isStarred = false,
|
||||
isRead = false,
|
||||
expirationTime = 0,
|
||||
messagesCount = 4,
|
||||
messageData = null,
|
||||
isDeleted = false,
|
||||
labelIds = emptyList(),
|
||||
recipients = "recipient, recipient1"
|
||||
)
|
||||
)
|
||||
assertEquals(expected, actual.observedValues.first())
|
||||
}
|
||||
|
||||
private fun buildFakeConversation(
|
||||
sender: Correspondent,
|
||||
recipients: List<Correspondent>
|
||||
) = Conversation(
|
||||
"conversationId",
|
||||
"subject",
|
||||
listOf(sender),
|
||||
recipients,
|
||||
4,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
"senderAddressId",
|
||||
listOf(),
|
||||
listOf(
|
||||
MessageEntity(
|
||||
"messageId",
|
||||
"conversationId",
|
||||
"subject",
|
||||
true,
|
||||
sender,
|
||||
recipients,
|
||||
123421L,
|
||||
0,
|
||||
0,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
emptyList(),
|
||||
emptyList(),
|
||||
""
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
private fun fakeMailboxUiData(
|
||||
itemId: String,
|
||||
senderName: String,
|
||||
|
|
Loading…
Reference in New Issue