MOBILE-419: Send in-app events for embedded blocks in parity with Android - #765
Merged
Merged
Conversation
Contributor
|
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Configuration timeout handling can suppress failure events, and image construction contains a data race.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Adds Android-parity event accounting, timing, failure reporting, targeting, and delayed delivery for embedded in-app blocks.
Changes:
- Centralizes show accounting and session-level deduplication.
- Adds embedded-block timing, delayed delivery, and polymorphic failure events.
- Expands targeting behavior, bridge services, dependency injection, and tests.
File summaries
| File | Description |
|---|---|
MindboxTests/Mock/MockInAppConfigurationDataFacade.swift |
Tracks failure-buffer actions. |
MindboxTests/InApp/Tests/WebView/MindboxWebPageRegistryTests.swift |
Updates block terminology. |
MindboxTests/InApp/Tests/WebView/BridgeHandlers/InappRequestActionHandlersTests.swift |
Updates in-app request handler tests. |
MindboxTests/InApp/Tests/TimeToDisplayBackgroundTests.swift |
Makes timing tests deterministic. |
MindboxTests/InApp/Tests/InappShowFailureManagerTests.swift |
Tests polymorphic failure payloads. |
MindboxTests/InApp/Tests/InappShowAccountantTests.swift |
Covers centralized show accounting. |
MindboxTests/InApp/Tests/InappSessionManagerTests/InappSessionManagerTests.swift |
Verifies ledger reset. |
MindboxTests/InApp/Tests/InappScheduleManagerTests.swift |
Covers accounting and tap timing. |
MindboxTests/InApp/Tests/InAppCoreManagerTests.swift |
Updates configuration and scheduling stubs. |
MindboxTests/InApp/Tests/InAppConfigurationMapperTests/InappFilterServiceTests/InappPlaceFilterTests.swift |
Adapts place-filter coverage. |
MindboxTests/InApp/Tests/InAppConfigurationMapperTests/InappFilterServiceTests/InappOverlayFilterTests.swift |
Supplies explicit variant selection. |
MindboxTests/InApp/Tests/InAppConfigurationMapperTests/InappFilterServiceTests/InappFilterServiceTests.swift |
Tests event-dependent targeting. |
MindboxTests/InApp/Tests/InAppConfigurationMapperTests/InappFilterServiceTests/EmbeddedFormVariantTests.swift |
Tests place-name trimming. |
MindboxTests/InApp/Tests/InAppConfigurationMapperTests/InappFilterServiceTests/ConfigCandidatesTests.swift |
Updates page-request filtering tests. |
MindboxTests/InApp/Tests/InAppConfigurationManagerTests.swift |
Tests configuration waits and timing. |
MindboxTests/InApp/Tests/InappConfigurationDataFacade/InappConfigurationDataFacadeTests.swift |
Covers failure-buffer discarding. |
MindboxTests/InApp/Tests/InAppConfigResponseTests/InappMapperTests.swift |
Covers pass-level failure handling. |
MindboxTests/InApp/Tests/InAppConfigResponseTests/EmbeddedBlockResolveTests.swift |
Expands page and place targeting coverage. |
MindboxTests/InApp/Tests/InAppConfigResponseTests/ConfigJsonStubs/EmbeddedBlockConfig.json |
Adds targeting and A/B fixtures. |
MindboxTests/InApp/Tests/ForegroundStopwatchTests.swift |
Uses an injectable clock. |
MindboxTests/Extensions/TimeIntervalTimeSpanTests.swift |
Covers delay parsing and formatting. |
MindboxTests/EmbeddedBlocks/MindboxEmbeddedBlockViewTests.swift |
Covers normalization, delays, and timeouts. |
MindboxTests/EmbeddedBlocks/EmbeddedBlockWebViewPageTests.swift |
Updates embedded-page request tests. |
MindboxTests/EmbeddedBlocks/EmbeddedBlockResolverTests.swift |
Covers processing-duration propagation. |
MindboxTests/EmbeddedBlocks/EmbeddedBlockPlaceRegistryTests.swift |
Tests delayed place delivery. |
MindboxTests/EmbeddedBlocks/EmbeddedBlockMocks.swift |
Extends embedded-block test doubles. |
MindboxTests/EmbeddedBlocks/EmbeddedBlockInappServiceTests.swift |
Tests the replacement in-app service. |
MindboxTests/EmbeddedBlocks/EmbeddedBlockDelayedDeliveryTests.swift |
Tests delayed-delivery behavior. |
MindboxTests/EmbeddedBlocks/EmbeddedBlockContentProviderFactoryTests.swift |
Covers unanswered-wait reporting. |
Mindbox/Utilities/TimeInterval+TimeSpan.swift |
Adds delay parsing and padded hours. |
Mindbox/Utilities/SessionTemporaryStorage.swift |
Consolidates session accounting state. |
Mindbox/Utilities/InappSessionLedger.swift |
Defines session-level in-app ledgers. |
Mindbox/InAppMessages/Presentation/Views/WebView/WebViewController.swift |
Shortens overlay reveal animation. |
Mindbox/InAppMessages/Presentation/Views/WebView/Prewarm/InAppWebViewPrewarmPlanner.swift |
Updates embedded-page terminology. |
Mindbox/InAppMessages/Presentation/Views/WebView/Bridge/Handlers/WebBridgeHost.swift |
Renames in-app request hosting. |
Mindbox/InAppMessages/Presentation/Views/WebView/Bridge/Handlers/ShowInAppActionHandler.swift |
Routes requests through the renamed host. |
Mindbox/InAppMessages/Presentation/Views/WebView/Bridge/Handlers/FilterShowableInappsActionHandler.swift |
Routes page filtering requests. |
Mindbox/InAppMessages/Presentation/Views/WebView/Bridge/BridgeMessage.swift |
Updates embedded-page bridge documentation. |
Mindbox/InAppMessages/Models/InAppShowFailure.swift |
Adds polymorphic embedded failures. |
Mindbox/InAppMessages/InAppTargetingChecker/TargetingCheckerTypes/CustomOperationChecker.swift |
Makes operation recording atomic. |
Mindbox/InAppMessages/InappShowFailureManager.swift |
Serializes and emits typed errors. |
Mindbox/InAppMessages/InappShowAccountant.swift |
Centralizes show accounting. |
Mindbox/InAppMessages/InappScheduleManager.swift |
Uses centralized accounting and tap timing. |
Mindbox/InAppMessages/InAppCoreManager.swift |
Delegates failure-buffer completion to mapping. |
Mindbox/InAppMessages/InAppConfigurationMapper/Services/InappFilterService/VariantsFilter.swift |
Trims embedded place names. |
Mindbox/InAppMessages/InAppConfigurationMapper/Services/InappFilterService/InappFilter.swift |
Expands place and page filtering. |
Mindbox/InAppMessages/InAppConfigurationMapper/Services/InAppConfigurationDataFacade.swift |
Exposes failure-buffer lifecycle methods. |
Mindbox/InAppMessages/InAppConfigurationMapper/InappFormBuilder.swift |
Extracts form and image construction. |
Mindbox/InAppMessages/ForegroundStopwatch.swift |
Adds injectable monotonic time. |
Mindbox/InAppMessages/Configuration/InAppConfigurationManager.swift |
Tracks configuration state and processing time. |
Mindbox/InAppMessages/Configuration/API/TargetingModel.swift |
Detects event-dependent targeting. |
Mindbox/EmbeddedBlocks/WebView/EmbeddedBlockWebViewProvider.swift |
Adds timing, accounting, and delayed-content state. |
Mindbox/EmbeddedBlocks/WebView/EmbeddedBlockWebViewPage.swift |
Adopts the renamed bridge protocol. |
Mindbox/EmbeddedBlocks/WebView/EmbeddedBlockPageHosting.swift |
Centralizes callback detachment. |
Mindbox/EmbeddedBlocks/WebView/EmbeddedBlockInappService.swift |
Handles page selection and taps. |
Mindbox/EmbeddedBlocks/WebView/EmbeddedBlockAckBudget.swift |
Tracks foreground-only acknowledgement time. |
Mindbox/EmbeddedBlocks/Resolver/EmbeddedBlockWebContent.swift |
Carries configured delay time. |
Mindbox/EmbeddedBlocks/Resolver/EmbeddedBlockResolver.swift |
Propagates processing duration and delay. |
Mindbox/EmbeddedBlocks/Resolver/EmbeddedBlockPlaceRegistry.swift |
Coordinates delayed place answers. |
Mindbox/EmbeddedBlocks/Resolver/EmbeddedBlockDelayedDelivery.swift |
Implements delayed foreground delivery. |
Mindbox/EmbeddedBlocks/Public/MindboxEmbeddedBlockView.swift |
Normalizes places and reports unanswered waits. |
Mindbox/EmbeddedBlocks/Public/MindboxEmbeddedBlock/MindboxEmbeddedBlock.swift |
Documents SwiftUI place normalization. |
Mindbox/EmbeddedBlocks/Feed/EmbeddedBlockFeedService.swift |
Removes the superseded feed service. |
Mindbox/EmbeddedBlocks/Container/EmbeddedBlockWaitBudget.swift |
Exposes consumed foreground wait time. |
Mindbox/EmbeddedBlocks/Container/EmbeddedBlockContentProviderFactory.swift |
Injects accounting and failure reporting. |
Mindbox/DI/Injections/InjectInappTools.swift |
Registers shared show accounting. |
Mindbox/DI/Injections/InjectEmbeddedBlocks.swift |
Registers new embedded-block services. |
Mindbox.xcodeproj/project.pbxproj |
Adds new sources and tests. |
Review details
- Files reviewed: 70/70 changed files
- Comments generated: 2
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Android has been sending 00:-padded hours in production; iOS now writes the same shape into every Inapp.Show. Parsing gains the delay(fromTimeSpan:) reading the embedded delayTime rides on.
Six independent fields with a hand-maintained erase() become one value the new session resets by a single assignment — nothing to forget.
Inapp.Show, the local show history and the cooldown were settled separately by the overlay and the block; the accountant is the single place now, with a per-place slot so a rebuilt page does not double-count. The stopwatch takes its clock as a seam — timing tests run on a test clock, not on sleeps.
The flat failures list becomes errors of two shapes — inappShowFailure and embeddedBlockShowFailure with placeSystemName, phase and waited — in sync with Android and the server.
Every selection — the trigger's, a place's, a page's — runs as one pass on one queue with a finish that fires exactly once; only a pass that picked nobody sends the refusals it buffered. Form building moves out of the mapper, config place names are trimmed, and the checker's event travels with the pass instead of living in shared state.
selectInappForPlace answers when the config arrives or the 30 s waiter gives up — an early nothing would collapse the block for the screen's whole life. The manager's clock is a seam; getEmbeddedPlaces trims the raw scan the way the selection trims.
filterShowableInapps mirrors the asked ids — order and duplicates included — each answered by the full list's verdict and vouched per offer; showInApp is honored only from a live block.
The fade ran 300 ms after the page had already drawn itself, so every tap on a story paid it on top of the load. 150 ms still hides the composite jump.
The block reports what the overlay reports: Inapp.Show with a timeToDisplay frozen at the moment the page draws, refusals with a phase and the waited budget, a delayTime served once per place, and a show accounted once per place. Pauses hold what they held — the ack budget keeps its remainder, a failure off screen waits until the block is looked at.
justSmK
force-pushed
the
feature/MOBILE-419-inapp-events-parity
branch
from
August 31, 2026 14:49
a897546 to
c476382
Compare
Each dedup was a check and a write as two separate atomic operations: on different queues the pair could straddle the session reset and carry one stale entry into the fresh ledger. The pairs now run inside a single mutate, answering whether the record is news; the answers are pinned by a ledger suite.
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.
Embedded blocks now report in-app events the way Android does: Inapp.Show with a timeToDisplay frozen at the moment the page draws, polymorphic Inapp.ShowFailure with embedded-block reasons, and show accounting deduped per place. mission/stories (#763) is already merged in with its pause semantics kept.
Wire/UX changes worth release notes:
timeToDisplayhours are now zero-padded (0:00:30→00:00:30) in all Inapp.Show — aligned with Android, which has been sending this format in production.minIntervalBetweenShows(Android parity): a story feed on the first screen can suppress overlay in-apps.Note for review: place-name trimming is restored on iOS for now — trim vs exact compare is being settled with Android separately.
https://tracker.yandex.ru/MOBILE-419