Add auto-dismiss capability to Remote Messaging Framework#4816
Open
SabrinaTardio wants to merge 10 commits into
Open
Add auto-dismiss capability to Remote Messaging Framework#4816SabrinaTardio wants to merge 10 commits into
SabrinaTardio wants to merge 10 commits into
Conversation
Add optional dismissAfterDaysShown field to RMF messages, allowing messages to be automatically dismissed after a configurable number of days from their first impression.
Wrap dismissAfterDaysShown under a new displayConditions JSON object and add a trigger field (after_idle) that controls when messages are shown. Thread idle-return context through iOS HomePageConfiguration and NTP so after-idle messages appear in both the main and focussed New Tab Page.
- Move auto-dismiss write from read-only context to self.context via dismissExpiredMessage helper to avoid stale in-memory state - Add @available(iOS 16, *) and .timeLimit(.minutes(1)) to new Swift Testing tests in HomePageConfigurationTests - Fix MockRemoteMessagingConfigFetcher to use displayConditions - Fix stray closing brace in mapper tests
- Change isOpenedAfterIdle from closure to plain Bool since the NTP is recreated on every state change and the value is fixed for its lifetime - Extract displayConditions mapping into mapToDisplayConditions using MappingValidator for cleaner parsing - Add mapEnumIfPresent to MappingValidator for optional enum fields - Clamp dismissAfterDaysShown values <= 0 to 1 - Add tests for mapEnumIfPresent and dismissAfterDaysShown clamping
Avoids nested performAndWait on the write context from within a read-only context's performAndWait block. The fetch already skips expired messages via continue, so the dismiss is a background side-effect. Updated test to verify the fetch behavior rather than the synchronous dismiss state.
The fire-and-forget Task means the dismiss may not have completed when fetchDismissedRemoteMessageIDs is called. The test already verifies the important behavior: the expired message is not returned by fetchScheduledRemoteMessage.
Contributor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Task/Issue URL: https://app.asana.com/1/137249556945/project/72649045549333/task/1214525802264426
Tech Design URL: https://app.asana.com/1/137249556945/project/481882893211075/task/1214488238400075
CC: N/A
Description
displayConditionswrapper object to RMF message JSON config, nestingdismissAfterDaysShownand a newtriggerfieldMessageTriggerenum andDisplayConditionsstruct to the domain model; messages with unknown triggers are silently discarded for forward compatibilityfetchScheduledRemoteMessagewith an optionaltriggerparameter for filtering messages by their trigger contextHomePageConfiguration.refresh(openedAfterIdle:)passestrigger: .afterIdlewhen the user returns from idle, andNewTabPageMessagesModelforwards this via anisOpenedAfterIdleclosurehasEscapeHatchto the focussed NTP inSuggestionTrayViewControllerdismissAfterDaysShowncontinues to work as before, now nested underdisplayConditionsTesting Steps
Test 1 -- Regular message (no trigger, no auto-dismiss):
Test 2 -- After-idle trigger only:
Test 3 -- Normal app usage after idle return:
Test 4 -- After-idle + auto-dismiss combo:
Test 5 -- Unknown trigger (forward compatibility):
Impact and Risks
Impact Level: Low
What could go wrong?
onAppearfires, the after-idle message may not show in focussed mode. Mitigated by the fact thatsetEscapeHatchis called before the view is installed in the hierarchyQuality Considerations
displayConditionsis fully backward compatible; messages without it behave identically to beforeNotes to Reviewer
displayConditionswrapper replaces the top-leveldismissAfterDaysShownfield in the JSON schema. The domain model groups both fields underDisplayConditionsSuggestionTrayViewControllerto forward the escape hatch staterelease/ios/7.219.0was deletedMade with Cursor
Note
Medium Risk
Medium risk because it changes the Core Data schema and message selection logic (new
firstShownDate, trigger-based filtering, and auto-dismiss behavior), which can affect when messages appear or are dismissed.Overview
Adds display-based delivery controls to remote messages via a new
displayConditionsJSON object, introducingMessageTrigger/DisplayConditionsin the domain model and mapping that discards messages with unknown triggers.Extends scheduled message fetching to optionally filter by trigger context and to auto-dismiss messages whose
dismissAfterDaysShownhas elapsed, persisting a newfirstShownDateCore Data field (model version bumped toRemoteMessaging 3) and recording it on first show.Threads the “opened after idle” context through iOS new tab/home message refresh flows so after-idle messages can be surfaced appropriately (including focused NTP), and updates mocks/tests to cover mapping validation, trigger filtering, and auto-dismiss scenarios.
Reviewed by Cursor Bugbot for commit fd39930. Bugbot is set up for automated code reviews on this repo. Configure here.