feat(inbox): Visual Notification Inbox overlay (integration / build distribution) - #769
feat(inbox): Visual Notification Inbox overlay (integration / build distribution)#769mahmoud-elmorabea wants to merge 20 commits into
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.97% -3.10%
- Complexity 838 1293 +455
============================================
Files 149 224 +75
Lines 4601 7685 +3084
Branches 628 1234 +606
============================================
+ Hits 3178 5070 +1892
- Misses 1189 2220 +1031
- Partials 234 395 +161 ☔ 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>
|
|
…rity actions (#776) 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>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ 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 84d2989. Configure here.
|
|
#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

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 surface across inbox state, SSE/HTTP ordering, and a new public Compose module; behavior is well-tested but race between SSE and backfill fetch is documented as unresolved.
Overview
Introduces the visual notification inbox end-to-end: a server-driven enablement gate (
X-CIO-Inbox-Enabled), parallel fetch/cache of templates and branding, visibility rules (hidden when not fully renderable—no UI error state), and aVisualInboxfacade over existing headless inbox mutations.messaginginappgainsInboxEventListener(build-time + runtime override),trackMessageClickedoverload withactionValuefor web-parity metrics, delete tombstones so dismissed messages are not resurrected by stale polls, and SSE backfill moved to the serverconnectedevent (foreground no longer firesfetchUserMessagesimmediately). The gist queue reuses its OkHttp client for inbox GETs and triggers template/branding loads on enablement or cache miss.Adds publishable module
messaginginbox: ComposeNotificationInboxOverlay/ bell / list, Jist + Material3 sheet, workspace bell SVG parsing and corner positioning, plus manifestqueriesfor URL resolution. CI lint/unit-test matrices includemessaginginbox; buildSrc pins Jist and new Compose deps.Reviewed by Cursor Bugbot for commit 519032b. Bugbot is set up for automated code reviews on this repo. Configure here.