Skip to content

Conversation

@anikiki
Copy link
Contributor

@anikiki anikiki commented Dec 15, 2025

Task/Issue URL: https://app.asana.com/1/137249556945/task/1212464602611971?focus=true

Description

Added support for per-card item matching and exclusion rules in the remote messaging system. This enhancement allows for more granular control over which card items are displayed within a CardsList message.

Steps to test this PR

Check the instructions for testing in the description of the task -> https://app.asana.com/1/137249556945/task/1212464602611971?focus=true

CardsList filtering

  • Verify that CardsList messages with card items containing matching rules only display items that match the device criteria
  • Verify that card items with exclusion rules are properly filtered out when the device matches those exclusion criteria
  • Verify that when all card items in a CardsList are filtered out, the entire message is not displayed
  • Verify that regular messages (non-CardsList) continue to work as before

NO UI changes


Note

Adds per-card matching/exclusion rules for CardsList messages and filters list items accordingly, with JSON mapping updates and comprehensive tests.

  • API:
    • Add CardItem fields: matchingRules, exclusionRules in remote-messaging-api.
  • Matching/Evaluation:
    • In RemoteMessagingConfigMatcher, process Content.CardsList by evaluating each CardItem's matchingRules/exclusionRules.
    • Return message with filtered listItems; return null if all items are filtered; non-CardsList messages unchanged.
  • Mapping:
    • Extend JsonListItem with matchingRules/exclusionRules and map them in JsonRemoteMessageMapper.
  • Tests:
    • Add/extend tests for JSON mapping, matcher behavior (partial/empty/all filtered cases), ViewModel, pixel helper, and modal evaluator to include new CardItem fields.

Written by Cursor Bugbot for commit 839f2eb. This will update automatically on new commits. Configure here.

Copy link
Contributor Author

anikiki commented Dec 15, 2025

@anikiki anikiki marked this pull request as ready for review December 15, 2025 23:36
@anikiki anikiki requested a review from cmonfortep December 15, 2025 23:50
@anikiki anikiki changed the title Add matching and exclusion rules to CardsList and related tests. [Android] "What’s New" promo message: Matching rules and excusion rules at card item level Dec 15, 2025
@anikiki anikiki force-pushed the feature/ana/android_whats_new_promo_message_prompt_dispatcher_modal_coordinator branch from 2549ea7 to f4be73c Compare December 16, 2025 11:08
@anikiki anikiki force-pushed the feature/ana/android/whats_new_promo_message_matching_rules_and_excusion_rules_at_card_item_level branch from 384bda0 to 12cfe3c Compare December 16, 2025 11:08
@anikiki anikiki force-pushed the feature/ana/android_whats_new_promo_message_prompt_dispatcher_modal_coordinator branch 2 times, most recently from 1045448 to 51a045a Compare December 16, 2025 11:35
@anikiki anikiki force-pushed the feature/ana/android/whats_new_promo_message_matching_rules_and_excusion_rules_at_card_item_level branch from 12cfe3c to 8528578 Compare December 16, 2025 11:35
@anikiki anikiki force-pushed the feature/ana/android_whats_new_promo_message_prompt_dispatcher_modal_coordinator branch from 51a045a to 661ffa2 Compare December 16, 2025 17:24
@anikiki anikiki force-pushed the feature/ana/android/whats_new_promo_message_matching_rules_and_excusion_rules_at_card_item_level branch from 8528578 to 839f2eb Compare December 16, 2025 17:24
val itemExclusion = if (cardItem.exclusionRules.isEmpty()) {
EvaluationResult.Fail
} else {
cardItem.exclusionRules.evaluateExclusionRules(message.id, rules)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: Card item percentile rules use parent message ID

When evaluating card item rules in filterCardsListMessage, message.id is passed to evaluateMatchingRules and evaluateExclusionRules instead of cardItem.id. These functions use this ID for percentile cohort lookups via remoteMessagingCohortStore.getPercentile(messageId). This means all card items within a message share the same percentile cohort value, so if rules with targetPercentile are used on card items, they cannot have independent percentage-based rollouts - they'll all pass or fail together based on the message's percentile. If independent per-card percentile targeting is intended, the card item's own id would need to be passed instead.


Please tell me if this was useful or not with a 👍 or 👎.

Fix in Cursor Fix in Web

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is probably correct. If there's a rule used by an item, we should pass the cardItem.id. We use that id to store the percentile and keep the logic deterministic.
The message will have its own percentile to decide % for the message. The item percentile should belong to them.

Copy link
Contributor

@cmonfortep cmonfortep left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

}

@Test
fun whenCardsListMessageWithAllCardItemsFailingRulesThenReturnsNull() = runBlocking {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes sense, but checking with iOS if that was captured on the requirements.

}

@Test
fun whenNonCardsListMessageThenReturnsMessageUnmodified() = runBlocking {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand the purpose of this test.

val itemExclusion = if (cardItem.exclusionRules.isEmpty()) {
EvaluationResult.Fail
} else {
cardItem.exclusionRules.evaluateExclusionRules(message.id, rules)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is probably correct. If there's a rule used by an item, we should pass the cardItem.id. We use that id to store the percentile and keep the logic deterministic.
The message will have its own percentile to decide % for the message. The item percentile should belong to them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants