tapjoy-react-native-sdk 13.4.1 → 14.0.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.
Files changed (32) hide show
  1. package/android/build.gradle +2 -2
  2. package/android/src/main/java/com/tapjoyreactnativesdk/TapjoyReactNativeSdkModule.kt +45 -29
  3. package/example/Gemfile +4 -2
  4. package/example/android/app/build.gradle +2 -3
  5. package/example/android/app/src/main/java/com/tapjoyreactnativesdkexample/MainApplication.kt +1 -3
  6. package/example/android/app/src/main/res/drawable/rn_edit_text_material.xml +2 -1
  7. package/example/android/build.gradle +3 -3
  8. package/example/android/gradle/wrapper/gradle-wrapper.properties +1 -1
  9. package/example/android/gradlew +7 -7
  10. package/example/android/gradlew.bat +10 -10
  11. package/example/ios/Podfile +2 -17
  12. package/example/ios/TapjoyReactNativeSdkExample/AppDelegate.mm +2 -2
  13. package/example/ios/TapjoyReactNativeSdkExample/Info.plist +1 -1
  14. package/example/ios/TapjoyReactNativeSdkExample/PrivacyInfo.xcprivacy +37 -0
  15. package/example/ios/TapjoyReactNativeSdkExample.xcodeproj/project.pbxproj +14 -13
  16. package/example/metro.config.js +1 -1
  17. package/example/package.json +3 -3
  18. package/example/src/App.tsx +21 -12
  19. package/example/src/ConnectContext.tsx +11 -0
  20. package/example/src/MainScreen.tsx +10 -4
  21. package/example/src/OfferwallDiscoverScreen.tsx +3 -8
  22. package/example/src/OfferwallScreen.tsx +23 -11
  23. package/example/src/Styles.ts +1 -1
  24. package/example/src/UserProperties.tsx +45 -19
  25. package/ios/TapjoyReactNativeSdk.m +6 -3
  26. package/ios/TapjoyReactNativeSdk.swift +37 -27
  27. package/package.json +8 -36
  28. package/src/TJPrivacyPolicy.ts +0 -12
  29. package/src/TJPurchase.ts +11 -0
  30. package/src/TJVersion.ts +1 -1
  31. package/src/index.ts +2 -0
  32. package/tapjoy-react-native-sdk.podspec +1 -1
@@ -79,9 +79,9 @@ dependencies {
79
79
  // For < 0.71, this will be from the local maven repo
80
80
  // For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
81
81
  //noinspection GradleDynamicVersion
82
- implementation 'com.facebook.react:react-native:0.73.2'
82
+ implementation 'com.facebook.react:react-native:0.74.1'
83
83
  implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
84
- implementation 'com.tapjoy:tapjoy-android-sdk:13.4.1'
84
+ implementation 'com.tapjoy:tapjoy-android-sdk:14.0.1'
85
85
  implementation "com.google.android.gms:play-services-ads-identifier:18.0.1"
86
86
  }
87
87
 
@@ -74,7 +74,6 @@ class TapjoyReactNativeSdkModule(reactContext: ReactApplicationContext) :
74
74
 
75
75
  Tapjoy.connect(this.currentActivity?.applicationContext, sdkKey, connectFlags.toHashtable(), object : TJConnectListener() {
76
76
  override fun onConnectSuccess() {
77
- Tapjoy.setActivity(currentActivity)
78
77
  promise.resolve(true)
79
78
  }
80
79
 
@@ -147,6 +146,11 @@ class TapjoyReactNativeSdkModule(reactContext: ReactApplicationContext) :
147
146
  })
148
147
  }
149
148
 
149
+ /**
150
+ * Sets user ID
151
+ *
152
+ * @param userId: User ID
153
+ */
150
154
  @ReactMethod
151
155
  fun setUserId(userId: String, promise: Promise) {
152
156
  Tapjoy.setUserID(userId, object: TJSetUserIDListener {
@@ -160,6 +164,16 @@ class TapjoyReactNativeSdkModule(reactContext: ReactApplicationContext) :
160
164
  })
161
165
  }
162
166
 
167
+ /**
168
+ * Gets user ID
169
+ *
170
+ * @return User ID
171
+ */
172
+ @ReactMethod
173
+ fun getUserId(promise: Promise) {
174
+ promise.resolve(Tapjoy.getUserID())
175
+ }
176
+
163
177
  /**
164
178
  * Sets the segment of the user
165
179
  *
@@ -196,6 +210,27 @@ class TapjoyReactNativeSdkModule(reactContext: ReactApplicationContext) :
196
210
  Tapjoy.setMaxLevel(maxLevel);
197
211
  }
198
212
 
213
+ /**
214
+ * Sets the level of the user.
215
+ *
216
+ * @param userLevel
217
+ * the level of the user
218
+ */
219
+ @ReactMethod
220
+ fun setUserLevel(userLevel: Int) {
221
+ Tapjoy.setUserLevel(userLevel)
222
+ }
223
+
224
+ /**
225
+ * Gets the level of the user.
226
+ *
227
+ * @return the level of the user.
228
+ */
229
+ @ReactMethod
230
+ fun getUserLevel(promise: Promise) {
231
+ promise.resolve(Tapjoy.getUserLevel())
232
+ }
233
+
199
234
  /**
200
235
  * Returns a String set which contains tags on the user.
201
236
  *
@@ -330,7 +365,6 @@ class TapjoyReactNativeSdkModule(reactContext: ReactApplicationContext) :
330
365
 
331
366
  }
332
367
  }
333
- Tapjoy.setActivity(this.currentActivity)
334
368
  val placement = Tapjoy.getPlacement(placementName, listener)
335
369
  placements[placementName] = placement
336
370
  }
@@ -477,15 +511,18 @@ class TapjoyReactNativeSdkModule(reactContext: ReactApplicationContext) :
477
511
  promise.resolve(placements[placementName]?.getEntryPoint()?.ordinal)
478
512
  }
479
513
 
480
- /**
481
- * Indicate if the user falls in any of the GDPR applicable countries
514
+ /**
515
+ * Tracks a purchase
482
516
  *
483
- * @param gdprApplicable true if GDPR applies to this user, false otherwise
517
+ * @param currencyCode
518
+ * the currency code of price as an alphabetic currency code
519
+ * specified in ISO 4217, i.e. "USD", "KRW"
520
+ * @param price
521
+ * the price of product
484
522
  */
485
- @Deprecated("Use setSubjectToGDPRStatus instead", ReplaceWith("setSubjectToGDPR(gdprApplicable)"))
486
523
  @ReactMethod
