[MSDK-3955] Expose ConsentOrPay settings in React Native bridge for P…#212
Conversation
|
CodeAnt AI is reviewing your PR. Thanks for using CodeAnt! 🎉We're free for open-source projects. if you're enjoying it, help us grow by sharing. Share on X · |
📝 WalkthroughWalkthroughThis PR adds support for a "consent or pay" configuration feature across the TCF2 settings model. A new ChangesTCF2 Consent-or-Pay Configuration
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
src/models/TCF2Settings.tsxOops! Something went wrong! :( ESLint: 8.57.1 TypeError: prettier.resolveConfig.sync is not a function Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Review Summary by QodoExpose ConsentOrPay settings in React Native bridge
WalkthroughsDescription• Expose ConsentOrPay settings in React Native bridge • Add serialization for ConsentOrPaySettings on Android • Add dictionary conversion for ConsentOrPaySettings on iOS • Create TypeScript model for TCF2ConsentOrPaySettings Diagramflowchart LR
A["ConsentOrPaySettings<br/>Native Models"] -->|"Serialize"| B["Android<br/>WritableMap"]
A -->|"Convert"| C["iOS<br/>Dictionary"]
B -->|"Bridge"| D["React Native<br/>TypeScript Models"]
C -->|"Bridge"| D
D -->|"Expose"| E["TCF2ConsentOrPaySettings<br/>Class"]
File Changes1. android/src/main/java/com/usercentrics/reactnative/extensions/UsercentricsCMPDataExtensions.kt
|
Code Review by Qodo
1. Unbridged consentOrPay maps
|
|
PR Summary: Add ConsentOrPay settings to the React Native bridge so JS can read them from CMP settings.
Impact and notes
|
There was a problem hiding this comment.
🧹 Nitpick comments (1)
ios/Extensions/UsercentricsCMPData+Dict.swift (1)
244-253: 💤 Low valueConsider using
NSDictionaryas return type for consistency.Most other
toDictionary()extensions in this file returnNSDictionary(e.g.,TCF2Settings.toDictionary()at line 177,CCPASettings.toDictionary()at line 153). This extension returns[String: Any], which is functionally equivalent since it's cast toAnyat the call site (line 239), but the inconsistency might confuse future maintainers.♻️ Optional refactor for consistency
extension ConsentOrPaySettings { - func toDictionary() -> [String: Any] { + func toDictionary() -> NSDictionary { return [ "enableConsentOrPay": self.enableConsentOrPay, "showTogglesForVendors": self.showTogglesForVendors, "publisherRestrictions": self.publisherRestrictions, "specialFeatures": self.specialFeatures ] } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@ios/Extensions/UsercentricsCMPData`+Dict.swift around lines 244 - 253, Change ConsentOrPaySettings.toDictionary() to return NSDictionary for consistency with other extensions; update the signature to func toDictionary() -> NSDictionary and return an NSDictionary instance (either by constructing NSDictionary with the same key/value pairs or by casting the literal to NSDictionary) so callers and other toDictionary() implementations (e.g., TCF2Settings.toDictionary, CCPASettings.toDictionary) use the same type.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@ios/Extensions/UsercentricsCMPData`+Dict.swift:
- Around line 244-253: Change ConsentOrPaySettings.toDictionary() to return
NSDictionary for consistency with other extensions; update the signature to func
toDictionary() -> NSDictionary and return an NSDictionary instance (either by
constructing NSDictionary with the same key/value pairs or by casting the
literal to NSDictionary) so callers and other toDictionary() implementations
(e.g., TCF2Settings.toDictionary, CCPASettings.toDictionary) use the same type.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 299aeff8-a7db-4fef-952c-52eee10a0768
📒 Files selected for processing (3)
android/src/main/java/com/usercentrics/reactnative/extensions/UsercentricsCMPDataExtensions.ktios/Extensions/UsercentricsCMPData+Dict.swiftsrc/models/TCF2Settings.tsx
|
Reviewed up to commit:20c2e3ea766c19069cef61bc60e50fb7bb62bb37 Additional Suggestionsrc/models/TCF2Settings.tsx, line:214-234Consider tightening the types for publisherRestrictions and specialFeatures in TCF2ConsentOrPaySettings (lines 214-234). Right now they're Record. If the value can only be the literal 'flexible' (per comment), use a more precise type like Record or an enum/union. That improves type-safety across the codebase and makes platform serializers clearer about permitted values.export class TCF2ConsentOrPaySettings {
enableConsentOrPay: boolean
showTogglesForVendors: boolean
/** Maps TCF Purpose ID (as string) to "flexible". Absent entries are mandatory. */
publisherRestrictions: Record<string, "flexible">
/** Maps Special Feature ID (as string) to "flexible". Absent entries are mandatory. */
specialFeatures: Record<string, "flexible">
constructor(
enableConsentOrPay: boolean,
showTogglesForVendors: boolean,
publisherRestrictions: Record<string, "flexible">,
specialFeatures: Record<string, "flexible">,
) {
this.enableConsentOrPay = enableConsentOrPay
this.showTogglesForVendors = showTogglesForVendors
this.publisherRestrictions = publisherRestrictions
this.specialFeatures = specialFeatures
}
}Others- Update Android unit tests/mocks that construct expected TCF2Settings objects and TCF data (e.g. GetCMPDataMock.kt expectedTCF2Settings around lines 448-509 and any TCF mock builders) to include the new consentOrPay structure (or cover null case). Without updating tests, CI will fail or the new field will be unexpectedly missing from assertions.// android/src/androidTest/java/com/usercentrics/reactnative/mock/GetCMPDataMock.kt
private val expectedTCF2Settings = hashMapOf(
// ...existing expectations...
"scope" to 1,
"changedPurposes" to mapOf(
"purposes" to listOf(1, 2, 3),
"legIntPurposes" to listOf(1, 2, 3),
),
// new field: consentOrPay
"consentOrPay" to mapOf(
"enableConsentOrPay" to false,
"showTogglesForVendors" to false,
"publisherRestrictions" to emptyMap<String, String>(),
"specialFeatures" to emptyMap<String, String>(),
),
)
extension TCF2Settings {
static func mock() -> TCF2Settings {
let consentOrPay = ConsentOrPaySettings(
enableConsentOrPay: KotlinBoolean(bool: true),
showTogglesForVendors: KotlinBoolean(bool: false),
publisherRestrictions: ["1": "flexible", "2": "flexible"],
specialFeatures: ["1": "flexible"]
)
return .init(
firstLayerTitle: "firstLayerTitle",
secondLayerTitle: "secondLayerTitle",
tabsPurposeLabel: "tabsPurposeLabel",
tabsVendorsLabel: "tabsVendorsLabel",
labelsFeatures: "labelsFeatures",
labelsIabVendors: "labelsIabVendors",
labelsNonIabPurposes: "labelsNonIabPurposes",
labelsNonIabVendors: "labelsNonIabVendors",
labelsPurposes: "labelsPurposes",
vendorFeatures: "vendorFeatures",
vendorLegitimateInterestPurposes: "vendorLegitimateInterestPurposes",
vendorPurpose: "vendorPurpose",
vendorSpecialFeatures: "vendorSpecialFeatures",
vendorSpecialPurposes: "vendorSpecialPurposes",
togglesConsentToggleLabel: "togglesConsentToggleLabel",
togglesLegIntToggleLabel: "togglesLegIntToggleLabel",
buttonsAcceptAllLabel: "buttonsAcceptAllLabel",
buttonsDenyAllLabel: "buttonsDenyAllLabel",
buttonsSaveLabel: "buttonsSaveLabel",
linksManageSettingsLabel: "linksManageSettingsLabel",
linksVendorListLinkLabel: "linksVendorListLinkLabel",
togglesSpecialFeaturesToggleOn: "togglesSpecialFeaturesToggleOn",
togglesSpecialFeaturesToggleOff: "togglesSpecialFeaturesToggleOff",
firstLayerMobileVariant: .full,
firstLayerHideToggles: true,
secondLayerHideToggles: true,
hideLegitimateInterestToggles: true,
categoriesOfDataLabel: "categoriesOfDataLabel",
dataRetentionPeriodLabel: "dataRetentionPeriodLabel",
legitimateInterestLabel: "legitimateInterestLabel",
version: "version",
examplesLabel: "examplesLabel",
cmpId: 123,
cmpVersion: 123,
showDataSharedOutsideEUText: true,
dataSharedOutsideEUText: "dataSharedOutsideEUText",
vendorIdsOutsideEUList: [1,2,3],
firstLayerHideButtonDeny: true,
hideButtonManageSettings: false,
secondLayerHideButtonDeny: true,
publisherCountryCode: "publisherCountryCode",
purposeOneTreatment: true,
selectedVendorIds: [1,2,3],
gdprApplies: true,
selectedStacks: [1,2,3],
scope: .global,
disabledSpecialFeatures: [1,2,3],
firstLayerShowDescriptions: true,
hideNonIabOnFirstLayer: true,
resurfacePeriod: 1,
resurfacePurposeChanged: true,
resurfaceVendorAdded: true,
firstLayerDescription: "firstLayerDescription",
firstLayerAdditionalInfo: "firstLayerAdditionalInfo",
secondLayerDescription: "secondLayerDescription",
appLayerNoteResurface: "appLayerNoteResurface",
firstLayerNoteResurface: "firstLayerNoteResurface",
changedPurposes: .mock(),
acmV2Enabled: true,
selectedATPIds: [43,46,55],
resurfaceATPListChanged: false,
atpListTitle: "Google Providers",
consentOrPay: consentOrPay
)
}
} |
CI Feedback 🧐A test triggered by this PR failed. Here is an AI-generated analysis of the failure:
|
|
CodeAnt AI finished reviewing your PR. |
User description
Summary by CodeRabbit
CodeAnt-AI Description
Expose Consent or Pay settings in React Native TCF2 data
What Changed
Impact
✅ Consistent Consent or Pay setup across iOS and Android✅ Fewer missing CMP settings in React Native apps✅ Clearer control over vendor and special feature display💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.