diff --git a/integration_test/scenarios/labels/remove_a_label_from_email_scenario.dart b/integration_test/scenarios/labels/remove_a_label_from_email_scenario.dart index 9d00e0e67..8f36c0d7e 100644 --- a/integration_test/scenarios/labels/remove_a_label_from_email_scenario.dart +++ b/integration_test/scenarios/labels/remove_a_label_from_email_scenario.dart @@ -19,6 +19,7 @@ class RemoveALabelFromEmailScenario extends BaseTestScenario @override Future runTestLogic() async { const emailUser = String.fromEnvironment('BASIC_AUTH_EMAIL'); + expect(emailUser, isNotEmpty, reason: 'BASIC_AUTH_EMAIL must be set'); final threadRobot = ThreadRobot($); final emailRobot = EmailRobot($); diff --git a/lib/features/email/data/network/email_api.dart b/lib/features/email/data/network/email_api.dart index 2abb44e32..7ef5187d2 100644 --- a/lib/features/email/data/network/email_api.dart +++ b/lib/features/email/data/network/email_api.dart @@ -971,6 +971,10 @@ class EmailAPI with HandleSetErrorMixin, MailAPIMixin { List emailIds, KeyWordIdentifier labelKeyword, ) async { + if (emailIds.isEmpty) { + throw ArgumentError.value(emailIds, 'emailIds', 'must not be empty'); + } + final method = SetEmailMethod(accountId) ..addUpdates(emailIds.generateMapUpdateObjectLabel(labelKeyword)); @@ -987,8 +991,9 @@ class EmailAPI with HandleSetErrorMixin, MailAPIMixin { ); final emailIdsUpdated = response?.updated?.keys ?? []; - final ids = emailIds.map((emailId) => emailId.id); - final isUpdated = emailIdsUpdated.every(ids.contains); + final ids = emailIds.toSetIds(); + final isUpdated = ids.every(emailIdsUpdated.contains) && + emailIdsUpdated.length == ids.length; if (emailIdsUpdated.isEmpty || !isUpdated) { throw parseErrorForSetResponse(response, emailIds.first.id); @@ -1031,6 +1036,10 @@ class EmailAPI with HandleSetErrorMixin, MailAPIMixin { List emailIds, KeyWordIdentifier labelKeyword, ) async { + if (emailIds.isEmpty) { + throw ArgumentError.value(emailIds, 'emailIds', 'must not be empty'); + } + final method = SetEmailMethod(accountId) ..addUpdates(emailIds.generateMapUpdateObjectLabel( labelKeyword, @@ -1050,13 +1059,12 @@ class EmailAPI with HandleSetErrorMixin, MailAPIMixin { ); final emailIdsUpdated = response?.updated?.keys ?? []; - final ids = emailIds.map((emailId) => emailId.id); - final isUpdated = emailIdsUpdated.every(ids.contains); + final ids = emailIds.toSetIds(); + final isUpdated = emailIdsUpdated.every(ids.contains) && + emailIdsUpdated.length == ids.length; if (emailIdsUpdated.isEmpty || !isUpdated) { - for (var id in emailIds) { - throw parseErrorForSetResponse(response, id.id); - } + throw parseErrorForSetResponse(response, emailIds.first.id); } } } \ No newline at end of file diff --git a/lib/features/thread/data/extensions/map_keywords_extension.dart b/lib/features/thread/data/extensions/map_keywords_extension.dart index 26d7a1e54..2990cae09 100644 --- a/lib/features/thread/data/extensions/map_keywords_extension.dart +++ b/lib/features/thread/data/extensions/map_keywords_extension.dart @@ -32,11 +32,11 @@ extension MapKeywordsExtension on Map? { this?.remove(keyword); } - void toggleKeyword(KeyWordIdentifier keyword, bool remove) { - if (remove) { - this?.remove(keyword); + void toggleKeyword(KeyWordIdentifier keyword, bool shouldRemove) { + if (shouldRemove) { + removeKeyword(keyword); } else { - this?[keyword] = true; + addKeyword(keyword); } } } diff --git a/model/lib/extensions/list_email_id_extension.dart b/model/lib/extensions/list_email_id_extension.dart index 0ea686fbf..962049188 100644 --- a/model/lib/extensions/list_email_id_extension.dart +++ b/model/lib/extensions/list_email_id_extension.dart @@ -9,6 +9,8 @@ extension ListEmailIdExtension on List { List toIds() => map((emailId) => emailId.id).toList(); + Set toSetIds() => map((emailId) => emailId.id).toSet(); + Map generateMapUpdateObjectMarkAsRead(ReadActions readActions) { return { for (var emailId in this)