487
- fun setSubjectToGDPR(gdprApplicable: Boolean){
488
- Tapjoy.getPrivacyPolicy().setSubjectToGDPR(gdprApplicable)
524
+ fun trackPurchase(currencyCode: String, price: Double) {
525
+ Tapjoy.trackPurchase(currencyCode, price)
489
526
  }
490
527
 
491
528
  /**
@@ -565,17 +602,6 @@ class TapjoyReactNativeSdkModule(reactContext: ReactApplicationContext) :
565
602
  }
566
603
  }
567
604
 
568
- /**
569
- * This method will set ad_tracking_enabled to false for Tapjoy which only shows the user contextual ads. No ad tracking will be done on this user.
570
- *
571
- * @param isBelowConsentAge true if below consent age (COPPA) applies to this user, false otherwise
572
- */
573
- @Deprecated("Use setBelowConsentAgeStatus instead", ReplaceWith("setBelowConsentAgeStatus(isBelowConsentAgeStatus)"))
574
- @ReactMethod
575
- fun setBelowConsentAge(isBelowConsentAge: Boolean){
576
- Tapjoy.getPrivacyPolicy().setBelowConsentAge(isBelowConsentAge)
577
- }
578
-
579
605
  /**
580
606
  * This method will set ad_tracking_enabled to false for Tapjoy which only shows the user contextual ads. No ad tracking will be done on this user.
581
607
  *
@@ -596,16 +622,6 @@ class TapjoyReactNativeSdkModule(reactContext: ReactApplicationContext) :
596
622
  Tapjoy.getPrivacyPolicy().setUSPrivacy(isUsPrivacy)
597
623
  }
598
624
 
599
- /**
600
- * This is used for sending User's consent to behavioral advertising such as in the context of GDPR
601
- *
602
- * @param userConsent The value can be "0" (User has not provided consent), "1" (User has provided consent) or a daisybit string as suggested in IAB's Transparency and Consent Framework
603
- */
604
- @Deprecated("Use setUserConsentStatus instead", ReplaceWith("setUserConsentStatus(userConsentStatus)"))
605
- @ReactMethod
606
- fun setUserConsent(userConsent: String){
607
- Tapjoy.getPrivacyPolicy().setUserConsent(userConsent)
608
- }
609
625
  /**
610
626
  * This is used for sending User's consent to behavioral advertising such as in the context of GDPR
611
627
  *
package/example/Gemfile CHANGED
@@ -3,5 +3,7 @@ source 'https://rubygems.org'
3
3
  # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
4
4
  ruby ">= 2.6.10"
5
5
 
6
- gem 'cocoapods', '~> 1.13'
7
- gem 'activesupport', '>= 6.1.7.3', '< 7.1.0'
6
+ # Cocoapods 1.15 introduced a bug which break the build. We will remove the upper
7
+ # bound in the template on Cocoapods with next React Native release.
8
+ gem 'cocoapods', '>= 1.13', '< 1.15'
9
+ gem 'activesupport', '>= 6.1.7.5', '< 7.1.0'
@@ -107,7 +107,6 @@ android {
107
107
  dependencies {
108
108
  // The version of react-native is set by the React Native Gradle Plugin
109
109
  implementation("com.facebook.react:react-android:")
110
- implementation("com.facebook.react:flipper-integration")
111
110
 
112
111
  if (hermesEnabled.toBoolean()) {
113
112
  implementation("com.facebook.react:hermes-android")
@@ -116,8 +115,8 @@ dependencies {
116
115
  }
117
116
 
118
117
  implementation 'com.google.android.gms:play-services-appset:16.0.2'
119
- implementation 'com.tapjoy:tapjoy-android-sdk:13.4.1'
118
+ implementation 'com.tapjoy:tapjoy-android-sdk:14.0.1'
120
119
 
121
120
  }
122
121
 
123
- apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
122
+ apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
@@ -9,7 +9,6 @@ import com.facebook.react.ReactPackage
9
9
  import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
10
10
  import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
11
11
  import com.facebook.react.defaults.DefaultReactNativeHost
12
- import com.facebook.react.flipper.ReactNativeFlipper
13
12
  import com.facebook.soloader.SoLoader
14
13
 
15
14
  class MainApplication : Application(), ReactApplication {
@@ -31,7 +30,7 @@ class MainApplication : Application(), ReactApplication {
31
30
  }
32
31
 
33
32
  override val reactHost: ReactHost
34
- get() = getDefaultReactHost(this.applicationContext, reactNativeHost)
33
+ get() = getDefaultReactHost(applicationContext, reactNativeHost)
35
34
 
36
35
  override fun onCreate() {
37
36
  super.onCreate()
@@ -40,6 +39,5 @@ class MainApplication : Application(), ReactApplication {
40
39
  // If you opted-in for the New Architecture, we load the native entry point for this app.
41
40
  load()
42
41
  }
43
- ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager)
44
42
  }
45
43
  }
@@ -17,7 +17,8 @@
17
17
  android:insetLeft="@dimen/abc_edit_text_inset_horizontal_material"
18
18
  android:insetRight="@dimen/abc_edit_text_inset_horizontal_material"
19
19
  android:insetTop="@dimen/abc_edit_text_inset_top_material"
20
- android:insetBottom="@dimen/abc_edit_text_inset_bottom_material">
20
+ android:insetBottom="@dimen/abc_edit_text_inset_bottom_material"
21
+ >
21
22
 
22
23
  <selector>
23
24
  <!--
@@ -1,11 +1,11 @@
1
1
  buildscript {
2
2
  ext {
3
3
  buildToolsVersion = "34.0.0"
4
- minSdkVersion = 21
4
+ minSdkVersion = 23
5
5
  compileSdkVersion = 34
6
6
  targetSdkVersion = 34
7
- ndkVersion = "25.1.8937393"
8
- kotlinVersion = "1.8.0"
7
+ ndkVersion = "26.1.10909125"
8
+ kotlinVersion = "1.9.22"
9
9
  }
10
10
  repositories {
11
11
  google()
@@ -1,6 +1,6 @@
1
1
  distributionBase=GRADLE_USER_HOME
2
2
  distributionPath=wrapper/dists
3
- distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip
3
+ distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-all.zip
4
4
  networkTimeout=10000
5
5
  validateDistributionUrl=true
6
6
  zipStoreBase=GRADLE_USER_HOME
@@ -145,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
145
145
  case $MAX_FD in #(
146
146
  max*)
147
147
  # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
148
- # shellcheck disable=SC3045
148
+ # shellcheck disable=SC2039,SC3045
149
149
  MAX_FD=$( ulimit -H -n ) ||
150
150
  warn "Could not query maximum file descriptor limit"
151
151
  esac
@@ -153,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
153
153
  '' | soft) :;; #(
154
154
  *)
155
155
  # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
156
- # shellcheck disable=SC3045
156
+ # shellcheck disable=SC2039,SC3045
157
157
  ulimit -n "$MAX_FD" ||
158
158
  warn "Could not set maximum file descriptor limit to $MAX_FD"
159
159
  esac
@@ -202,11 +202,11 @@ fi
202
202
  # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
203
203
  DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
204
204
 
205
- # Collect all arguments for the java command;
206
- # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
207
- # shell script including quotes and variable substitutions, so put them in
208
- # double quotes to make sure that they get re-expanded; and
209
- # * put everything else in single quotes, so that it's not re-expanded.
205
+ # Collect all arguments for the java command:
206
+ # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
207
+ # and any embedded shellness will be escaped.
208
+ # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
209
+ # treated as '${Hostname}' itself on the command line.
210
210
 
211
211
  set -- \
212
212
  "-Dorg.gradle.appname=$APP_BASE_NAME" \
@@ -42,11 +42,11 @@ set JAVA_EXE=java.exe
42
42
  %JAVA_EXE% -version >NUL 2>&1
43
43
  if "%ERRORLEVEL%" == "0" goto execute
44
44
 
45
- echo.
46
- echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47
- echo.
48
- echo Please set the JAVA_HOME variable in your environment to match the
49
- echo location of your Java installation.
45
+ echo. 1>&2
46
+ echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
47
+ echo. 1>&2
48
+ echo Please set the JAVA_HOME variable in your environment to match the 1>&2
49
+ echo location of your Java installation. 1>&2
50
50
 
51
51
  goto fail
52
52
 
@@ -56,11 +56,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56
56
 
57
57
  if exist "%JAVA_EXE%" goto execute
58
58
 
59
- echo.
60
- echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61
- echo.
62
- echo Please set the JAVA_HOME variable in your environment to match the
63
- echo location of your Java installation.
59
+ echo. 1>&2
60
+ echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
61
+ echo. 1>&2
62
+ echo Please set the JAVA_HOME variable in your environment to match the 1>&2
63
+ echo location of your Java installation. 1>&2
64
64
 
65
65
  goto fail
66
66
 
@@ -5,17 +5,6 @@ platform :ios, min_ios_version_supported
5
5
  prepare_react_native_project!
6
6
  source 'https://cdn.cocoapods.org/'
7
7
 
8
- # If you are using a `react-native-flipper` your iOS build will fail when `NO_FLIPPER=1` is set.
9
- # because `react-native-flipper` depends on (FlipperKit,...) that will be excluded
10
- #
11
- # To fix this you can also exclude `react-native-flipper` using a `react-native.config.js`
12
- # ```js
13
- # module.exports = {
14
- # dependencies: {
15
- # ...(process.env.NO_FLIPPER ? { 'react-native-flipper': { platforms: { ios: null } } } : {}),
16
- # ```
17
- flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled
18
-
19
8
  linkage = ENV['USE_FRAMEWORKS']
20
9
  if linkage != nil
21
10
  Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
@@ -27,11 +16,6 @@ target 'TapjoyReactNativeSdkExample' do
27
16
 
28
17
  use_react_native!(
29
18
  :path => config[:reactNativePath],
30
- # Enables Flipper.
31
- #
32
- # Note that if you have use_frameworks! enabled, Flipper will not work and
33
- # you should disable the next line.
34
- :flipper_configuration => flipper_config,
35
19
  # An absolute path to your application root.
36
20
  :app_path => "#{Pod::Config.instance.installation_root}/.."
37
21
  )
@@ -46,7 +30,8 @@ target 'TapjoyReactNativeSdkExample' do
46
30
  installer,
47
31
  # Set `mac_catalyst_enabled` to `true` in order to apply patches
48
32
  # necessary for Mac Catalyst builds
49
- :mac_catalyst_enabled => false
33
+ :mac_catalyst_enabled => false,
34
+ # :ccache_enabled => true
50
35
  )
51
36
  end
52
37
  end
@@ -16,10 +16,10 @@
16
16
 
17
17
  - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
18
18
  {
19
- return [self getBundleURL];
19
+ return [self bundleURL];
20
20
  }
21
21
 
22
- - (NSURL *)getBundleURL
22
+ - (NSURL *)bundleURL
23
23
  {
24
24
  #if DEBUG
25
25
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];
@@ -39,7 +39,7 @@
39
39
  <string>LaunchScreen</string>
40
40
  <key>UIRequiredDeviceCapabilities</key>
41
41
  <array>
42
- <string>armv7</string>
42
+ <string>armv64</string>
43
43
  </array>
44
44
  <key>UISupportedInterfaceOrientations</key>
45
45
  <array>
@@ -0,0 +1,37 @@
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
+ <key>NSPrivacyAccessedAPITypes</key>
6
+ <array>
7
+ <dict>
8
+ <key>NSPrivacyAccessedAPIType</key>
9
+ <string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
10
+ <key>NSPrivacyAccessedAPITypeReasons</key>
11
+ <array>
12
+ <string>C617.1</string>
13
+ </array>
14
+ </dict>
15
+ <dict>
16
+ <key>NSPrivacyAccessedAPIType</key>
17
+ <string>NSPrivacyAccessedAPICategoryUserDefaults</string>
18
+ <key>NSPrivacyAccessedAPITypeReasons</key>
19
+ <array>
20
+ <string>CA92.1</string>
21
+ </array>
22
+ </dict>
23
+ <dict>
24
+ <key>NSPrivacyAccessedAPIType</key>
25
+ <string>NSPrivacyAccessedAPICategorySystemBootTime</string>
26
+ <key>NSPrivacyAccessedAPITypeReasons</key>
27
+ <array>
28
+ <string>35F9.1</string>
29
+ </array>
30
+ </dict>
31
+ </array>
32
+ <key>NSPrivacyCollectedDataTypes</key>
33
+ <array/>
34
+ <key>NSPrivacyTracking</key>
35
+ <false/>
36
+ </dict>
37
+ </plist>
@@ -14,6 +14,7 @@
14
14
  13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
15
15
  7699B88040F8A987B510C191 /* libPods-TapjoyReactNativeSdkExample-TapjoyReactNativeSdkExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-TapjoyReactNativeSdkExample-TapjoyReactNativeSdkExampleTests.a */; };
