feat: UserAttributeListener onboarding and BaseAttributeListener for kits#688
feat: UserAttributeListener onboarding and BaseAttributeListener for kits#688denischilik wants to merge 10 commits intoworkstation/6.0-Releasefrom
Conversation
Introduce KitIntegration.BaseAttributeListener as the common superinterface for AttributeListener and UserAttributeListener. Document it as a temporary contract to enable incremental migration and smaller PRs. Made-with: Cursor
Resolve via BaseAttributeListener before AttributeListener/UserAttributeListener branches in onUserAttributesReceived and setUserAttribute(list). Made-with: Cursor
UserAttributeListener.onRemoveUserAttribute now forwards to the existing AttributeListener.removeUserAttribute implementation for braze-38 through braze-41. Made-with: Cursor
Declare onRemoveUserAttribute on KitIntegration.BaseAttributeListener so AttributeListener and UserAttributeListener implementors must implement it. KitManagerImpl now dispatches removal once via BaseAttributeListener. AttributeListener-only kits delegate onRemoveUserAttribute to removeUserAttribute; AttributeListenerTestKit updated accordingly. Made-with: Cursor
Drop void removeUserAttribute(String) from KitIntegration.AttributeListener. Kits keep the same logic as private-style helpers (fun removeUserAttribute without override) and still satisfy BaseAttributeListener via onRemoveUserAttribute. AdobeKitBase implements onRemoveUserAttribute by delegating to removeUserAttribute. Made-with: Cursor
Move kit-specific handling from removed helper methods into BaseAttributeListener.onRemoveUserAttribute implementations. Rename AttributeListenerTestKit callback to removeUserAttributeListener. Fix Braze custom-key branch for Kotlin smart-cast in Braze callback. Made-with: Cursor
Document intentional empty overrides in Adobe, AppsFlyer, Branch, Braze, and Kochava kits to satisfy SonarQube analysis. Made-with: Cursor
Made-with: Cursor
Replace if/else chain with when for standard vs custom user attribute removal; behavior unchanged across braze 38-41 kits. Made-with: Cursor
…arams, naming) - SingularKit: key/value/user naming, null checks for Java interop - AppsFlyerKit, Braze AppboyKit: consistent UserAttributeListener overrides Made-with: Cursor
PR SummaryMedium Risk Overview Updates forwarding logic in Migrates kits and tests to the new callbacks. Multiple kits now implement Written by Cursor Bugbot for commit 643c563. This will update automatically on new commits. Configure here. |
|
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
| if (key == null || value == null || value !is String) { | ||
| return | ||
| } | ||
| setUserAttribute(key, value) |
There was a problem hiding this comment.
Double user attribute dispatch for dual-interface kits
High Severity
For kits implementing both AttributeListener and UserAttributeListener (Braze, Singular), KitManagerImpl.setUserAttribute dispatches through both AttributeListener.setUserAttribute() and UserAttributeListener.onSetUserAttribute(). Previously onSetUserAttribute was a no-op, but it now delegates to setUserAttribute(), causing every user attribute to be set twice on the downstream SDK. This doubles Braze API calls and fires duplicate Singular events for AGE/GENDER attributes. The same issue applies to all four Braze kit versions (38–41).




Background
Aligns kit code with
UserAttributeListenerandBaseAttributeListenerso user-attribute handling uses the non-deprecated entry points (onSetUserAttribute,onRemoveUserAttribute) and sharedsupportsAttributeLists()behavior from kit-base.What Has Changed
BaseAttributeListenerand routessupportsAttributeLists()through kit-base (KitManagerImpl) once per providerremoveUserAttributefromAttributeListener; kits implement removal viaonRemoveUserAttribute(with kit-specific helpers where needed)onSetUserAttribute/onRemoveUserAttributesignatures and null-safe Java interopScreenshots/Video
N/A
Checklist
Additional Notes
Merge base:
feat/remove-attribute-listener(stacked PR).