Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.usercentrics.sdk.v2.settings.data.CustomizationFont
import com.usercentrics.sdk.v2.settings.data.FirstLayer
import com.usercentrics.sdk.v2.settings.data.PublishedApp
import com.usercentrics.sdk.v2.settings.data.SecondLayer
import com.usercentrics.sdk.v2.settings.data.ConsentOrPayRestriction
import com.usercentrics.sdk.v2.settings.data.ConsentOrPaySettings
import com.usercentrics.sdk.v2.settings.data.TCF2ChangedPurposes
import com.usercentrics.sdk.v2.settings.data.TCF2Settings
Expand Down Expand Up @@ -249,6 +250,7 @@ private fun TCF2Settings.serialize(): WritableMap {
"selectedATPIds" to selectedATPIds,
"consentOrPay" to consentOrPay?.serialize(),
"mandatoryLabel" to mandatoryLabel,
"specialFeaturesConsentOrPay" to specialFeaturesConsentOrPay?.map { it.serialize() },
).toWritableMap()
}

Expand Down Expand Up @@ -447,10 +449,16 @@ private fun TCF2ChangedPurposes?.serialize(): Any? {
}
return mapOf(
"purposes" to purposes,
"legIntPurposes" to legIntPurposes
"legIntPurposes" to legIntPurposes,
"consentOrPay" to consentOrPay?.map { it.serialize() },
)
}

private fun ConsentOrPayRestriction.serialize(): Map<String, Any?> = mapOf(
"id" to id,
"value" to value,
)
Comment on lines +457 to +460
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[VALIDATION] ConsentOrPayRestriction.serialize() returns id and value directly. Ensure the SDK's ConsentOrPayRestriction.value is a JSON-friendly type (String). If the SDK defines value as an enum, explicitly serialize it to a string (e.g. value.name or value.toString().uppercase()) so the JS side receives the expected 'FLEXIBLE'|'MANDATORY' strings. Also consider normalizing casing (uppercase) to match the TypeScript expectation.

private fun ConsentOrPayRestriction.serialize(): Map<String, Any?> = mapOf(
    "id" to id,
    "value" to value.toString().uppercase(),
)


internal fun AdditionalConsentModeData.serialize(): WritableMap {
return Arguments.createMap().apply {
putString("acString", acString)
Expand Down
13 changes: 12 additions & 1 deletion ios/Extensions/UsercentricsCMPData+Dict.swift
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,7 @@ extension TCF2Settings {
"resurfacePeriod": self.resurfacePeriod,
"consentOrPay": self.consentOrPay?.toDictionary() as Any,
"mandatoryLabel": self.mandatoryLabel,
"specialFeaturesConsentOrPay": self.specialFeaturesConsentOrPay?.map { $0.toDictionary() } as Any,
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[REFACTORING] You added "specialFeaturesConsentOrPay": self.specialFeaturesConsentOrPay?.map { $0.toDictionary() } as Any. Ensure the resulting array elements are JSON-serializable types (String/Int/Bool/NSDictionary). If ConsentOrPayRestriction.value is an enum on the native SDK, convert it to rawValue or String(describing:) in toDictionary() so the JS bridge receives plain strings (matching the TS 'FLEXIBLE'|'MANDATORY' expectation).

extension ConsentOrPayRestriction {
    func toDictionary() -> [String: Any] {
        return [
            "id": self.id,
            "value": (self.value as? CustomStringConvertible)?.description ?? String(describing: self.value),
        ]
    }
}

]
}
}
Expand Down Expand Up @@ -497,7 +498,17 @@ extension TCF2ChangedPurposes {
func toDictionary() -> Any {
return [
"purposes": purposes,
"legIntPurposes": legIntPurposes
"legIntPurposes": legIntPurposes,
"consentOrPay": consentOrPay?.map { $0.toDictionary() } as Any,
]
}
}

extension ConsentOrPayRestriction {
func toDictionary() -> [String: Any] {
return [
"id": self.id,
"value": self.value,
]
}
}
Expand Down
20 changes: 20 additions & 0 deletions src/models/TCF2Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ export class TCF2Settings {
selectedATPIds: number[]
consentOrPay?: TCF2ConsentOrPaySettings
mandatoryLabel: string
specialFeaturesConsentOrPay?: ConsentOrPayRestriction[]
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

[REFACTORING] You introduced specialFeaturesConsentOrPay?: ConsentOrPayRestriction[] and the ConsentOrPayRestriction class with value: string. For stronger type-safety, change the value type to a string literal union: value: 'FLEXIBLE' | 'MANDATORY'. This prevents invalid values being created in TypeScript consumers. Also remove the unnecessary optional-chaining in isFlexible(): use return this.value.toUpperCase() === 'FLEXIBLE' (value is non-nullable if typed as the union).

export class ConsentOrPayRestriction {
    id: number
    value: 'FLEXIBLE' | 'MANDATORY'

    constructor(id: number, value: 'FLEXIBLE' | 'MANDATORY') {
        this.id = id
        this.value = value
    }

    isFlexible(): boolean {
        return this.value.toUpperCase() === 'FLEXIBLE'
    }
}


constructor(
firstLayerTitle: string,
Expand Down Expand Up @@ -123,6 +124,7 @@ export class TCF2Settings {
dataSharedOutsideEUText?: string,
consentOrPay?: TCF2ConsentOrPaySettings,
mandatoryLabel: string = 'Mandatory',
specialFeaturesConsentOrPay?: ConsentOrPayRestriction[],
) {
this.firstLayerTitle = firstLayerTitle
this.secondLayerTitle = secondLayerTitle
Expand Down Expand Up @@ -185,6 +187,7 @@ export class TCF2Settings {
this.selectedATPIds = selectedATPIds
this.consentOrPay = consentOrPay
this.mandatoryLabel = mandatoryLabel
this.specialFeaturesConsentOrPay = specialFeaturesConsentOrPay
}
}

Expand All @@ -204,13 +207,30 @@ export class TCF2ChangedPurposes {

purposes: [number]
legIntPurposes: [number]
consentOrPay?: ConsentOrPayRestriction[]

constructor(
purposes: [number],
legIntPurposes: [number],
consentOrPay?: ConsentOrPayRestriction[],
) {
this.purposes = purposes
this.legIntPurposes = legIntPurposes
this.consentOrPay = consentOrPay
}
}

export class ConsentOrPayRestriction {
id: number
value: string

constructor(id: number, value: string) {
this.id = id
this.value = value
}

isFlexible(): boolean {
return this.value?.toUpperCase() === 'FLEXIBLE'
}
}

Expand Down
Loading