Implement Parent/Children icons for Folders in Move To

MAILAND-2301
This commit is contained in:
Davide Farella 2021-10-20 09:28:28 +02:00 committed by Davide Giuseppe Farella
parent dd35ed5aed
commit e70556022f
5 changed files with 98 additions and 102 deletions

View File

@ -28,7 +28,6 @@ import ch.protonmail.android.labels.data.remote.worker.UpdateConversationsLabels
import ch.protonmail.android.labels.domain.model.LabelId
import ch.protonmail.android.labels.domain.model.LabelType
import ch.protonmail.android.labels.domain.model.ManageLabelActionResult
import ch.protonmail.android.labels.domain.usecase.GetLabelsByType
import ch.protonmail.android.labels.domain.usecase.GetLabelsOrFolderWithChildrenByType
import ch.protonmail.android.labels.domain.usecase.UpdateMessageLabels
import ch.protonmail.android.labels.presentation.mapper.LabelDomainActionItemUiMapper
@ -60,7 +59,6 @@ private const val MAX_NUMBER_OF_SELECTED_LABELS = 100
@HiltViewModel
internal class LabelsActionSheetViewModel @Inject constructor(
private val savedStateHandle: SavedStateHandle,
private val getLabelsByType: GetLabelsByType,
private val getLabelsOrFolderWithChildrenByType: GetLabelsOrFolderWithChildrenByType,
private val accountManager: AccountManager,
private val userManager: UserManager,

View File

@ -94,11 +94,14 @@ class LabelDomainActionItemUiMapper @Inject constructor(
is LabelOrFolderWithChildren.Label -> LabelType.MESSAGE_LABEL
is LabelOrFolderWithChildren.Folder -> LabelType.FOLDER
}
val iconRes = when (labelType) {
LabelType.MESSAGE_LABEL -> R.drawable.circle_labels_selection
LabelType.FOLDER ->
if (useFolderColor) R.drawable.ic_folder_filled else R.drawable.ic_folder
LabelType.CONTACT_GROUP -> throw IllegalArgumentException("Contacts are currently unsupported")
val iconRes = when (label) {
is LabelOrFolderWithChildren.Label -> R.drawable.circle_labels_selection
is LabelOrFolderWithChildren.Folder ->
if (useFolderColor) {
if (label.children.isEmpty()) R.drawable.ic_folder_filled else R.drawable.ic_folder_multiple_filled
} else {
if (label.children.isEmpty()) R.drawable.ic_folder else R.drawable.ic_folder_multiple
}
}
val colorInt = if (useFolderColor) {

View File

@ -0,0 +1,29 @@
<!--
~ 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/.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M6,1.5H12.3462L14.8846,3.9546H24V16.5H6V1.5ZM1.5,6H4.5V18L19.5,18V21H4.5H3H1.5V6Z"
android:fillColor="@color/icon_norm"
android:fillType="evenOdd"/>
</vector>

View File

@ -151,24 +151,24 @@ class LabelDomainActionItemUiMapperTest {
val thirdFirstSecond = "third.first.second"
val thirdSecond = "third.second"
val input = buildFolders {
+first {
+firstFirst
folder(first) {
folder(firstFirst)
}
+second
+third {
+thirdFirst {
+thirdFirstFirst
+thirdFirstSecond
folder(second)
folder(third) {
folder(thirdFirst) {
folder(thirdFirstFirst)
folder(thirdFirstSecond)
}
+thirdSecond
folder(thirdSecond)
}
}
val expected = listOf(
buildActionItem(name = first, folderLevel = 0),
buildActionItem(name = first, folderLevel = 0, hasChildren = true),
buildActionItem(name = firstFirst, folderLevel = 1),
buildActionItem(name = second, folderLevel = 0),
buildActionItem(name = third, folderLevel = 0),
buildActionItem(name = thirdFirst, folderLevel = 1),
buildActionItem(name = third, folderLevel = 0, hasChildren = true),
buildActionItem(name = thirdFirst, folderLevel = 1, hasChildren = true),
buildActionItem(name = thirdFirstFirst, folderLevel = 2),
buildActionItem(name = thirdFirstSecond, folderLevel = 2),
buildActionItem(name = thirdSecond, folderLevel = 1)
@ -199,7 +199,7 @@ class LabelDomainActionItemUiMapperTest {
every { Color.parseColor(blueString) } returns blueInt
val expected = listOf(
buildActionItem(name = parent, folderLevel = 0, colorInt = redInt),
buildActionItem(name = parent, folderLevel = 0, hasChildren = true, colorInt = redInt),
buildActionItem(name = child, folderLevel = 1, colorInt = blueInt),
)
@ -228,7 +228,7 @@ class LabelDomainActionItemUiMapperTest {
}
val expected = listOf(
buildActionItem(name = parent, folderLevel = 0, colorInt = redInt),
buildActionItem(name = parent, folderLevel = 0, hasChildren = true, colorInt = redInt),
buildActionItem(name = child, folderLevel = 1, colorInt = redInt),
)
@ -254,7 +254,7 @@ class LabelDomainActionItemUiMapperTest {
}
val expected = listOf(
buildActionItem(name = parent, folderLevel = 0, colorInt = 0),
buildActionItem(name = parent, folderLevel = 0, hasChildren = true, colorInt = 0),
buildActionItem(name = child, folderLevel = 1, colorInt = 0),
)
@ -287,12 +287,13 @@ class LabelDomainActionItemUiMapperTest {
private fun buildActionItem(
name: String,
folderLevel: Int,
hasChildren: Boolean = false,
colorInt: Int = TEST_COLOR_INT
) = LabelActonItemUiModel(
labelId = LabelId(name),
title = name,
folderLevel = folderLevel,
iconRes = R.drawable.ic_folder_filled,
iconRes = if (hasChildren) R.drawable.ic_folder_multiple_filled else R.drawable.ic_folder_filled,
colorInt = colorInt,
labelType = LabelType.FOLDER
)

View File

@ -27,11 +27,10 @@ import ch.protonmail.android.core.Constants
import ch.protonmail.android.core.UserManager
import ch.protonmail.android.data.local.model.Message
import ch.protonmail.android.labels.data.remote.worker.UpdateConversationsLabelsWorker
import ch.protonmail.android.labels.domain.model.Label
import ch.protonmail.android.labels.domain.model.LabelId
import ch.protonmail.android.labels.domain.model.LabelOrFolderWithChildren
import ch.protonmail.android.labels.domain.model.LabelType
import ch.protonmail.android.labels.domain.model.ManageLabelActionResult
import ch.protonmail.android.labels.domain.usecase.GetLabelsByType
import ch.protonmail.android.labels.domain.usecase.GetLabelsOrFolderWithChildrenByType
import ch.protonmail.android.labels.domain.usecase.UpdateMessageLabels
import ch.protonmail.android.labels.presentation.LabelsActionSheetViewModel
@ -62,12 +61,13 @@ import me.proton.core.accountmanager.domain.AccountManager
import me.proton.core.domain.entity.UserId
import me.proton.core.test.android.ArchTest
import me.proton.core.test.kotlin.CoroutinesTest
import me.proton.core.util.kotlin.EMPTY_STRING
import kotlin.test.AfterTest
import kotlin.test.BeforeTest
import kotlin.test.Test
import kotlin.test.assertEquals
private val TEST_USER_ID = UserId("userId")
class LabelsActionSheetViewModelTest : ArchTest, CoroutinesTest {
@MockK
@ -79,15 +79,12 @@ class LabelsActionSheetViewModelTest : ArchTest, CoroutinesTest {
@MockK
private lateinit var userManager: UserManager
@MockK
private lateinit var getLabelsByType: GetLabelsByType
private val getLabelsOrFolderWithChildrenByType: GetLabelsOrFolderWithChildrenByType = mockk {
coEvery { this@mockk(any(), any()) } returns emptyList()
}
private val accountManager: AccountManager = mockk {
every { getPrimaryUserId() } returns flowOf(userId)
every { getPrimaryUserId() } returns flowOf(TEST_USER_ID)
}
@MockK
@ -113,7 +110,6 @@ class LabelsActionSheetViewModelTest : ArchTest, CoroutinesTest {
private val context: Context = mockk {
every { getColor(any()) } returns defaultColorInt
}
val userId = UserId("userId")
private val labelDomainUiMapper = LabelDomainActionItemUiMapper(context)
@ -131,25 +127,6 @@ class LabelsActionSheetViewModelTest : ArchTest, CoroutinesTest {
every { messageId } returns messageId1
every { labelIDsNotIncludingLocations } returns listOf(labelId1)
}
private val label1 = Label(
id = LabelId(labelId1),
name = title,
color = color,
order = 0,
type = LabelType.MESSAGE_LABEL,
path = EMPTY_STRING,
parentId = EMPTY_STRING
)
private val label2 = Label(
id = LabelId(labelId2),
name = title,
color = color,
order = 0,
type = LabelType.FOLDER,
path = EMPTY_STRING,
parentId = EMPTY_STRING
)
private val model1UiLabel = LabelActonItemUiModel(
labelId = LabelId(labelId1),
@ -195,26 +172,11 @@ class LabelsActionSheetViewModelTest : ArchTest, CoroutinesTest {
savedStateHandle.get<ActionSheetTarget>(LabelsActionSheet.EXTRA_ARG_ACTION_TARGET)
} returns ActionSheetTarget.MAILBOX_ITEMS_IN_MAILBOX_SCREEN
coEvery { getLabelsByType.invoke(any()) } returns listOf(label1)
coEvery { messageRepository.findMessageById(messageId1) } returns message1
every { userManager.requireCurrentUserId() } returns userId
every { userManager.requireCurrentUserId() } returns TEST_USER_ID
coEvery { conversationModeEnabled(any()) } returns false
viewModel = LabelsActionSheetViewModel(
savedStateHandle = savedStateHandle,
getLabelsByType = getLabelsByType,
getLabelsOrFolderWithChildrenByType = getLabelsOrFolderWithChildrenByType,
accountManager = accountManager,
userManager = userManager,
updateMessageLabels = updateMessageLabels,
updateConversationsLabels = updateConversationsLabels,
moveMessagesToFolder = moveMessagesToFolder,
moveConversationsToFolder = moveConversationsToFolder,
conversationModeEnabled = conversationModeEnabled,
messageRepository = messageRepository,
conversationsRepository = conversationsRepository,
labelDomainUiMapper = labelDomainUiMapper
)
viewModel = buildViewModel()
}
@AfterTest
@ -234,7 +196,7 @@ class LabelsActionSheetViewModelTest : ArchTest, CoroutinesTest {
moveMessagesToFolder(
listOf(messageId1), Constants.MessageLocationType.ARCHIVE.messageLocationTypeValue.toString(),
Constants.MessageLocationType.INBOX.messageLocationTypeValue.toString(),
userId
TEST_USER_ID
)
} just Runs
@ -248,7 +210,7 @@ class LabelsActionSheetViewModelTest : ArchTest, CoroutinesTest {
listOf(messageId1),
archiveLocationId,
inboxLocationId,
userId
TEST_USER_ID
)
}
assertEquals(ManageLabelActionResult.LabelsSuccessfullySaved, viewModel.actionsResult.value)
@ -278,7 +240,10 @@ class LabelsActionSheetViewModelTest : ArchTest, CoroutinesTest {
runBlockingTest {
// given
coEvery { getLabelsOrFolderWithChildrenByType(any(), any()) } returns
listOf(buildLabelOrFolderWithChildrenLabel(id = LabelId(labelId1), name = title))
coEvery { userManager.didReachLabelsThreshold(any()) } returns false
val viewModel = buildViewModel()
// when
viewModel.onLabelClicked(model1UiLabel)
@ -292,7 +257,10 @@ class LabelsActionSheetViewModelTest : ArchTest, CoroutinesTest {
fun verifyThatAfterOnLabelIsClickedForLabelTypeStandardLabelsAreAdded() = runBlockingTest {
// given
coEvery { getLabelsOrFolderWithChildrenByType(any(), any()) } returns
listOf(buildLabelOrFolderWithChildrenLabel(id = LabelId(labelId1), name = title))
coEvery { userManager.didReachLabelsThreshold(any()) } returns false
val viewModel = buildViewModel()
// when
viewModel.onLabelClicked(model1UiLabel)
@ -313,23 +281,8 @@ class LabelsActionSheetViewModelTest : ArchTest, CoroutinesTest {
}
coEvery { messageRepository.findMessageById(any()) } returns testMessage
val expectedResult = ManageLabelActionResult.ErrorLabelsThresholdReached(maximumLabelsSelectedThreshold)
val buildAListOfMoreThanOneHundredSelectedLabels = buildAListOfMoreThanOneHundredSelectedLabels()
coEvery { getLabelsByType.invoke(any()) } returns buildAListOfMoreThanOneHundredSelectedLabels
val labelsActionSheetViewModel = LabelsActionSheetViewModel(
savedStateHandle = savedStateHandle,
getLabelsByType = getLabelsByType,
getLabelsOrFolderWithChildrenByType = getLabelsOrFolderWithChildrenByType,
accountManager = accountManager,
userManager = userManager,
updateMessageLabels = updateMessageLabels,
updateConversationsLabels = updateConversationsLabels,
moveMessagesToFolder = moveMessagesToFolder,
moveConversationsToFolder = moveConversationsToFolder,
conversationModeEnabled = conversationModeEnabled,
messageRepository = messageRepository,
conversationsRepository = conversationsRepository,
labelDomainUiMapper = labelDomainUiMapper
)
coEvery { getLabelsOrFolderWithChildrenByType(any(), any()) } returns buildAListOfMoreThanOneHundredSelectedLabels()
val labelsActionSheetViewModel = buildViewModel()
// when
labelsActionSheetViewModel.onLabelClicked(model1UiLabel)
@ -363,7 +316,7 @@ class LabelsActionSheetViewModelTest : ArchTest, CoroutinesTest {
runBlockingTest {
// given
coEvery { userManager.currentUserId } returns userId
coEvery { userManager.currentUserId } returns TEST_USER_ID
coEvery { moveMessagesToFolder.invoke(any(), any(), any(), any()) } just Runs
coEvery { conversationModeEnabled(any()) } returns true
every {
@ -384,7 +337,7 @@ class LabelsActionSheetViewModelTest : ArchTest, CoroutinesTest {
fun verifyThatWhenLabelIsClickedForFolderTypeWithConversationModeEnabledAndMoveConversationsToFolderReturnsErrorResultErrorMovingToFolderIsEmitted() =
runBlockingTest {
// given
coEvery { userManager.currentUserId } returns userId
coEvery { userManager.currentUserId } returns TEST_USER_ID
coEvery { conversationModeEnabled(any()) } returns true
coEvery {
moveConversationsToFolder.invoke(any(), any(), any())
@ -403,8 +356,8 @@ class LabelsActionSheetViewModelTest : ArchTest, CoroutinesTest {
// given
coEvery { userManager.currentUserId } returns userId
coEvery { moveMessagesToFolder.invoke(any(), any(), any(), userId) } just Runs
coEvery { userManager.currentUserId } returns TEST_USER_ID
coEvery { moveMessagesToFolder.invoke(any(), any(), any(), TEST_USER_ID) } just Runs
coEvery { conversationModeEnabled(any()) } returns true
every {
savedStateHandle.get<ActionSheetTarget>("extra_arg_labels_action_sheet_actions_target")
@ -419,18 +372,30 @@ class LabelsActionSheetViewModelTest : ArchTest, CoroutinesTest {
assertEquals(ManageLabelActionResult.MessageSuccessfullyMoved(false), viewModel.actionsResult.value)
}
private fun buildAListOfMoreThanOneHundredSelectedLabels(): List<Label> {
return (0..100).map { index ->
Label(
id = LabelId("$index"),
name = "title $index",
color = color,
order = 0,
type = LabelType.MESSAGE_LABEL,
path = EMPTY_STRING,
parentId = EMPTY_STRING
)
}
private fun buildViewModel() = LabelsActionSheetViewModel(
savedStateHandle = savedStateHandle,
getLabelsOrFolderWithChildrenByType = getLabelsOrFolderWithChildrenByType,
accountManager = accountManager,
userManager = userManager,
updateMessageLabels = updateMessageLabels,
updateConversationsLabels = updateConversationsLabels,
moveMessagesToFolder = moveMessagesToFolder,
moveConversationsToFolder = moveConversationsToFolder,
conversationModeEnabled = conversationModeEnabled,
messageRepository = messageRepository,
conversationsRepository = conversationsRepository,
labelDomainUiMapper = labelDomainUiMapper
)
}
private fun buildLabelOrFolderWithChildrenLabel(
name: String = labelId1,
id: LabelId = LabelId(name)
) = LabelOrFolderWithChildren.Label(
id = id,
name = name,
color = color
)
private fun buildAListOfMoreThanOneHundredSelectedLabels(): List<LabelOrFolderWithChildren.Label> =
(0..100).map { index -> buildLabelOrFolderWithChildrenLabel("$index") }
}