Skip to content

feat(inbox): Visual Notification Inbox overlay (integration / build distribution)#769

Open
mahmoud-elmorabea wants to merge 12 commits into
mainfrom
feat/overlay-inbox
Open

feat(inbox): Visual Notification Inbox overlay (integration / build distribution)#769
mahmoud-elmorabea wants to merge 12 commits into
mainfrom
feat/overlay-inbox

Conversation

@mahmoud-elmorabea

@mahmoud-elmorabea mahmoud-elmorabea commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Draft integration PR for the Visual Notification Inbox overlay. Opened primarily to publish sample-app builds to Firebase App Distribution so another team can test the feature end-to-end.

Aggregates the already-reviewed sub-PRs: module skeleton, data layer, overlay UI, interaction/web-parity, message actions + branding colors, dismiss-resurrection guard, and sample-app listener demo.

Firebase App Distribution builds (java_layout + kotlin_compose) are posted as a comment on this PR once CI completes.

🤖 Generated with Claude Code


Note

Medium Risk
Large new surface area across queue polling, SSE lifecycle, inbox state, and public Compose APIs, though behavior is heavily unit-tested and failures tend to hide the inbox rather than crash hosts.

Overview
Adds a publishable messaginginbox Compose module (NotificationInboxOverlay, NotificationInboxBell, NotificationInboxView) that renders the visual inbox with Jist, workspace branding-driven chrome, and host InboxEventListener interception for actions.

messaginginapp gains the visual-inbox data layer: server gate via X-CIO-Inbox-Enabled, parallel templates/branding fetch (shared gist HTTP cache + session revalidation), VisualInbox visibility flows, and cio_inbox message selection. Queue polls wire enablement to InboxRepository; SSE transitions now HTTP-backfill before connect so inbox isn’t empty on fresh login. Dismiss tombstones stop deleted messages resurfacing from stale /queue polls; InAppMessagingManager.state exposes reactive store updates.

CI lint/unit matrices include messaginginbox; build adds jist and lifecycle-runtime-compose dependencies.

Reviewed by Cursor Bugbot for commit 3465bce. Bugbot is set up for automated code reviews on this repo. Configure here.

