@kontextso/sdk-react-native 3.3.1-rc.0 → 3.4.0-rc.1

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.
package/RNKontext.podspec CHANGED
@@ -15,6 +15,7 @@ Pod::Spec.new do |s|
15
15
 
16
16
  s.source_files = "ios/**/*.{h,m,mm,cpp,swift}"
17
17
  s.private_header_files = "ios/**/*.h"
18
+ s.resources = ["ios/PrivacyInfo.xcprivacy"]
18
19
 
19
20
 
20
21
  install_modules_dependencies(s)
@@ -86,4 +86,5 @@ dependencies {
86
86
  implementation "com.facebook.react:react-android"
87
87
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
88
88
  implementation "androidx.preference:preference:1.2.1"
89
+ implementation "com.google.android.gms:play-services-ads-identifier:18.0.1"
89
90
  }
@@ -1,2 +1,3 @@
1
1
  <manifest xmlns:android="http://schemas.android.com/apk/res/android">
2
- </manifest>
2
+ <uses-permission android:name="com.google.android.gms.permission.AD_ID" />
3
+ </manifest>
@@ -1,16 +1,50 @@
1
1
  package so.kontext.react
2
2
 
3
3
  import android.content.Context
4
+ import android.os.Handler
5
+ import android.os.Looper
4
6
  import android.media.AudioManager
5
7
  import androidx.preference.PreferenceManager
6
8
  import com.facebook.react.bridge.Arguments
7
9
  import com.facebook.react.bridge.Promise
8
10
  import com.facebook.react.bridge.ReactApplicationContext
9
11
  import com.facebook.react.bridge.WritableMap
12
+ import com.google.android.gms.ads.identifier.AdvertisingIdClient
13
+ import java.util.concurrent.Executors
10
14
 
11
15
 
12
16
  class RNKontextModuleImpl(private val reactContext: ReactApplicationContext) {
13
17
 
18
+ private val mainHandler = Handler(Looper.getMainLooper())
19
+ private val executor = Executors.newSingleThreadExecutor()
20
+
21
+ fun getAdvertisingId(promise: Promise?) {
22
+ if (promise == null) return
23
+ executor.execute {
24
+ val id = try {
25
+ val info = AdvertisingIdClient.getAdvertisingIdInfo(reactContext.applicationContext)
26
+ if (info.isLimitAdTrackingEnabled) null else info.id
27
+ } catch (_: Exception) {
28
+ null
29
+ }
30
+ mainHandler.post { promise.resolve(id) }
31
+ }
32
+ }
33
+
34
+ // Android has no IDFV equivalent — iOS only
35
+ fun getVendorId(promise: Promise?) {
36
+ promise?.resolve(null)
37
+ }
38
+
39
+ // Android has no ATT — iOS only
40
+ fun getTrackingAuthorizationStatus(promise: Promise?) {
41
+ promise?.resolve(4) // TrackingStatus.NotSupported
42
+ }
43
+
44
+ fun requestTrackingAuthorization(promise: Promise?) {
45
+ promise?.resolve(4) // TrackingStatus.NotSupported
46
+ }
47
+
14
48
  fun isSoundOn(promise: Promise?) {
15
49
  val audioManager = reactContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager
16
50
  val current = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC)
@@ -12,6 +12,22 @@ class RNKontextModule(reactContext: ReactApplicationContext) :
12
12
 
13
13
  override fun getName(): String = NAME
14
14
 
15
+ override fun getAdvertisingId(promise: Promise?) {
16
+ impl.getAdvertisingId(promise)
17
+ }
18
+
19
+ override fun getVendorId(promise: Promise?) {
20
+ impl.getVendorId(promise)
21
+ }
22
+
23
+ override fun getTrackingAuthorizationStatus(promise: Promise?) {
24
+ impl.getTrackingAuthorizationStatus(promise)
25
+ }
26
+
27
+ override fun requestTrackingAuthorization(promise: Promise?) {
28
+ impl.requestTrackingAuthorization(promise)
29
+ }
30
+
15
31
  override fun isSoundOn(promise: Promise?) {
16
32
  impl.isSoundOn(promise)
17
33
  }
@@ -38,6 +54,23 @@ class RNKontextModule(reactContext: ReactApplicationContext) :
38
54
  promise?.resolve(false)
39
55
  }
