feat: Visual Notification Inbox overlay (integration / build distribution) - #769
Conversation
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>
9205f46 to
ed05fb5
Compare
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. |
|
|
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #769 +/- ##
============================================
- Coverage 69.07% 65.93% -3.14%
- Complexity 838 1513 +675
============================================
Files 149 245 +96
Lines 4601 8617 +4016
Branches 628 1408 +780
============================================
+ Hits 3178 5682 +2504
- Misses 1189 2481 +1292
- Partials 234 454 +220 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
|
📏 SDK Binary Size Comparison Report
|
|
Build available to test |
…pty inbox) (#771) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
…EventListener (#772) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
…nts (#782) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
|
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Resolves the four conflicts, all caused by geofencing (#763) registering a new module in the same lists the inbox module uses. Each takes the union of both sides rather than either one: - settings.gradle: keep include ':geofence' alongside the note explaining why :messaginginbox needs no local include (it consumes Jist from Maven Central). - scripts/sdk-binary-size.gradle, lint.yml, test.yml: module lists now carry messaginginbox plus location and geofence. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
#800) Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
|
| */ | ||
| private fun backfillOnConnect() { | ||
| sseLogger.logSseConnectionConfirmedBackfill() | ||
| gistQueue.fetchUserMessages() |
There was a problem hiding this comment.
Could we track a follow-up to prevent the HTTP backfill from overwriting newer inbox state received through SSE? If an SSE update arrives while the backfill request is still running, the older HTTP response can replace it, and the inbox may stay stale until another SSE event or reconnect. I don’t think this needs to block this PR, but linking the follow-up here would make the remaining limitation clear.
There was a problem hiding this comment.
The window is too narrow and it exceptionally unlikely that these two responses have different messages. I suggest we take as a follow up to sequence the two calls or have some kind of logic to merge them
| if (inAppMessagingManager.getCurrentState().sessionId == sessionAtFetchStart && hasServableAssets) { | ||
| hasRevalidatedAssetsThisSession.set(true) | ||
| } else if (!hasServableAssets) { | ||
| logger.debug("$LOG_TAG revalidation produced nothing servable: gate stays open for the next poll") |
There was a problem hiding this comment.
This looks non-blocking and could be followed up separately. If the initial asset fetch exhausts its retries while SSE remains connected, there is no independent retry, so the inbox can stay hidden until a later lifecycle or connection event. Could we track that follow-up?
There was a problem hiding this comment.
Sure, what do you suggest? I don't think we should keep retrying for the entire session or maybe only if its network related issue
| // User became identified and SSE is enabled - start SSE connection | ||
| sseLogger.logEnablingSseForIdentifiedUser() | ||
| sseConnectionManager.startConnection() | ||
| startSseConnection() |
There was a problem hiding this comment.
Could we handle a direct switch from one identified user to another by observing the actual user ID, clearing the previous inbox state, and reconnecting SSE? For A → B, isUserIdentified stays true, so this callback never runs. The existing stream remains authenticated as A while the SDK treats B as current, and later events from A can replace B’s inbox state. Since this can expose one user’s inbox to another, I think it should block the release. A focused A → B test would help cover the fix.
There was a problem hiding this comment.
I think this is the whole of in-app, not just inbox. Maybe if we want to formally support that login while a user already logged in path we could. I suggest handling that as a follow up as well
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 2 potential issues.
❌ 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 8576d0f. Configure here.
|
|

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
Touches in-app messaging state, queue/SSE sync, and new public Compose APIs; behavior is heavily unit-tested but race between HTTP backfill and SSE inbox updates is documented as a known gap.
Overview
Introduces the Visual Notification Inbox end-to-end: a new
messaginginboxlibrary with Compose entry points (NotificationInboxOverlay,NotificationInboxBell,NotificationInboxView) that render messages via Jist and workspace branding (floating bell SVG, position, chrome).messaginginappgains the data layer:VisualInbox/InboxRepositoryfetch and cache/api/v1/templatesand/api/v1/branding, gate visibility onX-CIO-Inbox-Enabled, and expose reactive flows for the overlay. Host apps can registerInboxEventListener(build-time or runtime viasetInboxEventListener) to intercept inbox actions. Inbox click metrics now includeactionValue(new overload for binary compatibility). Dismiss tombstones stop deleted messages from reappearing on stale queue polls.SSE no longer calls
fetchUserMessages()on foreground alone; backfill runs once the server sendsconnected, matching gist-web and fixing empty inbox on fresh login. CI matrices addmessaginginbox; build deps add jist, Material3, and lifecycle-runtime-compose.Reviewed by Cursor Bugbot for commit 8576d0f. Bugbot is set up for automated code reviews on this repo. Configure here.