@kontextso/sdk-react-native 3.3.0-rc.1 → 3.3.0-rc.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -17,39 +17,38 @@ class RNKontextModuleImpl(private val reactContext: ReactApplicationContext) {
17
17
  promise?.resolve(volume > MINIMAL_VOLUME_THRESHOLD)
18
18
  }
19
19
 
20
- fun getTcfData(promise: Promise) {
20
+ fun getTcfData(promise: Promise?) {
21
+ if (promise == null) return
22
+
21
23
  try {
22
24
  val prefs = PreferenceManager.getDefaultSharedPreferences(reactContext.applicationContext)
23
- val all = prefs.all
24
25
 
25
- val out = HashMap<String, Any?>(32)
26
+ val tcString: String? = prefs.getString("IABTCF_TCString", null)
27
+
28
+ // gdprApplies is usually stored as Int, but some CMPs could store it as String
29
+ val gdprApplies: Int? = run {
30
+ val all = prefs.all
31
+ val raw = all["IABTCF_gdprApplies"] ?: return@run null
26
32
 
27
- for ((key, value) in all) {
28
- if (!key.startsWith("IABTCF_")) continue
29
- out[key] = normalizeForReactNative(value)
33
+ when (raw) {
34
+ is Int -> raw
35
+ is Long -> raw.toInt()
36
+ is Boolean -> if (raw) 1 else 0
37
+ is String -> raw.toIntOrNull()
38
+ is Number -> raw.toInt()
39
+ else -> null
40
+ }
30
41
  }
31
42
 
32
- // Promise.resolve accepts Map<String, Any?> and RN will bridge it to JS object
43
+ val out = HashMap<String, Any?>(2)
44
+ out["tcString"] = tcString
45
+ out["gdprApplies"] = gdprApplies
46
+
33
47
  promise.resolve(out)
34
48
  } catch (t: Throwable) {
35
- promise.reject("TCF_ERROR", "Failed to read IABTCF_* from SharedPreferences", t)
49
+ promise.reject("TCF_ERROR", "Failed to read IABTCF TC data from SharedPreferences", t)
36
50
  }
37
51
  }
38
-
39
- private fun normalizeForReactNative(value: Any?): Any? {
40
- return when (value) {
41
- null -> null
42
- is String -> value
43
- is Boolean -> value
44
- is Int -> value
45
- is Long -> value
46
- is Float -> value
47
- is Double -> value
48
- is Number -> value
49
- else -> value.toString() // extremely rare, but avoids crashing bridge
50
- }
51
- }
52
-
53
52
 
54
53
  companion object {
55
54
  private const val MINIMAL_VOLUME_THRESHOLD = 0.0f
package/dist/index.js CHANGED
@@ -662,7 +662,7 @@ var import_react_native5 = require("react-native");
662
662
  var import_react_native_device_info = __toESM(require("react-native-device-info"));
663
663
 
664
664
  // package.json
665
- var version = "3.2.2";
665
+ var version = "3.3.0-rc.3";
666
666
 
667
667
  // src/context/AdsProvider.tsx
668
668
  var import_jsx_runtime4 = require("react/jsx-runtime");
@@ -763,8 +763,20 @@ var getSdk = async () => ({
763
763
  platform: import_react_native5.Platform.OS === "ios" ? "ios" : "android",
764
764
  version
765
765
  });
766
+ var getTcf = async () => {
767
+ try {
768
+ const tcfData = await NativeRNKontext_default.getTcfData();
769
+ return {
770
+ gdpr: tcfData.gdprApplies,
771
+ gdprConsent: tcfData.tcString
772
+ };
773
+ } catch (error) {
774
+ console.error(error);
775
+ return {};
776
+ }
777
+ };
766
778
  var AdsProvider = (props) => {
767
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_sdk_react2.AdsProviderInternal, { ...props, getDevice, getSdk, getApp });
779
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_sdk_react2.AdsProviderInternal, { ...props, getDevice, getSdk, getApp, getTcf });
768
780
  };
769
781
  // Annotate the CommonJS export names for ESM import in node:
770
782
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -634,7 +634,7 @@ import { Appearance, Dimensions, PixelRatio, Platform as Platform3 } from "react
634
634
  import DeviceInfo from "react-native-device-info";
635
635
 
636
636
  // package.json
637
- var version = "3.2.2";
637
+ var version = "3.3.0-rc.3";
638
638
 
639
639
  // src/context/AdsProvider.tsx
640
640
  import { jsx as jsx4 } from "react/jsx-runtime";
@@ -735,8 +735,20 @@ var getSdk = async () => ({
735
735
  platform: Platform3.OS === "ios" ? "ios" : "android",
736
736
  version
737
737
  });
738
+ var getTcf = async () => {
739
+ try {
740
+ const tcfData = await NativeRNKontext_default.getTcfData();
741
+ return {
742
+ gdpr: tcfData.gdprApplies,
743
+ gdprConsent: tcfData.tcString
744
+ };
745
+ } catch (error) {
746
+ console.error(error);
747
+ return {};
748
+ }
749
+ };
738
750
  var AdsProvider = (props) => {
739
- return /* @__PURE__ */ jsx4(AdsProviderInternal, { ...props, getDevice, getSdk, getApp });
751
+ return /* @__PURE__ */ jsx4(AdsProviderInternal, { ...props, getDevice, getSdk, getApp, getTcf });
740
752
  };
741
753
  export {
742
754
  AdsProvider,
@@ -98,52 +98,40 @@ public class KontextSDK: NSObject {
98
98
  }
99
99
  }
100
100
 
101
- // MARK: - TCF (IABTCF_*)
101
+ // MARK: - TCF (minimal: GDPR applies + TC string)
102
102
 
103
- /// Returns all `IABTCF_*` values from `UserDefaults`.
104
- /// Values are normalized to React Native bridge-safe types:
105
- /// - String / NSNumber / NSNull
106
- /// - (rare) Data is returned as base64 String
103
+ /// Returns minimal TCF data needed for RTB:
104
+ /// - gdprApplies (0 | 1 | nil)
105
+ /// - tcString (String | nil)
107
106
  @objc
108
107
  public static func getTcfData() -> NSDictionary {
109
- let all: [String: Any] = UserDefaults.standard.dictionaryRepresentation
110
-
108
+ let defaults = UserDefaults.standard
111
109
  let out = NSMutableDictionary()
112
110
 
113
- for (key, value) in all {
114
- guard key.hasPrefix("IABTCF_") else { continue }
111
+ // IABTCF_TCString
112
+ if let tcString = defaults.string(forKey: "IABTCF_TCString") {
113
+ out["tcString"] = tcString
114
+ } else {
115
+ out["tcString"] = NSNull()
116
+ }
115
117
 
116
- if let normalized = normalizeForReactNative(value) {
117
- out[key] = normalized
118
+ // IABTCF_gdprApplies
119
+ if let raw = defaults.object(forKey: "IABTCF_gdprApplies") {
120
+ // Normalize to 0 / 1
121
+ if let n = raw as? NSNumber {
122
+ out["gdprApplies"] = n.intValue
123
+ } else if let b = raw as? Bool {
124
+ out["gdprApplies"] = b ? 1 : 0
125
+ } else if let s = raw as? String, let i = Int(s) {
126
+ out["gdprApplies"] = i
118
127
  } else {
119
- out[key] = NSNull()
128
+ out["gdprApplies"] = NSNull()
120
129
  }
130
+ } else {
131
+ out["gdprApplies"] = NSNull()
121
132
  }
122
133
 
123
134
  return out
124
135
  }
125
136
 
126
- private static func normalizeForReactNative(_ value: Any) -> Any? {
127
- switch value {
128
- case is NSNull:
129
- return NSNull()
130
-
131
- case let s as String:
132
- return s
133
-
134
- case let n as NSNumber:
135
- // NSNumber covers Int/Double/Bool in ObjC bridging.
136
- return n
137
-
138
- case let b as Bool:
139
- return NSNumber(value: b)
140
-
141
- case let d as Data:
142
- return d.base64EncodedString()
143
-
144
- default:
145
- return nil
146
- }
147
- }
148
-
149
137
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontextso/sdk-react-native",
3
- "version": "3.3.0-rc.1",
3
+ "version": "3.3.0-rc.3",
4
4
  "description": "Kontext SDK for React Native",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -54,7 +54,7 @@
54
54
  "react-native-webview": "^13.10.0"
55
55
  },
56
56
  "dependencies": {
57
- "@kontextso/sdk-react": "^3.0.6"
57
+ "@kontextso/sdk-react": "^3.0.7"
58
58
  },
59
59
  "files": [
60
60
  "dist/*",
@@ -7,7 +7,7 @@ export interface Spec extends TurboModule {
7
7
  dismissSKOverlay(): Promise<boolean>
8
8
  presentSKStoreProduct(appStoreId: string): Promise<boolean>
9
9
  dismissSKStoreProduct(): Promise<boolean>
10
- getTcfData(): Promise<Record<string, string | number | boolean | null>>
10
+ getTcfData(): Promise<{ gdprApplies: 0 | 1 | undefined, tcString: string | undefined }>
11
11
  }
12
12
 
13
13
  export default TurboModuleRegistry.getEnforcing<Spec>('RNKontext')
@@ -5,6 +5,7 @@ import {
5
5
  type DeviceConfig,
6
6
  log,
7
7
  type SDKConfig,
8
+ type RegulatoryConfig,
8
9
  } from '@kontextso/sdk-react'
9
10
  import { fetch as fetchNetworkInfo, NetInfoStateType } from '@react-native-community/netinfo'
10
11
  import { Appearance, Dimensions, PixelRatio, Platform } from 'react-native'
@@ -121,6 +122,19 @@ const getSdk = async (): Promise<SDKConfig> => ({
121
122
  version,
122
123
  })
123
124
 
125
+ const getTcf = async (): Promise<Pick<RegulatoryConfig, 'gdpr' | 'gdprConsent'>> => {
126
+ try {
127
+ const tcfData = await NativeRNKontext.getTcfData()
128
+ return {
129
+ gdpr: tcfData.gdprApplies,
130
+ gdprConsent: tcfData.tcString,
131
+ }
132
+ } catch (error) {
133
+ console.error(error)
134
+ return {}
135
+ }
136
+ }
137
+
124
138
  export const AdsProvider = (props: AdsProviderProps) => {
125
- return <AdsProviderInternal {...props} getDevice={getDevice} getSdk={getSdk} getApp={getApp} />
139
+ return <AdsProviderInternal {...props} getDevice={getDevice} getSdk={getSdk} getApp={getApp} getTcf={getTcf} />
126
140
  }