40
56
 
57
+ // ---------- iOS-only: SKAdNetwork ----------
58
+ override fun initSkAdNetworkImpression(params: com.facebook.react.bridge.ReadableMap, promise: Promise?) {
59
+ promise?.resolve(false)
60
+ }
61
+
62
+ override fun startSkAdNetworkImpression(promise: Promise?) {
63
+ promise?.resolve(false)
64
+ }
65
+
66
+ override fun endSkAdNetworkImpression(promise: Promise?) {
67
+ promise?.resolve(false)
68
+ }
69
+
70
+ override fun disposeSkAdNetwork(promise: Promise?) {
71
+ promise?.resolve(false)
72
+ }
73
+
41
74
  companion object {
42
75
  const val NAME = "RNKontext"
43
76
  }
@@ -14,6 +14,26 @@ class RNKontextModule(reactContext: ReactApplicationContext) :
14
14
 
15
15
  override fun getName(): String = NAME
16
16
 
17
+ @ReactMethod
18
+ fun getAdvertisingId(promise: Promise?) {
19
+ impl.getAdvertisingId(promise)
20
+ }
21
+
22
+ @ReactMethod
23
+ fun getVendorId(promise: Promise?) {
24
+ impl.getVendorId(promise)
25
+ }
26
+
27
+ @ReactMethod
28
+ fun getTrackingAuthorizationStatus(promise: Promise?) {
29
+ impl.getTrackingAuthorizationStatus(promise)
30
+ }
31
+
32
+ @ReactMethod
33
+ fun requestTrackingAuthorization(promise: Promise?) {
34
+ impl.requestTrackingAuthorization(promise)
35
+ }
36
+
17
37
  @ReactMethod
18
38
  fun isSoundOn(promise: Promise?) {
19
39
  impl.isSoundOn(promise)
@@ -46,6 +66,27 @@ class RNKontextModule(reactContext: ReactApplicationContext) :
46
66
  impl.getTcfData(promise)
47
67
  }
48
68
 
69
+ // ---------- iOS-only: SKAdNetwork ----------
70
+ @ReactMethod
71
+ fun initSkAdNetworkImpression(params: com.facebook.react.bridge.ReadableMap, promise: Promise?) {
72
+ promise?.resolve(false)
73
+ }
74
+
75
+ @ReactMethod
76
+ fun startSkAdNetworkImpression(promise: Promise?) {
77
+ promise?.resolve(false)
78
+ }
79
+
80
+ @ReactMethod
81
+ fun endSkAdNetworkImpression(promise: Promise?) {
82
+ promise?.resolve(false)
83
+ }
84
+
85
+ @ReactMethod
86
+ fun disposeSkAdNetwork(promise: Promise?) {
87
+ promise?.resolve(false)
88
+ }
89
+
49
90
  companion object {
50
91
  const val NAME = "RNKontext"
51
92
  }
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ var __export = (target, all) => {
11
11
  };
12
12
  var __copyProps = (to, from, except, desc) => {
13
13
  if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
14
+ for (const key of __getOwnPropNames(from))
15
15
  if (!__hasOwnProp.call(to, key) && key !== except)
16
16
  __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
17
  }
@@ -684,13 +684,92 @@ var InlineAd_default = InlineAd;
684
684
  // src/context/AdsProvider.tsx
685
685
  var import_sdk_react2 = require("@kontextso/sdk-react");
686
686
  var import_netinfo = require("@react-native-community/netinfo");
687
- var import_react_native6 = require("react-native");
687
+ var import_react_native7 = require("react-native");
688
688
  var import_react_native_device_info = __toESM(require("react-native-device-info"));
689
689
 
690
690
  // package.json
