Skip to content

Handle inbox schema type propositions + inbox display tracking#419

Open
spoorthipujariadobe wants to merge 5 commits intoadobe:feature/inboxfrom
spoorthipujariadobe:feature/inbox
Open

Handle inbox schema type propositions + inbox display tracking#419
spoorthipujariadobe wants to merge 5 commits intoadobe:feature/inboxfrom
spoorthipujariadobe:feature/inbox

Conversation

@spoorthipujariadobe
Copy link
Contributor

Description

The tracking implementation provides automatic display tracking for inbox propositions while continuing to maintain the separation between UI components (aepcomposeui) and messaging SDK logic (messaging).

Related Issue

Motivation and Context

1. InboxUIState.kt

  • InboxUIState.Success contains a displayed flag backed by Compose's mutableStateOf
  • Each new state instance starts with displayed = false
  • Prevents duplicate tracking on recomposition while allowing tracking for new state instances (e.g., after refresh)

2. InboxEvent.kt

  • New sealed class for inbox container-level events (display, sort, filter, etc.)
  • Currently implements InboxEvent.Display

3. AepInboxEventObserver

  • New interface extending AepUIEventObserver to add inbox-level event handling
  • InboxEventObserver - New implementation that coordinates both inbox and item-level events
  • Accepts vararg item observers (e.g., ContentCardEventObserver) for extensibility
  • Handles inbox events directly (retrieves proposition and tracks display) and delegates item events to registered observers

4. ContentCardMapper.kt

  • Extended to store inbox proposition items in addition to content cards
  • Inbox propositions stored during state creation in MessagingInboxProvider and retrieved during display tracking in InboxEventObserver.

5. AepInbox.kt

  • Updated to accept AepInboxEventObserver (non-optional)
  • Uses LaunchedEffect(Unit) to trigger display tracking once per composition

Data Flow

  1. MessagingInboxProvider creates state
  2. Stores inbox PropositionItem in ContentCardMapper
  3. Returns InboxUIState.Success (with displayed = false)
  4. AepInbox composable displays and checks displayed flag
  5. Calls observer.onInboxEvent(InboxEvent.Display)
  6. InboxEventObserver retrieves PropositionItem from ContentCardMapper
  7. Tracks display event via Messaging SDK
  8. Sets displayed = true

How Has This Been Tested?

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • I have signed the Adobe Open Source CLA.
  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

@codecov
Copy link

codecov bot commented Feb 13, 2026

Comment on lines +59 to +69
override fun onInboxEvent(event: InboxEvent) {
when (event) {
is InboxEvent.Display -> {
val uiState = event.inboxUIState
if (!uiState.displayed) {
ContentCardMapper.instance.getInboxPropositionItem(event.inboxUIState.template.id)
?.track(MessagingEdgeEventType.DISPLAY)
uiState.displayed = true
}
}
}
Copy link

@prudrabhat prudrabhat Mar 2, 2026

Choose a reason for hiding this comment

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

While this inbox tracking approach (uiState.displayed = true inside observer) works, it’s more implicit and couples tracking logic to mutable state living inside the event payload.
Would you be willing to consider the pattern we follow for the cards i.e derive new state (uiState.copy(displayed = true) and publish it via a single owner.

Something to note is that AepUI cards work because each card is an object with internal mutable state (BaseAepUI + updateState), so MessagingEventHandler can safely do:

  1. read event.aepUi.getState()
  2. compute copy
  3. call event.aepUi.updateState(...)

For inbox, there is no equivalent InboxUI object with updateState(...) because state comes from MessagingInboxProvider as a Flow<InboxUIState>. So I am thinking the natural single owner is the MessagingInboxProvider.

Do you think this can work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is the suggestion to have MessagingInboxProvider own the changes to displayed state? It is called by the app developer before the actual display. They might choose to call getInboxUI but never pass the Flow<InboxUIState> to AepInbox composable. So the state needs to be flipped in the LaunchedEffect of AepInbox. But right now, the composable in the UI layer is completely decoupled from the data provider in the Messaging layer so passing the displayed signal from AepInbox to MessagingInboxProvider is not possible.
Thinking more about this, we might not even need the displayed flag if the LaunchedEffect in AepInbox uses the template id i.e activity id as the key since it remains the same across network calls. How about I do away with the flag and its mutation completely?

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