16
16
  81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
17
+ B58E4E7E8EDB14A1C5F1CBAA /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = EDEB0408D1807C711EE2B6BB /* PrivacyInfo.xcprivacy */; };
17
18
  /* End PBXBuildFile section */
18
19
 
19
20
  /* Begin PBXContainerItemProxy section */
@@ -44,6 +45,7 @@
44
45
  81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = TapjoyReactNativeSdkExample/LaunchScreen.storyboard; sourceTree = "<group>"; };
45
46
  89C6BE57DB24E9ADA2F236DE /* Pods-TapjoyReactNativeSdkExample-TapjoyReactNativeSdkExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-TapjoyReactNativeSdkExample-TapjoyReactNativeSdkExampleTests.release.xcconfig"; path = "Target Support Files/Pods-TapjoyReactNativeSdkExample-TapjoyReactNativeSdkExampleTests/Pods-TapjoyReactNativeSdkExample-TapjoyReactNativeSdkExampleTests.release.xcconfig"; sourceTree = "<group>"; };
46
47
  ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
48
+ EDEB0408D1807C711EE2B6BB /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = TapjoyReactNativeSdkExample/PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
47
49
  /* End PBXFileReference section */
48
50
 
49
51
  /* Begin PBXFrameworksBuildPhase section */
@@ -92,6 +94,7 @@
92
94
  13B07FB61A68108700A75B9A /* Info.plist */,
93
95
  81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
94
96
  13B07FB71A68108700A75B9A /* main.m */,
97
+ EDEB0408D1807C711EE2B6BB /* PrivacyInfo.xcprivacy */,
95
98
  );
96
99
  name = TapjoyReactNativeSdkExample;
97
100
  sourceTree = "<group>";
@@ -244,6 +247,7 @@
244
247
  files = (
245
248
  81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
246
249
  13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
250
+ B58E4E7E8EDB14A1C5F1CBAA /* PrivacyInfo.xcprivacy in Resources */,
247
251
  );
248
252
  runOnlyForDeploymentPostprocessing = 0;
249
253
  };
@@ -649,6 +653,7 @@
649
653
  isa = XCBuildConfiguration;