691
- var version = "3.3.1-rc.0";
691
+ var version = "3.4.0-rc.0";
692
+
693
+ // src/services/Att.ts
694
+ var import_react_native6 = require("react-native");
695
+ var ZERO_UUID = "00000000-0000-0000-0000-000000000000";
696
+ var didRunStartupFlow = false;
697
+ var startupFlowPromise = null;
698
+ function requestTrackingAuthorization() {
699
+ if (didRunStartupFlow) {
700
+ return startupFlowPromise ?? Promise.resolve();
701
+ }
702
+ didRunStartupFlow = true;
703
+ startupFlowPromise = _runStartupFlow();
704
+ return startupFlowPromise;
705
+ }
706
+ async function getTrackingAuthorizationStatus() {
707
+ if (import_react_native6.Platform.OS !== "ios") {
708
+ return 4 /* NotSupported */;
709
+ }
710
+ try {
711
+ const raw = await NativeRNKontext_default.getTrackingAuthorizationStatus();
712
+ return _mapRawStatus(raw);
713
+ } catch (error) {
714
+ console.error(error);
715
+ return 4 /* NotSupported */;
716
+ }
717
+ }
718
+ async function getAdvertisingId() {
719
+ try {
720
+ const id = await NativeRNKontext_default.getAdvertisingId();
721
+ return _normalizeId(id);
722
+ } catch (error) {
723
+ console.error(error);
724
+ return null;
725
+ }
726
+ }
727
+ async function getVendorId() {
728
+ if (import_react_native6.Platform.OS !== "ios") {
729
+ return null;
730
+ }
731
+ try {
732
+ const id = await NativeRNKontext_default.getVendorId();
733
+ return _normalizeId(id);
734
+ } catch (error) {
735
+ console.error(error);
736
+ return null;
737
+ }
738
+ }
739
+ async function resolveIds(fallbacks) {
740
+ const [vendorId, advertisingId] = await Promise.all([getVendorId(), getAdvertisingId()]);
741
+ return {
742
+ vendorId: vendorId ?? _normalizeId(fallbacks?.vendorId),
743
+ advertisingId: advertisingId ?? _normalizeId(fallbacks?.advertisingId)
744
+ };
745
+ }
746
+ async function _runStartupFlow() {
747
+ if (import_react_native6.Platform.OS !== "ios") return;
748
+ try {
749
+ if (!_isVersionAtLeast145(import_react_native6.Platform.Version)) return;
750
+ const status = await getTrackingAuthorizationStatus();
751
+ if (status !== 0 /* NotDetermined */) return;
752
+ await NativeRNKontext_default.requestTrackingAuthorization();
753
+ } catch (error) {
754
+ console.error(error);
755
+ }
756
+ }
757
+ function _isVersionAtLeast145(version2) {
758
+ const [major = 0, minor = 0] = version2.split(".").map(Number);
759
+ return major > 14 || major === 14 && minor >= 5;
760
+ }
761
+ function _mapRawStatus(raw) {
762
+ if (raw >= 0 && raw <= 4) return raw;
763
+ return 4 /* NotSupported */;
764
+ }
765
+ function _normalizeId(id) {
766
+ if (!id || id.trim() === "") return null;
767
+ if (id.toLowerCase() === ZERO_UUID) return null;
768
+ return id;
769
+ }
692
770
 
693
771
  // src/context/AdsProvider.tsx
772
+ var import_react3 = require("react");
694
773
  var import_jsx_runtime4 = require("react/jsx-runtime");