mahmoud-elmorabea and others added 9 commits July 3, 2026 17:22
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…, selection) (#744)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…747)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tes, no-template skip, hovering panel) (#751)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…e, desugaring docs) (#752)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… poll (#758)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown

Sample app builds 📱

Below you will find the list of the latest versions of the sample apps. It's recommended to always download the latest builds of the sample apps to accurately test the pull request.


@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
  • java_layout: Build failed. See CI job logs to determine the issue and try re-building.

@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
  • kotlin_compose: Build failed. See CI job logs to determine the issue and try re-building.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 50.50167% with 444 lines in your changes missing coverage. Please review.
✅ Project coverage is 65.40%. Comparing base (b5cf24d) to head (3465bce).
⚠️ Report is 25 commits behind head on main.

Files with missing lines Patch % Lines
...ustomer/messaginginbox/NotificationInboxOverlay.kt 0.00% 290 Missing ⚠️
...customer/messaginginbox/VisualInboxOverlayState.kt 77.94% 15 Missing and 15 partials ⚠️
...tomer/messaginginapp/inbox/data/InboxRepository.kt 78.35% 9 Missing and 20 partials ⚠️
.../io/customer/messaginginapp/inbox/data/InboxApi.kt 34.14% 26 Missing and 1 partial ⚠️
...va/io/customer/messaginginapp/inbox/VisualInbox.kt 0.00% 24 Missing ⚠️
...ava/io/customer/messaginginbox/InboxJistDecoder.kt 66.10% 9 Missing and 11 partials ⚠️
...stomer/messaginginapp/gist/data/listeners/Queue.kt 72.41% 5 Missing and 3 partials ⚠️
...ustomer/messaginginapp/di/DIGraphMessagingInApp.kt 14.28% 6 Missing ⚠️
...io/customer/messaginginapp/ModuleMessagingInApp.kt 25.00% 3 Missing ⚠️
...customer/messaginginapp/type/InboxEventListener.kt 0.00% 3 Missing ⚠️
... and 3 more
Additional details and impacted files
@@             Coverage Diff              @@
##               main     #769      +/-   ##
============================================
- Coverage     69.07%   65.40%   -3.67%     
- Complexity      838     1020     +182     
============================================
  Files           149      173      +24     
  Lines          4601     5851    +1250     
  Branches        628      878     +250     
============================================
+ Hits           3178     3827     +649     
- Misses         1189     1719     +530     
- Partials        234      305      +71     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
  • kotlin_compose: feat/overlay-inbox (1783341984)

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
  • java_layout: feat/overlay-inbox (1783341976)

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

📏 SDK Binary Size Comparison Report

Module Last Recorded Size Current Size Change in Size
core 33.61 KB 33.61 KB ✅ No Change
datapipelines 42.43 KB 42.43 KB ✅ No Change
messagingpush 31.67 KB 31.67 KB ✅ No Change
messaginginapp 123.88 KB 147.50 KB ⬆️ +23.62KB
messaginginbox null 42.39 KB ⬆️ +42.39KB
tracking-migration 22.89 KB 22.89 KB ✅ No Change

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown

Build available to test
Version: feat-overlay-inbox-SNAPSHOT
Repository: https://central.sonatype.com/repository/maven-snapshots/

@mahmoud-elmorabea mahmoud-elmorabea marked this pull request as ready for review July 6, 2026 13:03
@mahmoud-elmorabea mahmoud-elmorabea requested a review from a team as a code owner July 6, 2026 13:03
) {
val context = LocalContext.current
val state by remember(controller) { controller.uiStateFlow() }
.collectAsStateWithLifecycle(initialValue = VisualInboxUiState(loading = true))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Duplicate inbox state collectors

Medium Severity

InboxListContent calls controller.uiStateFlow() and collects it separately from parent composables that already collect the same controller’s flow. Each call builds a new cold flow whose onStart triggers another load() (templates/branding fetch path), so one mounted overlay or view can run parallel load pipelines and briefly surface inconsistent UI snapshots.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit e65c84c. Configure here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Partially valid — the mechanism is real but the stated impact is guarded.

uiStateFlow() is a cold flow, and both the parent (NotificationInboxView/NotificationInboxOverlay) and the child InboxListContent collect it, so mounting does start two collections that each hit load() via .onStart. However, InboxRepository.loadTemplatesAndBranding() prevents the parallel load pipelines described here: an atomic in-flight guard (fetchInFlight.compareAndSet(false, true) → early return with current state) plus a once-per-session revalidation gate mean a second concurrent load short-circuits with no extra network fetch.

So the residual cost is redundant flow collection (two subscriptions + snapshot reads), not parallel fetches or divergent UI. Worth a low-priority cleanup (hoist/share a single collection), not a correctness bug.

…pty inbox) (#771)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(16.dp)
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Overlay bell ignores renderable gate

Low Severity

NotificationInboxOverlay keeps composing InboxBellContent whenever the overlay stays mounted for panelExpanded, even when canShowChrome is false (inbox hidden or no renderable messages). NotificationInboxBell hides the bell in that case, but the overlay can still show a floating bell with nothing valid to open.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 138e675. Configure here.

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
  • java_layout: feat/overlay-inbox (1783353755)

@github-actions

github-actions Bot commented Jul 6, 2026

Copy link
Copy Markdown
  • kotlin_compose: feat/overlay-inbox (1783353743)

…EventListener (#772)

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 3465bce. Configure here.

* after running its (non-dismiss) action. Matches both a JSON boolean `true` and the string `"true"`.
*/
private fun actionDismissFlag(event: JistActionEvent): Boolean =
((event.data as? JsonObject)?.get("dismiss") as? JsonPrimitive)?.contentOrNull == "true"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Dismiss flag ignores JSON boolean

Medium Severity

actionDismissFlag treats data.dismiss as enabled only when JsonPrimitive.contentOrNull equals the string "true". For a normal JSON boolean true, contentOrNull is null in kotlinx.serialization, so auto-dismiss-after-click never runs even though the comment claims boolean and string forms are supported.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 3465bce. Configure here.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
  • java_layout: feat/overlay-inbox (1783429189)

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
  • kotlin_compose: feat/overlay-inbox (1783429180)

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.

1 participant