Skip to content

MOBILE-419: Send in-app events for embedded blocks in parity with Android - #765

Merged
justSmK merged 10 commits into
mission/storiesfrom
feature/MOBILE-419-inapp-events-parity
Sep 1, 2026
Merged

MOBILE-419: Send in-app events for embedded blocks in parity with Android#765
justSmK merged 10 commits into
mission/storiesfrom
feature/MOBILE-419-inapp-events-parity

Conversation

@justSmK

@justSmK justSmK commented Aug 31, 2026

Copy link
Copy Markdown
Collaborator

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:

  • timeToDisplay hours are now zero-padded (0:00:3000:00:30) in all Inapp.Show — aligned with Android, which has been sending this format in production.
  • A block's show now advances minIntervalBetweenShows (Android parity): a story feed on the first screen can suppress overlay in-apps.
  • The overlay window reveal after the page's init is halved (300 → 150 ms) — every story tap paid it on top of the load.

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

@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor
TestsPassed ✅SkippedFailedTime ⏱
Unit tests report2122 ran2122 ✅2m 10s 753ms

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 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.

Comment thread Mindbox/InAppMessages/InAppConfigurationMapper/InappFormBuilder.swift Outdated
Comment thread Mindbox/InAppMessages/Configuration/InAppConfigurationManager.swift
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
justSmK force-pushed the feature/MOBILE-419-inapp-events-parity branch from a897546 to c476382 Compare August 31, 2026 14:49
@justSmK
justSmK requested a review from Vailence August 31, 2026 15:15
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.
@justSmK
justSmK merged commit 1e84ce5 into mission/stories Sep 1, 2026
4 checks passed
@justSmK
justSmK deleted the feature/MOBILE-419-inapp-events-parity branch September 1, 2026 09:03
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