695
774
  ErrorUtils.setGlobalHandler((error, isFatal) => {
696
775
  if (!isFatal) {
@@ -709,7 +788,7 @@ var getDevice = async () => {
709
788
  const powerState = await import_react_native_device_info.default.getPowerState();
710
789
  const deviceType = import_react_native_device_info.default.getDeviceType();
711
790
  const soundOn = await NativeRNKontext_default.isSoundOn();
712
- const screen = import_react_native6.Dimensions.get("screen");
791
+ const screen = import_react_native7.Dimensions.get("screen");
713
792
  const networkInfo = await (0, import_netinfo.fetch)();
714
793
  const mapDeviceTypeToHardwareType = () => {
715
794
  switch (deviceType) {
@@ -746,14 +825,14 @@ var getDevice = async () => {
746
825
  detail: networkInfo.type === import_netinfo.NetInfoStateType.cellular && networkInfo.details.cellularGeneration || void 0
747
826
  },
748
827
  os: {
749
- name: import_react_native6.Platform.OS,
828
+ name: import_react_native7.Platform.OS,
750
829
  version: import_react_native_device_info.default.getSystemVersion(),
751
830
  locale: Intl.DateTimeFormat().resolvedOptions().locale,
752
831
  timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
753
832
  },
754
833
  screen: {
755
- darkMode: import_react_native6.Appearance.getColorScheme() === "dark",
756
- dpr: import_react_native6.PixelRatio.get(),
834
+ darkMode: import_react_native7.Appearance.getColorScheme() === "dark",
835
+ dpr: import_react_native7.PixelRatio.get(),
757
836
  height: screen.height,
758
837
  width: screen.width,
759
838
  orientation: screen.width > screen.height ? "landscape" : "portrait"
@@ -786,7 +865,7 @@ var getApp = async () => {
786
865
  };
787
866
  var getSdk = async () => ({
788
867
  name: "sdk-react-native",
789
- platform: import_react_native6.Platform.OS === "ios" ? "ios" : "android",
868
+ platform: import_react_native7.Platform.OS === "ios" ? "ios" : "android",
790
869
  version
791
870
  });
792
871
  var getTcf = async () => {
@@ -804,7 +883,38 @@ var getTcf = async () => {
804
883
  }
805
884
  };
806
885
  var AdsProvider = (props) => {
807
- return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_sdk_react2.AdsProviderInternal, { ...props, getDevice, getSdk, getApp, getTcf });
886
+ const [advertisingId, setAdvertisingId] = (0, import_react3.useState)();
887
+ const [vendorId, setVendorId] = (0, import_react3.useState)();
888
+ const initializeIfa = async () => {
889
+ try {
890
+ if (import_react_native7.Platform.OS === "ios") {
891
+ await requestTrackingAuthorization();
892
+ }
893
+ const ids = await resolveIds({
894
+ advertisingId: props.advertisingId ?? void 0,
895
+ vendorId: props.vendorId ?? void 0
896
+ });
897
+ setAdvertisingId(ids.advertisingId);
898
+ setVendorId(ids.vendorId);
899
+ } catch (error) {
900
+ console.error(error);
901
+ }
902
+ };
903
+ (0, import_react3.useEffect)(() => {
904
+ initializeIfa();
905
+ }, []);
906
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
907
+ import_sdk_react2.AdsProviderInternal,
908
+ {
909
+ ...props,
910
+ advertisingId,
911
+ vendorId,
912
+ getDevice,
913
+ getSdk,
914
+ getApp,
915
+ getTcf
916
+ }
917
+ );
808
918
  };
809
919
  // Annotate the CommonJS export names for ESM import in node:
810
920
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -656,13 +656,92 @@ import {
656
656
  log
657
657
  } from "@kontextso/sdk-react";
658
658
  import { fetch as fetchNetworkInfo, NetInfoStateType } from "@react-native-community/netinfo";
659
- import { Appearance, Dimensions, PixelRatio, Platform as Platform3 } from "react-native";
659
+ import { Appearance, Dimensions, PixelRatio, Platform as Platform4 } from "react-native";
660
660
  import DeviceInfo from "react-native-device-info";
661
661
 
662
662
  // package.json
663
- var version = "3.3.1-rc.0";
663
+ var version = "3.4.0-rc.0";
664
+
665
+ // src/services/Att.ts
666
+ import { Platform as Platform3 } from "react-native";
667
+ var ZERO_UUID = "00000000-0000-0000-0000-000000000000";
668
+ var didRunStartupFlow = false;
669
+ var startupFlowPromise = null;
670
+ function requestTrackingAuthorization() {
671
+ if (didRunStartupFlow) {
672
+ return startupFlowPromise ?? Promise.resolve();
673
+ }
674
+ didRunStartupFlow = true;
675
+ startupFlowPromise = _runStartupFlow();
676
+ return startupFlowPromise;
677
+ }
678
+ async function getTrackingAuthorizationStatus() {
679
+ if (Platform3.OS !== "ios") {
680
+ return 4 /* NotSupported */;
681
+ }
682
+ try {
683
+ const raw = await NativeRNKontext_default.getTrackingAuthorizationStatus();
684
+ return _mapRawStatus(raw);
685
+ } catch (error) {
686
+ console.error(error);
687
+ return 4 /* NotSupported */;
688
+ }
689
+ }
690
+ async function getAdvertisingId() {
691
+ try {
692
+ const id = await NativeRNKontext_default.getAdvertisingId();
693
+ return _normalizeId(id);
694
+ } catch (error) {
695
+ console.error(error);
696
+ return null;
697
+ }
698
+ }
699
+ async function getVendorId() {
700
+ if (Platform3.OS !== "ios") {
701
+ return null;
702
+ }
703
+ try {
704
+ const id = await NativeRNKontext_default.getVendorId();
705
+ return _normalizeId(id);
706
+ } catch (error) {
707
+ console.error(error);
708
+ return null;
709
+ }
710
+ }
711
+ async function resolveIds(fallbacks) {
712
+ const [vendorId, advertisingId] = await Promise.all([getVendorId(), getAdvertisingId()]);
713
+ return {
714
+ vendorId: vendorId ?? _normalizeId(fallbacks?.vendorId),
715
+ advertisingId: advertisingId ?? _normalizeId(fallbacks?.advertisingId)
716
+ };
717
+ }
718
+ async function _runStartupFlow() {
719
+ if (Platform3.OS !== "ios") return;
720
+ try {
721
+ if (!_isVersionAtLeast145(Platform3.Version)) return;
722
+ const status = await getTrackingAuthorizationStatus();
723
+ if (status !== 0 /* NotDetermined */) return;
724
+ await NativeRNKontext_default.requestTrackingAuthorization();
725
+ } catch (error) {
726
+ console.error(error);
727
+ }
728
+ }
729
+ function _isVersionAtLeast145(version2) {
730
+ const [major = 0, minor = 0] = version2.split(".").map(Number);
731
+ return major > 14 || major === 14 && minor >= 5;
732
+ }
733
+ function _mapRawStatus(raw) {
734
+ if (raw >= 0 && raw <= 4) return raw;
735
+ return 4 /* NotSupported */;
736
+ }
737
+ function _normalizeId(id) {
738
+ if (!id || id.trim() === "") return null;
739
+ if (id.toLowerCase() === ZERO_UUID) return null;
740
+ return id;
741
+ }
664
742
 
665
743
  // src/context/AdsProvider.tsx
744
+ import { useEffect as useEffect2, useState as useState2 } from "react";
666
745
  import { jsx as jsx4 } from "react/jsx-runtime";
667
746
  ErrorUtils.setGlobalHandler((error, isFatal) => {
668
747
  if (!isFatal) {
@@ -718,7 +797,7 @@ var getDevice = async () => {
718
797
  detail: networkInfo.type === NetInfoStateType.cellular && networkInfo.details.cellularGeneration || void 0
719
798
  },
720
799
  os: {
721
- name: Platform3.OS,
800
+ name: Platform4.OS,
722
801
  version: DeviceInfo.getSystemVersion(),
723
802
  locale: Intl.DateTimeFormat().resolvedOptions().locale,
724
803
  timezone: Intl.DateTimeFormat().resolvedOptions().timeZone
@@ -758,7 +837,7 @@ var getApp = async () => {
758
837
  };
759
838
  var getSdk = async () => ({
760
839
  name: "sdk-react-native",
761
- platform: Platform3.OS === "ios" ? "ios" : "android",
840
+ platform: Platform4.OS === "ios" ? "ios" : "android",
762
841
  version
763
842
  });
764
843
  var getTcf = async () => {
@@ -776,7 +855,38 @@ var getTcf = async () => {
776
855
  }
777
856
  };
778
857
  var AdsProvider = (props) => {
779
- return /* @__PURE__ */ jsx4(AdsProviderInternal, { ...props, getDevice, getSdk, getApp, getTcf });
858
+ const [advertisingId, setAdvertisingId] = useState2();
859
+ const [vendorId, setVendorId] = useState2();
860
+ const initializeIfa = async () => {
861
+ try {
862
+ if (Platform4.OS === "ios") {
863
+ await requestTrackingAuthorization();
864
+ }
865
+ const ids = await resolveIds({
866
+ advertisingId: props.advertisingId ?? void 0,
867
+ vendorId: props.vendorId ?? void 0
868
+ });
869
+ setAdvertisingId(ids.advertisingId);
870
+ setVendorId(ids.vendorId);
871
+ } catch (error) {
872
+ console.error(error);
873
+ }
874
+ };
875
+ useEffect2(() => {
876
+ initializeIfa();
877
+ }, []);
878
+ return /* @__PURE__ */ jsx4(
879
+ AdsProviderInternal,
880
+ {
881
+ ...props,
882
+ advertisingId,
883
+ vendorId,
884
+ getDevice,
885
+ getSdk,
886
+ getApp,
887
+ getTcf
888
+ }
889
+ );
780
890
  };
781
891
  export {
782
892
  AdsProvider,
@@ -3,6 +3,8 @@ import AVFoundation
3
3
  import StoreKit
4
4
  import UIKit
5
5
  import React
6
+ import AdSupport
7
+ import AppTrackingTransparency
6
8
 
7
9
  @objc(KontextSDK)
8
10
  public class KontextSDK: NSObject {
@@ -98,6 +100,65 @@ public class KontextSDK: NSObject {
98
100
  }
99
101
  }
100
102
 
103
+ // MARK: - SKAdNetwork
104
+
105
+ @objc
106
+ public static func initSkAdNetworkImpression(
107
+ _ params: [String: Any],
108
+ resolver resolve: @escaping RCTPromiseResolveBlock,
109
+ rejecter reject: @escaping RCTPromiseRejectBlock
110
+ ) {
111
+ SKAdNetworkManager.shared.initImpression(params: params) { success, error in
112
+ if let error = error {
113
+ reject("SKAN_INIT_IMPRESSION_FAILED", error.localizedDescription, error)
114
+ } else {
115
+ resolve(success)
116
+ }
117
+ }
118
+ }
119
+
120
+ @objc
121
+ public static func startSkAdNetworkImpression(
122
+ _ resolve: @escaping RCTPromiseResolveBlock,
123
+ rejecter reject: @escaping RCTPromiseRejectBlock
124
+ ) {
125
+ SKAdNetworkManager.shared.startImpression { success, error in
126
+ if let error = error {
127
+ reject("SKAN_START_IMPRESSION_FAILED", error.localizedDescription, error)
128
+ } else {
129
+ resolve(success)
130
+ }
131
+ }
132
+ }
133
+
134
+ @objc
135
+ public static func endSkAdNetworkImpression(
136
+ _ resolve: @escaping RCTPromiseResolveBlock,
137
+ rejecter reject: @escaping RCTPromiseRejectBlock
138
+ ) {
139
+ SKAdNetworkManager.shared.endImpression { success, error in
140
+ if let error = error {
141
+ reject("SKAN_END_IMPRESSION_FAILED", error.localizedDescription, error)
142
+ } else {
143
+ resolve(success)
144
+ }
145
+ }
146
+ }
147
+
148
+ @objc
149
+ public static func disposeSkAdNetwork(
150
+ _ resolve: @escaping RCTPromiseResolveBlock,
151
+ rejecter reject: @escaping RCTPromiseRejectBlock
152
+ ) {
153
+ SKAdNetworkManager.shared.dispose { success, error in
154
+ if let error = error {
155
+ reject("SKAN_DISPOSE_FAILED", error.localizedDescription, error)
156
+ } else {
157
+ resolve(success)
158
+ }
159
+ }
160
+ }
161
+
101
162
  // MARK: - TCF (minimal: GDPR applies + TC string)
102
163
 
103
164
  /// Returns minimal TCF data needed for RTB:
@@ -134,4 +195,49 @@ public class KontextSDK: NSObject {
134
195
  return out
135
196
  }
136
197
 
198
+ // MARK: - ATT / IFA
199
+
200
+ private static let notSupportedStatus = 4
201
+
202
+ @objc
203
+ public static func getTrackingAuthorizationStatus() -> NSNumber {
204
+ if #available(iOS 14, *) {
205
+ return NSNumber(value: ATTrackingManager.trackingAuthorizationStatus.rawValue)
206
+ }
207
+ return NSNumber(value: notSupportedStatus)
208
+ }
209
+
210
+ @objc
211
+ public static func requestTrackingAuthorization(
212
+ _ resolve: @escaping RCTPromiseResolveBlock,
213
+ rejecter reject: @escaping RCTPromiseRejectBlock
214
+ ) {
215
+ if #available(iOS 14, *) {
216
+ TrackingAuthorizationManager.shared.requestTrackingAuthorization { statusRaw in
217
+ resolve(NSNumber(value: statusRaw))
218
+ }
219
+ } else {
220
+ resolve(NSNumber(value: notSupportedStatus))
221
+ }
222
+ }
223
+
224
+ @objc
225
+ public static func getAdvertisingId() -> String? {
226
+ let manager = ASIdentifierManager.shared()
227
+ if #available(iOS 14.0, *) {
228
+ guard ATTrackingManager.trackingAuthorizationStatus == .authorized else {
229
+ return nil
230
+ }
231
+ return manager.advertisingIdentifier.uuidString
232
+ }
233
+ return manager.isAdvertisingTrackingEnabled
234
+ ? manager.advertisingIdentifier.uuidString
235
+ : nil
236
+ }
237
+
238
+ @objc
239
+ public static func getVendorId() -> String? {
240
+ return UIDevice.current.identifierForVendor?.uuidString
241
+ }
242
+
137
243
  }
@@ -0,0 +1,64 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+
6
+ <key>NSPrivacyTracking</key><true/>
7
+
8
+ <key>NSPrivacyTrackingDomains</key>
9
+ <array>
10
+ <string>megabrain.co</string>
11
+ </array>
12
+
13
+ <key>NSPrivacyCollectedDataTypes</key>
14
+ <array>
15
+
16
+ <dict>
17
+ <key>NSPrivacyCollectedDataType</key>
18
+ <string>NSPrivacyCollectedDataTypeDeviceID</string>
19
+ <key>NSPrivacyCollectedDataTypeLinked</key><true/>
20
+ <key>NSPrivacyCollectedDataTypeTracking</key><true/>
21
+ <key>NSPrivacyCollectedDataTypePurposes</key>
22
+ <array>
23
+ <string>NSPrivacyCollectedDataTypePurposeThirdPartyAdvertising</string>
24
+ </array>
25
+ </dict>
26
+
27
+ <dict>
28
+ <key>NSPrivacyCollectedDataType</key>
29
+ <string>NSPrivacyCollectedDataTypeOtherAppInfo</string>
30
+ <key>NSPrivacyCollectedDataTypeLinked</key><false/>
31
+ <key>NSPrivacyCollectedDataTypeTracking</key><false/>
32
+ <key>NSPrivacyCollectedDataTypePurposes</key>
33
+ <array>
34
+ <string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
35
+ </array>
36
+ </dict>
37
+
38
+ <dict>
39
+ <key>NSPrivacyCollectedDataType</key>
40
+ <string>NSPrivacyCollectedDataTypeOtherDiagnosticData</string>
41
+ <key>NSPrivacyCollectedDataTypeLinked</key><false/>
42
+ <key>NSPrivacyCollectedDataTypeTracking</key><false/>
43
+ <key>NSPrivacyCollectedDataTypePurposes</key>
44
+ <array>
45
+ <string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
46
+ </array>
47
+ </dict>
48
+
49
+ </array>
50
+
51
+ <key>NSPrivacyAccessedAPITypes</key>
52
+ <array>
53
+ <dict>
54
+ <key>NSPrivacyAccessedAPIType</key>
55
+ <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
56
+ <key>NSPrivacyAccessedAPITypeReasons</key>
57
+ <array>
58
+ <string>CA92.1</string>
59
+ </array>
60
+ </dict>
61
+ </array>
62
+
63
+ </dict>
64
+ </plist>