diff --git a/app/src/main/kotlin/ch/protonmail/android/navigation/Home.kt b/app/src/main/kotlin/ch/protonmail/android/navigation/Home.kt index 9d7c1ed5d2..e23a907bd5 100644 --- a/app/src/main/kotlin/ch/protonmail/android/navigation/Home.kt +++ b/app/src/main/kotlin/ch/protonmail/android/navigation/Home.kt @@ -773,10 +773,10 @@ fun Home( onShowErrorSnackbar = { showErrorSnackbar(it) }, - onSendGroupMessage = { + onSendGroupMessage = { groupName, members -> navController.navigate( Screen.MessageActionComposer( - DraftAction.ComposeToAddresses(it) + DraftAction.ComposeToContactGroup(groupName, members) ) ) }, diff --git a/app/src/main/kotlin/ch/protonmail/android/navigation/route/HomeRoutes.kt b/app/src/main/kotlin/ch/protonmail/android/navigation/route/HomeRoutes.kt index 2d4d331233..5420380497 100644 --- a/app/src/main/kotlin/ch/protonmail/android/navigation/route/HomeRoutes.kt +++ b/app/src/main/kotlin/ch/protonmail/android/navigation/route/HomeRoutes.kt @@ -426,7 +426,7 @@ internal fun NavGraphBuilder.addContactSearch(navController: NavHostController) internal fun NavGraphBuilder.addContactGroupDetails( navController: NavHostController, onShowErrorSnackbar: (String) -> Unit, - onSendGroupMessage: (List) -> Unit, + onSendGroupMessage: (groupName: String, members: List) -> Unit, onOpenContact: (ContactId) -> Unit, showFeatureMissingSnackbar: () -> Unit ) { diff --git a/mail-composer/data/src/main/kotlin/ch/protonmail/android/composer/data/mapper/DraftMapper.kt b/mail-composer/data/src/main/kotlin/ch/protonmail/android/composer/data/mapper/DraftMapper.kt index 5fb5c3c04f..222643f6a1 100644 --- a/mail-composer/data/src/main/kotlin/ch/protonmail/android/composer/data/mapper/DraftMapper.kt +++ b/mail-composer/data/src/main/kotlin/ch/protonmail/android/composer/data/mapper/DraftMapper.kt @@ -108,6 +108,7 @@ fun DraftAction.toDraftCreateMode(): DraftCreateMode? = when (this) { DraftAction.Compose -> DraftCreateMode.Empty is DraftAction.MailTo -> DraftCreateMode.Mailto(this.uri) is DraftAction.ComposeToAddresses, + is DraftAction.ComposeToContactGroup, is DraftAction.PrefillForShare -> { Timber.e("rust-draft: mapping draft action $this failed! Unsupported by rust DraftCreateMode type") null diff --git a/mail-composer/presentation/src/main/kotlin/ch/protonmail/android/mailcomposer/presentation/viewmodel/ComposerViewModel.kt b/mail-composer/presentation/src/main/kotlin/ch/protonmail/android/mailcomposer/presentation/viewmodel/ComposerViewModel.kt index 2a6c22f254..fee7a9545b 100644 --- a/mail-composer/presentation/src/main/kotlin/ch/protonmail/android/mailcomposer/presentation/viewmodel/ComposerViewModel.kt +++ b/mail-composer/presentation/src/main/kotlin/ch/protonmail/android/mailcomposer/presentation/viewmodel/ComposerViewModel.kt @@ -113,6 +113,7 @@ import ch.protonmail.android.mailevents.domain.model.AppEvent import ch.protonmail.android.mailmessage.domain.model.DraftAction import ch.protonmail.android.mailmessage.domain.model.DraftAction.Compose import ch.protonmail.android.mailmessage.domain.model.DraftAction.ComposeToAddresses +import ch.protonmail.android.mailmessage.domain.model.DraftAction.ComposeToContactGroup import ch.protonmail.android.mailmessage.domain.model.DraftAction.Forward import ch.protonmail.android.mailmessage.domain.model.DraftAction.MailTo import ch.protonmail.android.mailmessage.domain.model.DraftAction.PrefillForShare @@ -508,6 +509,12 @@ class ComposerViewModel @AssistedInject constructor( } } + is ComposeToContactGroup -> { + prefillForNewDraft().onRight { + prefillForComposeToAction(listOf(draftAction.toGroupRecipient())) + } + } + is Forward, is Reply, is ReplyAll, @@ -989,6 +996,9 @@ class ComposerViewModel @AssistedInject constructor( } } + private fun ComposeToContactGroup.toGroupRecipient(): RecipientUiModel.Group = + RecipientUiModel.Group(name = name, members = members, color = "") + private fun String.stripNewLines() = this.replace("[\n\r]".toRegex(), " ") private fun logViewModelAction(action: ComposerAction, message: String) { diff --git a/mail-composer/presentation/src/test/kotlin/ch/protonmail/android/mailcomposer/presentation/viewmodel/ComposerViewModelTest.kt b/mail-composer/presentation/src/test/kotlin/ch/protonmail/android/mailcomposer/presentation/viewmodel/ComposerViewModelTest.kt index 60988e6487..b6279cb6d1 100644 --- a/mail-composer/presentation/src/test/kotlin/ch/protonmail/android/mailcomposer/presentation/viewmodel/ComposerViewModelTest.kt +++ b/mail-composer/presentation/src/test/kotlin/ch/protonmail/android/mailcomposer/presentation/viewmodel/ComposerViewModelTest.kt @@ -1178,6 +1178,48 @@ internal class ComposerViewModelTest { } } + @Test + fun `should set group recipient to state when contact group was given as an input`() = runTest { + // Given + val expectedUserId = expectedUserId { UserIdSample.Primary } + val groupName = "Friends" + val groupMembers = listOf("alice@example.com", "bob@example.com") + val expectedAction = DraftAction.ComposeToContactGroup(groupName, groupMembers) + val expectedDraftGroupRecipient = DraftRecipient.GroupRecipient( + name = groupName, + recipients = groupMembers.map { address -> + DraftRecipient.SingleRecipient( + name = "", + address = address, + validity = DraftRecipientValidity.Validating, + privacyLock = PrivacyLock.None + ) + } + ) + + expectNoInputDraftMessageId() + expectInputDraftAction { expectedAction } + expectStoreDraftSubjectSucceeds(Subject("")) + expectStoreDraftBodySucceeds(DraftBody("")) + expectUpdateRecipientsSucceeds(listOf(expectedDraftGroupRecipient), emptyList(), emptyList()) + expectObservedMessageAttachments() + expectNoRestoredState(savedStateHandle) + expectInitComposerWithNewEmptyDraftSucceeds(expectedUserId) { + DraftFieldsTestData.EmptyDraftWithPrimarySender + } + + // When + val viewModel = viewModel() + viewModel.composerStates.test { + // Then + assertEquals( + RecipientUiModel.Group(name = groupName, members = groupMembers, color = ""), + recipientsStateManager.recipients.value.toRecipients.firstOrNull() + ) + cancelAndIgnoreRemainingEvents() + } + } + @Test fun `should show warning when send button is clicked with expiration set and external recipients`() = runTest { // Given diff --git a/mail-contact/presentation/src/main/kotlin/ch/protonmail/android/mailcontact/presentation/contactgroupdetails/ContactGroupDetailsScreen.kt b/mail-contact/presentation/src/main/kotlin/ch/protonmail/android/mailcontact/presentation/contactgroupdetails/ContactGroupDetailsScreen.kt index 439a0ac7e9..be7b7df7f3 100644 --- a/mail-contact/presentation/src/main/kotlin/ch/protonmail/android/mailcontact/presentation/contactgroupdetails/ContactGroupDetailsScreen.kt +++ b/mail-contact/presentation/src/main/kotlin/ch/protonmail/android/mailcontact/presentation/contactgroupdetails/ContactGroupDetailsScreen.kt @@ -143,7 +143,12 @@ private fun ContactGroupDetails( SendGroupMessageAction( memberCount = uiModel.memberCount, - onClick = { actions.onSendGroupMessage(uiModel.members.map { it.emailAddress }) } + onClick = { + actions.onSendGroupMessage( + uiModel.name, + uiModel.members.map { it.emailAddress } + ) + } ) Column( @@ -274,7 +279,7 @@ fun ContactGroupDetailsScreenPreview() { actions = ContactGroupDetailsScreen.Actions( onBack = {}, onShowErrorSnackbar = {}, - onSendGroupMessage = {}, + onSendGroupMessage = { _, _ -> }, onOpenContact = {}, showFeatureMissingSnackbar = {} ) @@ -287,7 +292,7 @@ object ContactGroupDetailsScreen { data class Actions( val onBack: () -> Unit, val onShowErrorSnackbar: (String) -> Unit, - val onSendGroupMessage: (List) -> Unit, + val onSendGroupMessage: (groupName: String, members: List) -> Unit, val onOpenContact: (ContactId) -> Unit, val showFeatureMissingSnackbar: () -> Unit ) diff --git a/mail-message/domain/src/main/kotlin/ch/protonmail/android/mailmessage/domain/model/DraftAction.kt b/mail-message/domain/src/main/kotlin/ch/protonmail/android/mailmessage/domain/model/DraftAction.kt index 2c01b9eff9..3c513b0d94 100644 --- a/mail-message/domain/src/main/kotlin/ch/protonmail/android/mailmessage/domain/model/DraftAction.kt +++ b/mail-message/domain/src/main/kotlin/ch/protonmail/android/mailmessage/domain/model/DraftAction.kt @@ -39,6 +39,9 @@ sealed interface DraftAction { @Serializable data class ComposeToAddresses(val recipients: List) : DraftAction + @Serializable + data class ComposeToContactGroup(val name: String, val members: List) : DraftAction + @Serializable data class PrefillForShare(val intentShareInfo: IntentShareInfo) : DraftAction