650
654
  buildSettings = {
651
655
  ALWAYS_SEARCH_USER_PATHS = YES;
656
+ CC = "";
652
657
  CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
653
658
  CLANG_CXX_LANGUAGE_STANDARD = "c++20";
654
659
  CLANG_CXX_LIBRARY = "libc++";
@@ -676,6 +681,7 @@
676
681
  CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
677
682
  "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
678
683
  COPY_PHASE_STRIP = NO;
684
+ CXX = "";
679
685
  ENABLE_STRICT_OBJC_MSGSEND = YES;
680
686
  ENABLE_TESTABILITY = YES;
681
687
  "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
@@ -696,6 +702,8 @@
696
702
  GCC_WARN_UNUSED_FUNCTION = YES;
697
703
  GCC_WARN_UNUSED_VARIABLE = YES;
698
704
  IPHONEOS_DEPLOYMENT_TARGET = 13.4;
705
+ LD = "";
706
+ LDPLUSPLUS = "";
699
707
  LD_RUNPATH_SEARCH_PATHS = (
700
708
  /usr/lib/swift,
701
709
  "$(inherited)",
@@ -714,12 +722,7 @@
714
722
  "-DFOLLY_MOBILE=1",
715
723
  "-DFOLLY_USE_LIBCPP=1",
716
724
  );
717
- OTHER_LDFLAGS = (
718
- "$(inherited)-Wl",
719
- "-ld_classic",
720
- "-Wl",
721
- "-ld_classic",
722
- );
725
+ OTHER_LDFLAGS = "$(inherited)";
723
726
  REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
724
727
  SDKROOT = iphoneos;
725
728
  TARGETED_DEVICE_FAMILY = "1,2";
@@ -731,6 +734,7 @@
731
734
  isa = XCBuildConfiguration;
732
735
  buildSettings = {
733
736
  ALWAYS_SEARCH_USER_PATHS = YES;
737
+ CC = "";
734
738
  CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
735
739
  CLANG_CXX_LANGUAGE_STANDARD = "c++20";
736
740
  CLANG_CXX_LIBRARY = "libc++";
@@ -758,6 +762,7 @@
758
762
  CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
759
763
  "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
760
764
  COPY_PHASE_STRIP = YES;
765
+ CXX = "";
761
766
  ENABLE_NS_ASSERTIONS = NO;
762
767
  ENABLE_STRICT_OBJC_MSGSEND = YES;
763
768
  "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386;
@@ -774,6 +779,8 @@
774
779
  GCC_WARN_UNUSED_FUNCTION = YES;
775
780
  GCC_WARN_UNUSED_VARIABLE = YES;
776
781
  IPHONEOS_DEPLOYMENT_TARGET = 13.4;
782
+ LD = "";
783
+ LDPLUSPLUS = "";
777
784
  LD_RUNPATH_SEARCH_PATHS = (
778
785
  /usr/lib/swift,
779
786
  "$(inherited)",
@@ -791,13 +798,7 @@
791
798
  "-DFOLLY_MOBILE=1",
792
799
  "-DFOLLY_USE_LIBCPP=1",
793
800
  );
794
- OTHER_LDFLAGS = (
795
- "$(inherited)",
796
- "-Wl",
797
- "-ld_classic",
798
- "-Wl",
799
- "-ld_classic",
800
- );
801
+ OTHER_LDFLAGS = "$(inherited)";
801
802
  REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native";
802
803
  SDKROOT = iphoneos;
803
804
  TARGETED_DEVICE_FAMILY = "1,2";
@@ -12,7 +12,7 @@ const modules = Object.keys({
12
12
 
13
13
  /**
14
14
  * Metro configuration
15
- * https://facebook.github.io/metro/docs/configuration
15
+ * https://reactnative.dev/docs/metro
16
16
  *
17
17
  * @type {import('metro-config').MetroConfig}
18
18
  */
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "TapjoyReactNativeSdkExample",
3
- "version": "13.4.1",
3
+ "version": "14.0.1",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "android": "react-native run-android",
@@ -16,7 +16,7 @@
16
16
  "@react-navigation/native": "^6.1.9",
17
17
  "dayjs": "^1.11.10",
18
18
  "react": "18.2.0",
19
- "react-native": "0.73.2",
19
+ "react-native": "0.74.1",
20
20
  "react-native-gesture-handler": "^2.14.1",
21
21
  "react-native-picker-select": "^9.0.0",
22
22
  "react-native-reanimated": "^3.6.1",
@@ -30,7 +30,7 @@
30
30
  "@babel/preset-env": "^7.23.8",
31
31
  "@babel/runtime": "^7.23.8",
32
32
  "babel-plugin-module-resolver": "^5.0.0",
33
- "@react-native/metro-config": "^0.73.3",
33
+ "@react-native/metro-config": "^0.74.83",
34
34
  "metro-react-native-babel-preset": "0.77.0"
35
35
  },
36
36
  "engines": {
@@ -1,29 +1,38 @@
1
- import * as React from 'react';
1
+ import React, { useState } from 'react';
2
2
  import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
3
3
  import { NavigationContainer } from '@react-navigation/native';
4
+ import { Dimensions } from 'react-native';
4
5
  import MainScreen from './MainScreen';
5
6
  import OfferwallScreen from './OfferwallScreen';
6
7
  import OfferwallDiscoverScreen from './OfferwallDiscoverScreen';
7
8
  import UserProperties from './UserProperties';
8
9
  import styles from './Styles';
10
+ import { ConnectContext } from './ConnectContext';
9
11
 
10
12
  const Tab = createBottomTabNavigator();
13
+ const windowHeight = Dimensions.get('window').height;
14
+
11
15
 
12
16
  export default function App() {
17
+ const [isSdkConnected, setIsSdkConnected] = useState(false);
13
18
  return (
14
19
  <NavigationContainer>
15
- <Tab.Navigator
16
- screenOptions={{
17
- tabBarLabelPosition: 'beside-icon',
18
- tabBarLabelStyle: styles.tabBarLabelStyle,
19
- tabBarIconStyle: styles.tabBarIconStyle,
20
- }}
20
+ <ConnectContext.Provider value={{ isSdkConnected, setIsSdkConnected }}>
21
+ <Tab.Navigator
22
+ screenOptions={{
23
+ scrollEnabled: true,
24
+ tabBarLabelPosition: 'beside-icon',
25
+ tabBarLabelStyle: styles.tabBarLabelStyle,
26
+ tabBarIconStyle: styles.tabBarIconStyle,
27
+ tabBarStyle: { height: windowHeight * 0.075, paddingRight: 10},
28
+ }}
21
29
  >
22
- <Tab.Screen name="Main" component={MainScreen} />
23
- <Tab.Screen name="Offerwall" component={OfferwallScreen} />
24
- <Tab.Screen name="Discover" component={OfferwallDiscoverScreen} />
25
- <Tab.Screen name="User Properties" component={UserProperties} />
26
- </Tab.Navigator>
30
+ <Tab.Screen name="Main" component={MainScreen} />
31
+ <Tab.Screen name="Offerwall" component={OfferwallScreen} />
32
+ <Tab.Screen name="Discover" component={OfferwallDiscoverScreen} />
33
+ <Tab.Screen name="User" component={UserProperties} />
34
+ </Tab.Navigator>
35
+ </ConnectContext.Provider>
27
36
  </NavigationContainer>
28
37
  );
29
38
  }
@@ -0,0 +1,11 @@
1
+ import React, { createContext, useState } from 'react';
2
+
3
+ interface ConnectContextProps {
4
+ isSdkConnected: boolean;
5
+ setIsSdkConnected: (newIsSdkConnected: boolean) => void;
6
+ }
7
+
8
+ export const ConnectContext = createContext<ConnectContextProps>({
9
+ isSdkConnected: false,
10
+ setIsSdkConnected: () => {},
11
+ });
@@ -1,4 +1,4 @@
1
- import React, { useState, useEffect } from 'react';
1
+ import React, { useState, useEffect, useContext } from 'react';
2
2
  import {
3
3
  View,
4
4
  SafeAreaView,
@@ -17,11 +17,13 @@ import {
17
17
  import styles from './Styles';
18
18
  import Button from './Button';
19
19
  import Tapjoy, { TJVersion, TJConnect } from 'tapjoy-react-native-sdk';
20
+ import { ConnectContext } from './ConnectContext';
20
21
 
21
22
  const MainScreen: React.FC = () => {
22
23
  const [sdkKey, setSdkKey] = useState<string>('');
23
24
  const [isConnecting, setIsConnecting] = useState<boolean>(false);
24
25
  const [statusLabelText, setStatusLabelText] = useState('Status Message');
26
+ const { isSdkConnected, setIsSdkConnected } = useContext(ConnectContext);
25
27
 
26
28
  interface TapjoyEvent {
27
29
  name: string;
@@ -56,8 +58,9 @@ const MainScreen: React.FC = () => {
56
58
  await AsyncStorage.setItem('sdkKey', sdkKey);
57
59
 
58
60
  Tapjoy.setDebugEnabled(true);
59
- let userId = await AsyncStorage.getItem('userId');
60
- let flags: object = { TJC_OPTION_USER_ID: userId };
61
+ // Use the following line to set the user id
62
+ // let flags: object = { TJC_OPTION_USER_ID: userId };
63
+ let flags: object = {};
61
64
  let trackingStatus = await getTrackingStatus();
62
65
  if (trackingStatus !== 'authorized' && trackingStatus !== 'unavailable') {
63
66
  await requestTrackingPermission();
@@ -80,8 +83,11 @@ const MainScreen: React.FC = () => {
80
83
  setIsConnecting(false);
81
84
  setStatusLabelText(
82
85
  'Tapjoy SDK Connected' +
83
- (userId !== null ? `\nFlags: ${JSON.stringify(flags)}` : '')
86
+ (Object.keys(flags).length > 0
87
+ ? `\nFlags: ${JSON.stringify(flags)}`
88
+ : '')
84
89
  );
90
+ setIsSdkConnected(true);
85
91
  } catch (error: any) {
86
92
  setStatusLabelText(
87
93
  `Tapjoy SDK failed to connect. code: ${error.code}, message: ${error.message}`
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useRef, useState } from 'react';
1
+ import React, { useEffect, useRef, useState, useContext } from 'react';
2
2
  import { useFocusEffect } from '@react-navigation/native';
3
3
  import {
4
4
  FlatList,
@@ -14,6 +14,7 @@ import AsyncStorage from '@react-native-async-storage/async-storage';
14
14
  import dayjs from 'dayjs';
15
15
  import Button from './Button';
16
16
  import styles from './Styles';
17
+ import { ConnectContext } from './ConnectContext';
17
18
 
18
19
  const OfferwallDiscoverScreen: React.FC = () => {
19
20
  const widthChangedManually = useRef(false);
@@ -24,17 +25,11 @@ const OfferwallDiscoverScreen: React.FC = () => {
24
25
 
25
26
  const [offerwallPlacementName, _setOfferwallPlacementName] =
26
27
  useState<string>('offerwall_discover');
27
- const [isSdkConnected, setIsSdkConnected] = useState<boolean>(false);
28
28
 
29
29
  const [logData, setLogData] = useState<Array<string>>([]);
30
30
  const owdRef: React.MutableRefObject<TJOfferwallDiscoverView | null> =
31
31
  useRef<TJOfferwallDiscoverView | null>(null);
32
-
33
- useFocusEffect(
34
- React.useCallback(() => {
35
- setIsSdkConnected(Tapjoy.isConnected());
36
- }, [])
37
- );
32
+ const { isSdkConnected, setIsSdkConnected } = useContext(ConnectContext);
38
33
 
39
34
  useEffect(() => {
40
35
  AsyncStorage.getItem('owdPlacementName').then((value) => {
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useState } from 'react';
1
+ import React, { useEffect, useState, useContext } from 'react';
2
2
  import { useFocusEffect } from '@react-navigation/native';
3
3
  import {
4
4
  FlatList,
@@ -12,16 +12,16 @@ import dayjs from 'dayjs';
12
12
  import AsyncStorage from '@react-native-async-storage/async-storage';
13
13
  import Button from './Button';
14
14
  import styles, { pickerSelectStyles } from './Styles';
15
- import Tapjoy, { TJPlacement } from 'tapjoy-react-native-sdk';
15
+ import Tapjoy, { TJPlacement, TJPurchase } from 'tapjoy-react-native-sdk';
16
16
  import RNPickerSelect from 'react-native-picker-select';
17
17
  import TJEntryPoint from '../../src/TJEntryPoint';
18
+ import { ConnectContext } from './ConnectContext';
18
19
 
19
20
  let offerwallPlacement: TJPlacement;
20
21
 
21
22
  const OfferwallScreen: React.FC = () => {
22
23
  const [offerwallPlacementName, _setOfferwallPlacementName] =
23
24
  useState<string>('offerwall_unit');
24
- const [isSdkConnected, setIsSdkConnected] = useState<boolean>(false);
25
25
  const [placementState, setPlacementState] = useState<string>('');
26
26
  const [logData, setLogData] = useState<Array<string>>([]);
27
27
  const [entryPoint, setEntryPoint] = useState<TJEntryPoint>(
@@ -30,12 +30,7 @@ const OfferwallScreen: React.FC = () => {
30
30
  const [currencyId, _setCurrencyId] = useState<string>('');
31
31
  const [currencyBalance, _setCurrencyBalance] = useState<string>('');
32
32
  const [requiredAmount, _setRequiredAmount] = useState<string>('');
33
-
34
- useFocusEffect(
35
- React.useCallback(() => {
36
- setIsSdkConnected(Tapjoy.isConnected());
37
- }, [])
38
- );
33
+ const { isSdkConnected, setIsSdkConnected } = useContext(ConnectContext);
39
34
 
40
35
  useEffect(() => {
41
36
  retrieveStoredPlacementName();
@@ -204,6 +199,14 @@ const OfferwallScreen: React.FC = () => {
204
199
  setPlacementState('loading');
205
200
  };
206
201
 
202
+ const sendPurchaseAction = () => {
203
+ const offerwallPurchase = new TJPurchase();
204
+ let currency = 'USD';
205
+ let price = 0.99;
206
+ offerwallPurchase.trackPurchase(currency, price);
207
+ addLogItem(`Track Purchase Event - Currency: ${currency} Price: ${price}`);
208
+ };
209
+
207
210
  const showPlacement = () => {
208
211
  addLogItem(offerwallPlacement.name);
209
212
  if (placementState !== 'ready') {
@@ -238,8 +241,10 @@ const OfferwallScreen: React.FC = () => {
238
241
  };
239
242
 
240
243
  const addLogItem = (item: string) => {
241
- logData.push(dayjs(new Date()).format('HH:mm:ss') + ' ' + item);
242
- setLogData(logData);
244
+ setLogData((prevLogData) => [
245
+ ...prevLogData,
246
+ dayjs(new Date()).format('HH:mm:ss') + ' ' + item,
247
+ ]);
243
248
  };
244
249
 
245
250
  const entryPointArray = [
@@ -352,6 +357,13 @@ const OfferwallScreen: React.FC = () => {
352
357
  title={'\u2573'}
353
358
  />
354
359
  </View>
360
+ <View style={styles.buttonContainer}>
361
+ <Button
362
+ onPress={sendPurchaseAction}
363
+ disabled={!isSdkConnected}
364
+ title={'Purchase'}
365
+ />
366
+ </View>
355
367
  </SafeAreaView>
356
368
  </ScrollView>
357
369
  <View style={styles.owLogContainer}>
@@ -128,7 +128,7 @@ const styles = StyleSheet.create({
128
128
  },
129
129
  tabBarLabelStyle: {
130
130
  fontWeight: '400',
131
- fontSize: 10,
131
+ fontSize: 12,
132
132
  },
133
133
  tabBarIconStyle: {
134
134
  display: 'none',
@@ -23,8 +23,9 @@ const UserProperties: React.FC = () => {
23
23
 
24
24
  const [statusLabelText, setStatusLabelText] =
25
25
  useState<string>('Status Message');
26
- const [userId, _setUserId] = useState<string>('');
26
+ const [userId, setUserId] = useState<string>('');
27
27
  const [maxLevel, _setMaxLevel] = useState<string>('');
28
+ const [userLevel, _setUserLevel] = useState<string>('');
28
29
  const [USPrivacy, setUSPrivacy] = useState<string>('');
29
30
  const [isSubjectToGDPR, setSubjectToGDPR] = useState<TJStatus>(
30
31
  TJStatus.Unknown
@@ -60,23 +61,25 @@ const UserProperties: React.FC = () => {
60
61
  if (isFocused) {
61
62
  retrievePrivacyPolicy().then();
62
63
  retrieveUserSegment().then();
64
+ retrieveUserId().then();
65
+ retrieveUserLevel().then();
66
+ retrieveMaxLevel().then();
63
67
  }
64
68
  }, [isFocused]);
65
69
 
66
- useEffect(() => {
67
- retrieveUserId().then();
68
- });
69
-
70
- useEffect(() => {
71
- retrieveMaxLevel().then();
72
- });
73
-
74
- const retrieveUserId = async () => {
70
+ const retrieveUserLevel = async () => {
75
71
  try {
76
- const value = await AsyncStorage.getItem('userId');
72
+ const value = await Tapjoy.getUserLevel();
77
73
  if (value !== null) {
78
- await setUserId(value);
74
+ await setUserLevel(value.toString());
79
75
  }
76
+ } catch (error) {
77
+ setStatusLabelText(`Failed to retrieve User Level: ${error}`);
78
+ }
79
+ };
80
+ const retrieveUserId = async () => {
81
+ try {
82
+ await setUserId(await Tapjoy.getUserId());
80
83
  } catch (error) {
81
84
  setStatusLabelText(`Failed to retrieve User ID: ${error}`);
82
85
  }
@@ -151,10 +154,15 @@ const UserProperties: React.FC = () => {
151
154
  try {
152
155
  let trimmedUserId = userId.trim();
153
156
  let trimmedMaxLevel = maxLevel.trim();
157
+ let trimmedUserLevel = userLevel.trim();
154
158
  let maxLevelValue = -1;
155
159
  if (trimmedMaxLevel.length > 0) {
156
160
  maxLevelValue = parseInt(trimmedMaxLevel);
157
161
  }
162
+ let userLevelValue = -1;
163
+ if (trimmedUserLevel.length > 0) {
164
+ userLevelValue = parseInt(trimmedUserLevel);
165
+ }
158
166
  let privacyPolicy = new TJPrivacyPolicy();
159
167
  privacyPolicy.setSubjectToGDPRStatus(isSubjectToGDPR);
160
168
  privacyPolicy.setBelowConsentAgeStatus(isBelowConsentAge);
@@ -164,9 +172,9 @@ const UserProperties: React.FC = () => {
164
172
  privacyPolicy.optOutAdvertisingID(optOut);
165
173
  }
166
174
  Tapjoy.setUserSegment(userSegment);
167
- await AsyncStorage.setItem('userId', trimmedUserId);
168
175
  await AsyncStorage.setItem('maxLevel', trimmedMaxLevel);
169
176
  await Tapjoy.setMaxLevel(maxLevelValue);
177
+ await Tapjoy.setUserLevel(userLevelValue);
170
178
  await Tapjoy.setUserId(trimmedUserId);
171
179
  setStatusLabelText(`User ID set:\n"${trimmedUserId}"`);
172
180
  } catch (error) {
@@ -174,18 +182,16 @@ const UserProperties: React.FC = () => {
174
182
  }
175
183
  };
176
184
 
177
- const setUserId = async (newUserId: string) => {
178
- _setUserId(newUserId);
179
- let trimmedUserId = newUserId.trim();
180
- await AsyncStorage.setItem('userId', trimmedUserId);
181
- };
182
-
183
185
  const setMaxLevel = async (maxLevel: string) => {
184
186
  _setMaxLevel(maxLevel);
185
187
  let trimmedMaxLevel = maxLevel.trim();
186
188
  await AsyncStorage.setItem('maxLevel', trimmedMaxLevel);
187
189
  };
188
190
 
191
+ const setUserLevel = async (userLevel: string) => {
192
+ _setUserLevel(userLevel);
193
+ };
194
+
189
195
  const handleUSPrivacy = async (newUSPrivacy: string) => {
190
196
  setUSPrivacy(newUSPrivacy);
191
197
  };
@@ -198,6 +204,10 @@ const UserProperties: React.FC = () => {
198
204
  await setMaxLevel('');
199
205
  };
200
206
 
207
+ const handleClearUserLevel = async () => {
208
+ await setUserLevel('');
209
+ };
210
+
201
211
  const handleAddUserTag = async () => {
202
212
  Tapjoy.addUserTag(userTag);
203
213
  setUserTag('');
@@ -270,6 +280,22 @@ const UserProperties: React.FC = () => {
270
280
  title={'\u2573'}
271
281
  />
272
282
  </View>
283
+ <View style={styles.inputContainer}>
284
+ <Text style={styles.userPropertiesLabel}>User Level:</Text>
285
+ <TextInput
286
+ style={styles.textInput}
287
+ value={userLevel}
288
+ keyboardType={'numeric'}
289
+ onChangeText={setUserLevel}
290
+ placeholder="Enter user level"
291
+ placeholderTextColor="#888"
292
+ />
293
+ <Button
294
+ style={styles.clearButton}
295
+ onPress={handleClearUserLevel}
296
+ title={'\u2573'}
297
+ />
298
+ </View>
273
299
  <View style={styles.inputContainer}>
274
300
  <Text style={styles.userPropertiesLabel}>User Tags:</Text>
275
301
  <TextInput
@@ -8,9 +8,12 @@ RCT_EXTERN_METHOD(connect:(NSString *)sdkKey connectFlags:(NSDictionary *)connec
8
8
  RCT_EXTERN_METHOD(setDebugEnabled:(BOOL)enabled)
9
9
  RCT_EXTERN__BLOCKING_SYNCHRONOUS_METHOD(isConnected)
10
10
  RCT_EXTERN_METHOD(setUserId:(NSString *)userId resolve:(RCTPromiseResolveBlock *)resolve reject:(RCTPromiseRejectBlock)reject)
11
+ RCT_EXTERN_METHOD(getUserId:(RCTPromiseResolveBlock *)resolve reject:(RCTPromiseRejectBlock)reject)
11
12
  RCT_EXTERN_METHOD(setUserSegment:(nonnull NSNumber *)userSegment)
12
13
  RCT_EXTERN_METHOD(getUserSegment: (RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
13
14
  RCT_EXTERN_METHOD(setMaxLevel:(int)maxLevel)
15
+ RCT_EXTERN_METHOD(setUserLevel:(int)userLevel)
16
+ RCT_EXTERN_METHOD(getUserLevel: (RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
14
17
  RCT_EXTERN_METHOD(getUserTags: (RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)
15
18
  RCT_EXTERN_METHOD(setUserTags:(NSArray *)tags)
16
19
  RCT_EXTERN_METHOD(clearUserTags)
@@ -36,10 +39,7 @@ RCT_EXTERN_METHOD(spendCurrency:(int)amount resolve:(RCTPromiseResolveBlock *)re
36
39
  RCT_EXTERN_METHOD(awardCurrency:(int)amount resolve:(RCTPromiseResolveBlock *)resolve reject:(RCTPromiseRejectBlock)reject)
37
40
 
38
41
  #pragma mark - Privacy
39
- RCT_EXTERN_METHOD(setSubjectToGDPR:(BOOL)isSubjectToGDPR)
40
- RCT_EXTERN_METHOD(setBelowConsentAge:(BOOL)isBelowConsentAge)
41
42
  RCT_EXTERN_METHOD(setUSPrivacy:(NSString *)privacyValue)
42
- RCT_EXTERN_METHOD(setUserConsent:(NSString *)userConsent)
43
43
  RCT_EXTERN_METHOD(setBelowConsentAgeStatus:(nonnull NSNumber *)isBelowConsentAgeStatus)
44
44
  RCT_EXTERN_METHOD(setSubjectToGDPRStatus:(nonnull NSNumber *)isSubjectToGDPRStatus)
45
45
  RCT_EXTERN_METHOD(setUserConsentStatus:(nonnull NSNumber *)userConsentStatus)
@@ -52,4 +52,7 @@ RCT_EXTERN_METHOD(getUSPrivacy: (RCTPromiseResolveBlock)resolve reject:(RCTPromi
52
52
  return NO;
53
53
  }
54
54
 
55
+ #pragma mark - Purchase
56
+ RCT_EXTERN_METHOD(trackPurchase:(NSString *)currencyCode price:(nonnull NSNumber *)price);
57
+
55
58
  @end
@@ -115,13 +115,17 @@ class TapjoyReactNativeSdk: RCTEventEmitter {
115
115
  }
116
116
  }
117
117
 
118
+ @objc func getUserId(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
119
+ resolve(Tapjoy.getUserID())
120
+ }
121
+
118
122
  /**
119
123
  * Sets the segment of the user
120
124
  *
121
125
  * @param userSegment TJSegment enum 0 (non-payer), 1 (payer), 2 (VIP), -1 (unknown)
122
126
  */
123
127
  @objc func setUserSegment(_ userSegment: NSNumber) {
124
- let segmentMap: [Int: TJSegment] = [
128
+ let segmentMap: [Int: Segment] = [
125
129
  0: .nonPayer,
126
130
  1: .payer,
127
131
  2: .VIP
@@ -152,6 +156,24 @@ class TapjoyReactNativeSdk: RCTEventEmitter {
152
156
  Tapjoy.setMaxLevel(maxLevel)
153
157
  }
154
158
 
159
+ @objc func setUserLevel(_ userLevel: Int32) {
160
+ Tapjoy.setUserLevel(userLevel)
161
+ }
162
+
163
+ /**
164
+ * Gets the level of the user.
165
+ *
166
+ * @return the level of the user.
167
+ */
168
+ @objc func getUserLevel(_ resolve: @escaping RCTPromiseResolveBlock, reject: @escaping RCTPromiseRejectBlock) {
169
+ do {
170
+ let level = Tapjoy.getUserLevel()
171
+ resolve(level)
172
+ } catch let error {
173
+ reject("getUserLevel failed", "Failed to get user level", error)
174
+ }
175
+ }
176
+
155
177
  /**
156
178
  * Returns a string set which contains tags on the user.
157
179
  *
@@ -391,16 +413,6 @@ class TapjoyReactNativeSdk: RCTEventEmitter {
391
413
  }
392
414
  })
393
415
  }
394
-
395
- // MARK: - Privacy
396
- /**
397
- Indicate if the user falls in any of the GDPR applicable countries.
398
- - Parameter isSubjectToGDPR: true for enabling and false for disabling.
399
- */
400
- @available(*, deprecated, message: "Use `setSubjectToGDPRStatus(_:)` instead.")
401
- @objc func setSubjectToGDPR(_ isSubjectToGDPR: Bool) {
402
- Tapjoy.getPrivacyPolicy().setSubjectToGDPR(isSubjectToGDPR)
403
- }
404
416
 
405
417
  /**
406
418
  * This can be used by the integrating App to indicate if the user falls in any of the GDPR applicable countries
@@ -415,14 +427,6 @@ class TapjoyReactNativeSdk: RCTEventEmitter {
415
427
  TJPrivacyPolicy.sharedInstance().subjectToGDPRStatus = subjectToGDPRStatus
416
428
  }
417
429
 
418
- /**
419
- This method will set ad_tracking_enabled to false for Tapjoy which only shows the user contextual ads. No ad tracking will be done on this user.
420
- - Parameter isBelowConsentAge: true if the user is affected by COPPA, false if they are not.
421
- */
422
- @available(*, deprecated, message: "Use `setBelowConsentAgeStatus(_:)` instead.")
423
- @objc func setBelowConsentAge(_ isBelowConsentAge: Bool) {
424
- Tapjoy.getPrivacyPolicy().setBelowConsentAge(isBelowConsentAge)
425
- }
426
430
  /**
427
431
  * In the US, the Children’s Online Privacy Protection Act (COPPA) imposes certain requirements on operators of online services that (a)
428
432
  * have actual knowledge that the connected user is a child under 13 years of age, or (b) operate services (including apps) that are
@@ -450,14 +454,6 @@ class TapjoyReactNativeSdk: RCTEventEmitter {
450
454
  Tapjoy.getPrivacyPolicy().usPrivacy = privacyValue
451
455
  }
452
456
 
453
- /**
454
- * This is used for sending User's consent to behavioral advertising such as in the context of GDPR
455
- * - Parameter userConsent: The value can be "0" (User has not provided consent), "1" (User has provided consent) or a daisybit string as suggested in IAB's Transparency and Consent Framework
456
- */
457
- @available(*, deprecated, message: "Use `setUserConsentStatus(_:)` instead.")
458
- @objc func setUserConsent(_ userConsent: String) {
459
- Tapjoy.getPrivacyPolicy().setUserConsent(userConsent)
460
- }
461
457
  /**
462
458
  * This is used for sending User's consent to behavioral advertising such as in the context of GDPR
463
459
  * The consent value can be "0" (User has not provided consent), "1" (User has provided consent) or
@@ -539,6 +535,20 @@ class TapjoyReactNativeSdk: RCTEventEmitter {
539
535
  return TJStatus.unknown
540
536
  }
541
537
  }
538
+
539
+ // MARK: - Purchase
540
+ /**
541
+ * Tracks a purchase
542
+ *
543
+ * @param currencyCode
544
+ * the currency code of price as an alphabetic currency code
545
+ * specified in ISO 4217, i.e. "USD", "KRW"
546
+ * @param price
547
+ * the price of product
548
+ */
549
+ @objc func trackPurchase(_ currencyCode: String, price: NSNumber) {
550
+ Tapjoy.trackPurchase(withCurrencyCode: currencyCode, price: price.doubleValue)
551
+ }
542
552
  }
543
553
 
544
554
  extension TapjoyReactNativeSdk: TJPlacementDelegate {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tapjoy-react-native-sdk",
3
- "version": "13.4.1",
3
+ "version": "14.0.1",
4
4
  "description": "ReactNative Plugin for Tapjoy SDK",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -48,9 +48,11 @@
48
48
  "bootstrap": "yarn example && yarn install && yarn example pods",
49
49
  "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build temp package",
50
50
  "prepare-repo": "rm -rf temp package && mkdir temp && cd temp && git clone git@github.com:Tapjoy/react-native-sdk . && rm -rf *",
51
+ "prepare-staging-repo": "rm -rf temp package && mkdir temp && cd temp && git clone git@github.com:Tapjoy/react-native-sdk-staging.git . && rm -rf *",
51
52
  "copy-pack": "npm pack && tar xvzf tapjoy-react-native*.tgz && cp -af ./package/* ./temp && rm tapjoy-react-native*.tgz",
52
53
  "push": "cd temp && git add . && export VERSION=`node -p \"require('./package.json').version\"` && git commit -m \"Release $VERSION\" && git push",
53
- "publish-npm": "yarn prepare-repo && yarn copy-pack && yarn push && cd temp && npm config set //registry.npmjs.org/:_authToken $NPM_TOKEN && release-it --no-increment --ci"
54
+ "publish-npm": "yarn prepare-repo && yarn copy-pack && yarn push && cd temp && npm config set //registry.npmjs.org/:_authToken $NPM_TOKEN && npm pkg fix && npm publish",
55
+ "publish-staging-npm": "yarn prepare-staging-repo && yarn copy-pack && yarn push && cd temp && npm config set //registry.npmjs.org/:_authToken $NPM_TOKEN && npm pkg fix && npm publish --dry-run"
54
56
  },
55
57
  "keywords": [
56
58
  "react-native",
@@ -59,7 +61,7 @@
59
61
  "tapjoy",
60
62
  "offerwall"
61
63
  ],
62
- "repository": "https://github.com/Tapjoy/react-native-sdk",
64
+ "repository.url": "https://github.com/Tapjoy/react-native-sdk",
63
65
  "author": "Tapjoy <grow_tapjoy_sdk@unity3d.com> (https://dev.tapjoy.com)",
64
66
  "license": "SEE LICENSE IN <LICENSE>",
65
67
  "bugs": {
@@ -72,8 +74,7 @@
72
74
  "devDependencies": {
73
75
  "@commitlint/config-conventional": "^18.4.4",
74
76
  "@react-native-community/eslint-config": "^3.2.0",
75
- "@react-native/metro-config": "^0.73.3",
76
- "@release-it/conventional-changelog": "^8.0.1",
77
+ "@react-native/metro-config": "^0.74.83",
77
78
  "@types/jest": "^29.5.11",
78
79
  "@types/react": "^18.2.48",
79
80
  "commitlint": "^18.4.4",
@@ -84,10 +85,8 @@
84
85
  "jest": "^29.7.0",
85
86
  "pod-install": "^0.2.0",
86
87
  "prettier": "^3.2.4",
87
- "react": "18.2.0",
88
- "react-native": "^0.73.2",
89
- "react-native-builder-bob": "^0.23.2",
90
- "release-it": "^17.0.1",
88
+ "react": "^18.3.1",
89
+ "react-native": "^0.74.1",
91
90
  "typescript": "^5.3.3"
92
91
  },
93
92
  "resolutions": {
@@ -113,19 +112,6 @@
113
112
  "@commitlint/config-conventional"
114
113
  ]
115
114
  },
116
- "release-it": {
117
- "npm": {
118
- "publish": true
119
- },
120
- "github": {
121
- "release": false
122
- },
123
- "plugins": {
124
- "@release-it/conventional-changelog": {
125
- "preset": "angular"
126
- }
127
- }
128
- },
129
115
  "eslintConfig": {
130
116
  "root": true,
131
117
  "extends": [
@@ -156,20 +142,6 @@
156
142
  "trailingComma": "es5",
157
143
  "useTabs": false
158
144
  },
159
- "react-native-builder-bob": {
160
- "source": "src",
161
- "output": "lib",
162
- "targets": [
163
- "commonjs",
164
- "module",
165
- [
166
- "typescript",
167
- {
168
- "project": "tsconfig.build.json"
169
- }
170
- ]
171
- ]
172
- },
173
145
  "dependencies": {
174
146
  "eventemitter3": "^5.0.0"
175
147
  }
@@ -14,14 +14,6 @@ class TJPrivacyPolicy {
14
14
  }
15
15
  }
16
16
 
17
- setBelowConsentAge(isBelowConsentAge: boolean): void {
18
- Tapjoy.setBelowConsentAge(isBelowConsentAge);
19
- }
20
-
21
- setSubjectToGDPR(isSubjectToGDPR: boolean): void {
22
- Tapjoy.setSubjectToGDPR(isSubjectToGDPR);
23
- }
24
-
25
17
  async getSubjectToGDPR(): Promise<TJStatus> {
26
18
  try {
27
19
  let isSubjectToGDPR: TJStatus = await Tapjoy.getSubjectToGDPR();
@@ -46,10 +38,6 @@ class TJPrivacyPolicy {
46
38
  }
47
39
  }
48
40
 
49
- setUserConsent(userConsent: string): void {
50
- Tapjoy.setUserConsent(userConsent);
51
- }
52
-
53
41
  async getUserConsent(): Promise<TJStatus> {
54
42
  try {
55
43
  let userConsent: TJStatus = await Tapjoy.getUserConsent();
@@ -0,0 +1,11 @@
1
+ import { NativeModules } from 'react-native';
2
+
3
+ const Tapjoy = NativeModules.TapjoyReactNativeSdk;
4
+
5
+ class TJPurchase {
6
+ trackPurchase(currencyCode: string, price: number): void {
7
+ Tapjoy.trackPurchase(currencyCode, price);
8
+ }
9
+ }
10
+
11
+ export default TJPurchase;
package/src/TJVersion.ts CHANGED
@@ -1,4 +1,4 @@
1
- const REACT_LIBRARY_VERSION = '13.4.1';
1
+ const REACT_LIBRARY_VERSION = '14.0.1';
2
2
  const REACT_LIBRARY_VERSION_SUFFIX = '';
3
3
 
4
4
  export class TJVersion {
package/src/index.ts CHANGED
@@ -6,6 +6,7 @@ import TJStatus from './TJStatus';
6
6
  import TJSegment from './TJSegment';
7
7
  import TJOfferwallDiscoverView from './TJOfferwallDiscoverView';
8
8
  import TJConnect from './TJConnect';
9
+ import TJPurchase from './TJPurchase';
9
10
 
10
11
  const LINKING_ERROR =
11
12
  `The package 'tapjoy-react-native-sdk' doesn't seem to be linked. Make sure: \n\n` +
@@ -33,5 +34,6 @@ export {
33
34
  TJSegment,
34
35
  TJOfferwallDiscoverView,
35
36
  TJConnect,
37
+ TJPurchase,
36
38
  };
37
39
  export default Tapjoy;
@@ -17,7 +17,7 @@ Pod::Spec.new do |s|
17
17
  s.source_files = "ios/**/*.{h,m,mm,swift}"
18
18
 
19
19
  s.dependency "React-Core"
20
- s.dependency "TapjoySDK", "13.4.1"
20
+ s.dependency "TapjoySDK", "14.0.1"
21
21
 
22
22
  # Don't install the dependencies when we run `pod install` in the old architecture.
23
23
  if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then