diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..0817ed8 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,31 @@ +module.exports = { + root: true, + parser: '@typescript-eslint/parser', + plugins: ['@typescript-eslint', 'prettier'], + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'prettier' + ], + rules: { + 'object-curly-spacing': ['error', 'always'], + 'prettier/prettier': 'error', + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }] + }, + env: { + node: true, + es6: true + }, + parserOptions: { + ecmaVersion: 2020, + sourceType: 'module' + }, + ignorePatterns: [ + 'lib/', + 'sample/', + 'android/', + 'ios/', + '*.min.js', + 'node_modules/' + ] +}; \ No newline at end of file diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml index 1daa647..c9ca729 100644 --- a/.github/workflows/pull-request.yml +++ b/.github/workflows/pull-request.yml @@ -14,7 +14,10 @@ jobs: - name: "Checkout" uses: actions/checkout@v4 - uses: actions/setup-node@master - - uses: c-hive/gha-yarn-cache@v2 + with: + node-version: 18 + cache: yarn + cache-dependency-path: yarn.lock - name: "Install node modules" run: | diff --git a/.gitignore b/.gitignore index da882ec..7c7ac06 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ ## Build generated build/ DerivedData/ +.yarn/ *.DS_Store ## Various settings @@ -78,3 +79,9 @@ build .gradle local.properties package-lock.json + +# TypeScript build output +lib/ + +# Development package +*.tgz diff --git a/.npmignore b/.npmignore index d64a3d9..3d3e024 100644 --- a/.npmignore +++ b/.npmignore @@ -1 +1,65 @@ -sample +# Sample app +sample/ + +# Android build artifacts and libs +android/libs/ +android/build/ +android/.gradle/ +android/local.properties + +# iOS build artifacts +ios/build/ +ios/Pods/ +ios/Podfile.lock + +# Build directories +build/ +dist/ + +# Dependencies +node_modules/ + +# IDE files +.idea/ +.vscode/ +*.iml +*.iws + +# OS files +.DS_Store +Thumbs.db + +# Git +.git/ +.github/ + +# Logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Other +.gradle/ +.trunk/ +*.tgz +*.tar.gz + +# Heavy binary files +*.jar +*.aar +*.so +*.dylib +*.dll + +# Development files +package-lock.json +yarn.lock +tsconfig.json +release.sh + +# Development and test files +**/*.test.ts +**/*.test.tsx +**/*.spec.ts +**/*.spec.tsx \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..17bbe7f --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,11 @@ +module.exports = { + bracketSpacing: true, + singleQuote: true, + trailingComma: 'es5', + tabWidth: 2, + useTabs: false, + semi: true, + bracketSameLine: false, + arrowParens: 'avoid', + printWidth: 80 +}; \ No newline at end of file diff --git a/ONBOARDING.md b/ONBOARDING.md new file mode 100644 index 0000000..588cd6c --- /dev/null +++ b/ONBOARDING.md @@ -0,0 +1,213 @@ +# Developer Onboarding Guide + +This guide will help you set up your development environment for working on the react-native-mparticle SDK. + +## Prerequisites + +- Node.js and npm +- React Native development environment set up ([React Native Environment Setup Guide](https://reactnative.dev/docs/environment-setup)) +- For iOS: + - macOS + - Xcode (latest version recommended) + - CocoaPods + - Ruby (for CocoaPods) +- For Android: + - Android Studio + - Java Development Kit (JDK) + - Android SDK + +## Project Structure + +``` +react-native-mparticle/ +├── android/ # Native Android SDK implementation +├── ios/ # Native iOS SDK implementation +├── js/ # JavaScript/TypeScript SDK implementation +├── sample/ # Sample app for testing +└── ... +``` + +## Initial Setup + +Install dependencies: +```bash +yarn install +``` + +## Running the Sample App + +The sample app is a great way to test your changes and see the SDK in action. + +### iOS Sample App + +1. Navigate to the sample directory: +```bash +cd sample +``` + +2. Install JavaScript dependencies: +```bash +yarn install +``` + +3. Install iOS dependencies: +```bash +cd ios +pod install +cd .. +``` + +4. Start the Metro bundler: +```bash +yarn start +``` + +5. Open the iOS workspace: +```bash +open ios/MParticleSample.xcworkspace +``` + +6. In Xcode: + - Select your target device/simulator + - Update signing configuration if needed + - Build and run (⌘R) + +### Android Sample App + +1. Navigate to the sample directory: +```bash +cd sample +``` + +2. Install JavaScript dependencies: +```bash +npm install +# or +yarn install +``` + +3. Start the Metro bundler: +```bash +npm start +# or +yarn start +``` + +4. Open Android Studio: + - Open the `android` folder in Android Studio + - Let Gradle sync complete + - Update any required SDK packages if prompted + +5. Run the app: + - Select your target device/emulator + - Click Run (or press ⇧F10) + +## Development Workflow + +### Building the SDK + +#### Android +```bash +cd android +./gradlew build +``` + +#### iOS +```bash +cd ios +pod install +``` + +### Running Tests + +```bash +# Run JavaScript tests +npm test + +# Run Android tests +cd android +./gradlew test + +# Run iOS tests +cd ios/RNMParticle.xcodeproj +xcodebuild test +``` + +## Troubleshooting + +### Common iOS Issues + +1. "Missing config.h" error: + This error occurs because the mParticle SDK contains Swift code which requires special handling. To fix this: + + a. Open your `sample/ios/Podfile` and add this block before the target definition: + ```ruby + pre_install do |installer| + installer.pod_targets.each do |pod| + if pod.name == 'mParticle-Apple-SDK' + def pod.build_type; + Pod::BuildType.new(:linkage => :dynamic, :packaging => :framework) + end + end + end + end + ``` + + b. Clean and reinstall pods: + ```bash + cd sample/ios + pod cache clean --all + rm -rf Pods Podfile.lock + pod install + ``` + + c. If using Xcode 12 or later, ensure your project's Build Settings has "Allow Non-modular Includes In Framework Modules" set to Yes + +2. Pod install fails: + - Try cleaning the pod cache: `pod cache clean --all` + - Delete Podfile.lock and try again + - Ensure CocoaPods is up to date: `bundle update` + +3. Build errors: + - Clean build folder in Xcode (⇧⌘K) + - Delete derived data: `rm -rf ~/Library/Developer/Xcode/DerivedData` + - Ensure all dependencies are properly installed + +### Common Android Issues + +1. Gradle sync fails: + - Check Android Studio SDK Manager for missing packages + - Update Gradle version if needed + - Clean project and rebuild + +2. Build errors: + - Run `./gradlew clean` + - Invalidate caches in Android Studio + - Ensure all dependencies are properly installed + +## Contributing + +1. Create a feature branch +2. Make your changes +3. Test thoroughly +4. Create a pull request +5. Ensure CI passes +6. Request review + +## Release Process + +1. Update version numbers: + - package.json + - android/build.gradle + - ios/RNMParticle.podspec + +2. Update CHANGELOG.md + +3. Create release PR + +4. After merge, create a new release on GitHub + +5. Publish to npm: +```bash +npm publish +``` \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index f87b43f..aef261f 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,16 +1,18 @@ buildscript { + ext.kotlin_version = "2.1.0" repositories { mavenCentral() google() } dependencies { - classpath 'com.android.tools.build:gradle:7.4.2' + classpath 'com.android.tools.build:gradle:8.1.4' + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } plugins { id "org.sonarqube" version "4.4.1.3373" - id "org.jlleitschuh.gradle.ktlint" version "11.6.1" + id "org.jlleitschuh.gradle.ktlint" version "13.0.0" } sonarqube { @@ -21,10 +23,41 @@ sonarqube { } } +def isNewArchitectureEnabled() { + // React Native 0.80+ uses this standard detection approach + return project.hasProperty("newArchEnabled") && project.newArchEnabled.toBoolean() +} + +def supportsNamespace() { + def parsed = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.') + def major = parsed[0].toInteger() + def minor = parsed[1].toInteger() + + // Namespace support was added in 7.3.0 + if (major == 7 && minor >= 3) { + return true + } + + return major >= 8 +} + apply plugin: 'org.jlleitschuh.gradle.ktlint' apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +//if (isNewArchitectureEnabled()) { +// apply plugin: 'com.facebook.react' +//} android { + if (supportsNamespace()) { + namespace 'com.mparticle.react' + buildFeatures.buildConfig = true + sourceSets { + main { + manifest.srcFile "src/main/AndroidManifestNew.xml" + } + } + } compileSdkVersion 33 defaultConfig { @@ -32,6 +65,25 @@ android { targetSdkVersion 33 versionCode 2 versionName "2.0.0" + //buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() + } + sourceSets { + main { + //if (isNewArchitectureEnabled()) { + // java.srcDirs += ['src/newarch/java'] + //} else { + java.srcDirs += ['src/oldarch/java'] + //} + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = '17' } buildTypes { release { @@ -45,17 +97,16 @@ android { } repositories { - maven { - //update periodically - current version: 0.70.5 - url "$rootDir/react-native-android" - } mavenCentral() google() +} +ktlint { + outputToConsole = true } dependencies { - compileOnly 'com.facebook.react:react-native:0.20.1' + api 'com.facebook.react:react-android:+' // // In your app, you should include mParticle core like this: @@ -64,13 +115,14 @@ dependencies { // // (See https://github.com/mparticle/mparticle-android-sdk for the latest version) // - compileOnly 'com.mparticle:android-core:[5.9.3, )' + api 'com.mparticle:android-core:[5.9.3, )' // // And, if you want to include kits, you can do so as follows: // // compile 'com.mparticle:android-example-kit:REPLACEME' // + implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.6.1" testImplementation 'org.mockito:mockito-core:5.8.0' androidTestImplementation 'org.mockito:mockito-android:5.8.0' @@ -79,6 +131,6 @@ dependencies { testImplementation 'junit:junit:4.13.2' testImplementation files('libs/java-json.jar') - testImplementation 'com.mparticle:android-core:5.55.0' - testImplementation 'com.facebook.react:react-native:0.20.1' + testImplementation 'com.mparticle:android-core:5+' + testImplementation("com.facebook.react:react-android:+") } diff --git a/android/gradle.properties b/android/gradle.properties index fab3fb6..418c55f 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -51,3 +51,5 @@ expo.webp.enabled=true # Enable animated webp support (~3.4 MB increase) # Disabled by default because iOS doesn't support animated webp expo.webp.animated=false + +sonar.gradle.skipCompile=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index 7a70adf..85e6182 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar deleted file mode 100644 index 21d9660..0000000 Binary files a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar and /dev/null differ diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar.md5 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar.md5 deleted file mode 100644 index d8f0e96..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar.md5 +++ /dev/null @@ -1 +0,0 @@ -7b864274b543d21ee7d7c9c8e7f7b043 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar.sha1 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar.sha1 deleted file mode 100644 index 50cc9b7..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -75340c383a5d55a37d68181f12b1d8d939a3f065 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar.sha256 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar.sha256 deleted file mode 100644 index 2f6f656..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar.sha256 +++ /dev/null @@ -1 +0,0 @@ -1fe6791aeefb0391d319d763c655a6f8232676141b886d0a467b8834a0b86497 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar.sha512 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar.sha512 deleted file mode 100644 index af4ef65..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug-sources.jar.sha512 +++ /dev/null @@ -1 +0,0 @@ -b6d659b87a103dd21026d8715420d047b70e76219d39121795598811cff2c7bb6cf3a860d8836fe6eeb753f785d7c2f7b961ea48c5cba27626a6e1cb5b07ee62 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar deleted file mode 100644 index 5723e1f..0000000 Binary files a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar and /dev/null differ diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar.md5 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar.md5 deleted file mode 100644 index 0d34886..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar.md5 +++ /dev/null @@ -1 +0,0 @@ -8f67048d84e52b2c37b14459567a5a9d \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar.sha1 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar.sha1 deleted file mode 100644 index 2fa63ef..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar.sha1 +++ /dev/null @@ -1 +0,0 @@ -f246204e16175a16e94ddab8556b5980c6241d14 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar.sha256 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar.sha256 deleted file mode 100644 index a366acb..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar.sha256 +++ /dev/null @@ -1 +0,0 @@ -98edd89a8c6b428921a71c83353b7c2ead7561ef78390d3d2f8bdec7ea0bccba \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar.sha512 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar.sha512 deleted file mode 100644 index b8b843c..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-debug.aar.sha512 +++ /dev/null @@ -1 +0,0 @@ -ccbb56a7ba17357aa68c9ba685f118acae462481c186ba2e18a5dff3a779fb6cf1b6557965777282625b1fea8a82336ee3d6166d226ac494413770ade3369402 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar deleted file mode 100644 index 4e26eec..0000000 Binary files a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar and /dev/null differ diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar.md5 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar.md5 deleted file mode 100644 index 780670a..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar.md5 +++ /dev/null @@ -1 +0,0 @@ -c8db891c3be1b407d7079c02c303243b \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar.sha1 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar.sha1 deleted file mode 100644 index 3355f97..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -34cf662170d553da87ddd8ef2213f13212955d1d \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar.sha256 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar.sha256 deleted file mode 100644 index eee7318..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar.sha256 +++ /dev/null @@ -1 +0,0 @@ -e622d9a7db5ba1a2161785ab8745dda58d1012aad04f7f9489fce207cf567f8a \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar.sha512 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar.sha512 deleted file mode 100644 index 8882337..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release-sources.jar.sha512 +++ /dev/null @@ -1 +0,0 @@ -205a0fd395d6d02c27c4611ae1ceca7ccb4f3554f17f44d338f9ffef2e3521e933616e74ac1b17bb7d300891ede5ecf58e966a11becda27f6760f862f2316783 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar deleted file mode 100644 index 13ad1c5..0000000 Binary files a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar and /dev/null differ diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar.md5 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar.md5 deleted file mode 100644 index 07e91ce..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar.md5 +++ /dev/null @@ -1 +0,0 @@ -4eea565acfa26284caefb83ea547a27d \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar.sha1 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar.sha1 deleted file mode 100644 index 08dc4b9..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar.sha1 +++ /dev/null @@ -1 +0,0 @@ -6d67ef0ee827fb500c5dae6e8de8497b7513b51f \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar.sha256 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar.sha256 deleted file mode 100644 index 5b262a1..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar.sha256 +++ /dev/null @@ -1 +0,0 @@ -3cf7d55a8e2a610cb293d91acc90881114df0150aea5bb19b2df78158c331134 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar.sha512 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar.sha512 deleted file mode 100644 index a93539c..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5-release.aar.sha512 +++ /dev/null @@ -1 +0,0 @@ -f114d26c0c757a2a333423738861dfcd225a790ba97a3a140e21cd131e9cf1c8cdc9e78372c735b6dc8f8ca004cf38e7b75b3c07afef5230fba7b57e71d332b3 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module deleted file mode 100644 index 69ed68f..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module +++ /dev/null @@ -1,204 +0,0 @@ -{ - "formatVersion": "1.1", - "component": { - "group": "com.facebook.react", - "module": "hermes-engine", - "version": "0.70.5", - "attributes": { - "org.gradle.status": "release" - } - }, - "createdBy": { - "gradle": { - "version": "7.5.1" - } - }, - "variants": [ - { - "name": "debugVariantDefaultApiPublication", - "attributes": { - "com.android.build.api.attributes.BuildTypeAttr": "debug", - "org.gradle.category": "library", - "org.gradle.dependency.bundling": "external", - "org.gradle.libraryelements": "aar", - "org.gradle.usage": "java-api" - }, - "files": [ - { - "name": "hermes-engine-0.70.5-debug.aar", - "url": "hermes-engine-0.70.5-debug.aar", - "size": 4033701, - "sha512": "ccbb56a7ba17357aa68c9ba685f118acae462481c186ba2e18a5dff3a779fb6cf1b6557965777282625b1fea8a82336ee3d6166d226ac494413770ade3369402", - "sha256": "98edd89a8c6b428921a71c83353b7c2ead7561ef78390d3d2f8bdec7ea0bccba", - "sha1": "f246204e16175a16e94ddab8556b5980c6241d14", - "md5": "8f67048d84e52b2c37b14459567a5a9d" - } - ] - }, - { - "name": "debugVariantDefaultRuntimePublication", - "attributes": { - "com.android.build.api.attributes.BuildTypeAttr": "debug", - "org.gradle.category": "library", - "org.gradle.dependency.bundling": "external", - "org.gradle.libraryelements": "aar", - "org.gradle.usage": "java-runtime" - }, - "dependencies": [ - { - "group": "com.facebook.fbjni", - "module": "fbjni", - "version": { - "requires": "0.2.2" - } - }, - { - "group": "com.facebook.soloader", - "module": "soloader", - "version": { - "requires": "0.10.3" - } - }, - { - "group": "com.facebook.yoga", - "module": "proguard-annotations", - "version": { - "requires": "1.19.0" - } - }, - { - "group": "androidx.annotation", - "module": "annotation", - "version": { - "requires": "1.3.0" - } - } - ], - "files": [ - { - "name": "hermes-engine-0.70.5-debug.aar", - "url": "hermes-engine-0.70.5-debug.aar", - "size": 4033701, - "sha512": "ccbb56a7ba17357aa68c9ba685f118acae462481c186ba2e18a5dff3a779fb6cf1b6557965777282625b1fea8a82336ee3d6166d226ac494413770ade3369402", - "sha256": "98edd89a8c6b428921a71c83353b7c2ead7561ef78390d3d2f8bdec7ea0bccba", - "sha1": "f246204e16175a16e94ddab8556b5980c6241d14", - "md5": "8f67048d84e52b2c37b14459567a5a9d" - } - ] - }, - { - "name": "debugVariantDefaultSourcePublication", - "attributes": { - "com.android.build.api.attributes.BuildTypeAttr": "debug", - "org.gradle.category": "documentation", - "org.gradle.dependency.bundling": "external", - "org.gradle.docstype": "sources", - "org.gradle.usage": "java-runtime" - }, - "files": [ - { - "name": "hermes-engine-0.70.5-debug-sources.jar", - "url": "hermes-engine-0.70.5-debug-sources.jar", - "size": 62707, - "sha512": "b6d659b87a103dd21026d8715420d047b70e76219d39121795598811cff2c7bb6cf3a860d8836fe6eeb753f785d7c2f7b961ea48c5cba27626a6e1cb5b07ee62", - "sha256": "1fe6791aeefb0391d319d763c655a6f8232676141b886d0a467b8834a0b86497", - "sha1": "75340c383a5d55a37d68181f12b1d8d939a3f065", - "md5": "7b864274b543d21ee7d7c9c8e7f7b043" - } - ] - }, - { - "name": "releaseVariantDefaultApiPublication", - "attributes": { - "com.android.build.api.attributes.BuildTypeAttr": "release", - "org.gradle.category": "library", - "org.gradle.dependency.bundling": "external", - "org.gradle.libraryelements": "aar", - "org.gradle.usage": "java-api" - }, - "files": [ - { - "name": "hermes-engine-0.70.5-release.aar", - "url": "hermes-engine-0.70.5-release.aar", - "size": 3458378, - "sha512": "f114d26c0c757a2a333423738861dfcd225a790ba97a3a140e21cd131e9cf1c8cdc9e78372c735b6dc8f8ca004cf38e7b75b3c07afef5230fba7b57e71d332b3", - "sha256": "3cf7d55a8e2a610cb293d91acc90881114df0150aea5bb19b2df78158c331134", - "sha1": "6d67ef0ee827fb500c5dae6e8de8497b7513b51f", - "md5": "4eea565acfa26284caefb83ea547a27d" - } - ] - }, - { - "name": "releaseVariantDefaultRuntimePublication", - "attributes": { - "com.android.build.api.attributes.BuildTypeAttr": "release", - "org.gradle.category": "library", - "org.gradle.dependency.bundling": "external", - "org.gradle.libraryelements": "aar", - "org.gradle.usage": "java-runtime" - }, - "dependencies": [ - { - "group": "com.facebook.fbjni", - "module": "fbjni", - "version": { - "requires": "0.2.2" - } - }, - { - "group": "com.facebook.soloader", - "module": "soloader", - "version": { - "requires": "0.10.3" - } - }, - { - "group": "com.facebook.yoga", - "module": "proguard-annotations", - "version": { - "requires": "1.19.0" - } - }, - { - "group": "androidx.annotation", - "module": "annotation", - "version": { - "requires": "1.3.0" - } - } - ], - "files": [ - { - "name": "hermes-engine-0.70.5-release.aar", - "url": "hermes-engine-0.70.5-release.aar", - "size": 3458378, - "sha512": "f114d26c0c757a2a333423738861dfcd225a790ba97a3a140e21cd131e9cf1c8cdc9e78372c735b6dc8f8ca004cf38e7b75b3c07afef5230fba7b57e71d332b3", - "sha256": "3cf7d55a8e2a610cb293d91acc90881114df0150aea5bb19b2df78158c331134", - "sha1": "6d67ef0ee827fb500c5dae6e8de8497b7513b51f", - "md5": "4eea565acfa26284caefb83ea547a27d" - } - ] - }, - { - "name": "releaseVariantDefaultSourcePublication", - "attributes": { - "com.android.build.api.attributes.BuildTypeAttr": "release", - "org.gradle.category": "documentation", - "org.gradle.dependency.bundling": "external", - "org.gradle.docstype": "sources", - "org.gradle.usage": "java-runtime" - }, - "files": [ - { - "name": "hermes-engine-0.70.5-release-sources.jar", - "url": "hermes-engine-0.70.5-release-sources.jar", - "size": 62694, - "sha512": "205a0fd395d6d02c27c4611ae1ceca7ccb4f3554f17f44d338f9ffef2e3521e933616e74ac1b17bb7d300891ede5ecf58e966a11becda27f6760f862f2316783", - "sha256": "e622d9a7db5ba1a2161785ab8745dda58d1012aad04f7f9489fce207cf567f8a", - "sha1": "34cf662170d553da87ddd8ef2213f13212955d1d", - "md5": "c8db891c3be1b407d7079c02c303243b" - } - ] - } - ] -} diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module.md5 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module.md5 deleted file mode 100644 index ad1706d..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module.md5 +++ /dev/null @@ -1 +0,0 @@ -4ff83d5a836dec90593a9de87e02b66f \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module.sha1 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module.sha1 deleted file mode 100644 index 8af82fe..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module.sha1 +++ /dev/null @@ -1 +0,0 @@ -b5236e1fc7e7d9e5ddf5219e8a6bb08a0237d9da \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module.sha256 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module.sha256 deleted file mode 100644 index 539e637..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module.sha256 +++ /dev/null @@ -1 +0,0 @@ -4e27316d4f981093d6f73885dcdc5e64dc23a18ad892d68cf7b7fc22cdfc598d \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module.sha512 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module.sha512 deleted file mode 100644 index 5e22762..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.module.sha512 +++ /dev/null @@ -1 +0,0 @@ -8b5d314a29a4a5d578a43a7a5b8243736247084af2e36eb4830050fd29103ed930a3a6f8d1dfa68f3be226891f14d2e56e8122a4fef9c28464cbbcd1e52a6204 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom deleted file mode 100644 index a7dd4cd..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - 4.0.0 - com.facebook.react - hermes-engine - 0.70.5 - pom - - - com.facebook.fbjni - fbjni - 0.2.2 - compile - true - - - com.facebook.soloader - soloader - 0.10.3 - compile - true - - - com.facebook.yoga - proguard-annotations - 1.19.0 - compile - true - - - androidx.annotation - annotation - 1.3.0 - compile - true - - - diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom.md5 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom.md5 deleted file mode 100644 index 680fc0a..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom.md5 +++ /dev/null @@ -1 +0,0 @@ -9182f5e678c542dba36f6bc0168d49a9 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom.sha1 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom.sha1 deleted file mode 100644 index 59d3647..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom.sha1 +++ /dev/null @@ -1 +0,0 @@ -6a6ff8f12beb194ef2fb27de7c4594bfed44088b \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom.sha256 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom.sha256 deleted file mode 100644 index 1e38ef5..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom.sha256 +++ /dev/null @@ -1 +0,0 @@ -7ddd030c89cc685a0061c3ec5340140161fd1fab1df7859699b23ad64a4fbd6f \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom.sha512 b/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom.sha512 deleted file mode 100644 index 095be6a..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/0.70.5/hermes-engine-0.70.5.pom.sha512 +++ /dev/null @@ -1 +0,0 @@ -0bf0740d048ee97daaa8771e6a8ca340a59b68e2d4c0f5e9feeb090b87a059c2ecfc993592d26c409a2fb5ea28c839846ea5567c7abde8b5e285e3c742ee1987 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml b/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml deleted file mode 100644 index ec4d790..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - com.facebook.react - hermes-engine - - 0.70.5 - 0.70.5 - - 0.70.5 - - 20221106211107 - - diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml.md5 b/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml.md5 deleted file mode 100644 index 058ad36..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml.md5 +++ /dev/null @@ -1 +0,0 @@ -d696a517f905ef03db049e3498bed1d8 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml.sha1 b/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml.sha1 deleted file mode 100644 index a0452b3..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml.sha1 +++ /dev/null @@ -1 +0,0 @@ -62474f1140166dd5b0cdb3a0433691fd413f6cc7 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml.sha256 b/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml.sha256 deleted file mode 100644 index 2850bd6..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml.sha256 +++ /dev/null @@ -1 +0,0 @@ -3e3e01b6b286761657f01a1a0b92386e2532badb0ceca6d54a29dfc032a00bfd \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml.sha512 b/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml.sha512 deleted file mode 100644 index d24ae7c..0000000 --- a/android/libs/react-native-android/com/facebook/react/hermes-engine/maven-metadata.xml.sha512 +++ /dev/null @@ -1 +0,0 @@ -fbaf046e2812062b9c153695d7fd934b64959de73b084611b938c80e77e9b5df91aab55de42920103f564ba9b66423ac5ab74516f7a69355a7b4a6cbd360fc53 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar deleted file mode 100644 index f71fd28..0000000 Binary files a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar and /dev/null differ diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar.md5 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar.md5 deleted file mode 100644 index e06f76c..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar.md5 +++ /dev/null @@ -1 +0,0 @@ -74d86431fd9bc24b8769b1dcff698814 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar.sha1 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar.sha1 deleted file mode 100644 index bc68ce8..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -c64ee18787feb457f9a4f3ffc888b0f312afe16c \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar.sha256 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar.sha256 deleted file mode 100644 index 31c42cc..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar.sha256 +++ /dev/null @@ -1 +0,0 @@ -947f3bb8fe00e0d72d10eb3fe1bd00c181ee366fdf28fcd6e35794575faa1fb1 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar.sha512 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar.sha512 deleted file mode 100644 index 5fb3ee5..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug-sources.jar.sha512 +++ /dev/null @@ -1 +0,0 @@ -1cabc724dd44d1266c637d9db0a41e1d0d03d7b333770b173c7724bd56a318e43947bf1bd5f83734c4afdf5f695749bbb8e77c4df2268974cc23d8a7b399d179 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar deleted file mode 100644 index a324a45..0000000 Binary files a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar and /dev/null differ diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar.md5 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar.md5 deleted file mode 100644 index 9139f2e..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar.md5 +++ /dev/null @@ -1 +0,0 @@ -8b6106b2cab596fdcdf1de5b495419dd \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar.sha1 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar.sha1 deleted file mode 100644 index f0a325f..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar.sha1 +++ /dev/null @@ -1 +0,0 @@ -650825ef196f2045dfe93cf7eff46ed6a9cb851e \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar.sha256 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar.sha256 deleted file mode 100644 index c59430f..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar.sha256 +++ /dev/null @@ -1 +0,0 @@ -e9f11e2e7c0e95bdc8443566d9ba6cec9b9613ee09426832f38050edcf65b828 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar.sha512 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar.sha512 deleted file mode 100644 index c6ea3e1..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-debug.aar.sha512 +++ /dev/null @@ -1 +0,0 @@ -a75e86a070303e119cc4875d194740bc99a70dc4c538e994fe68fd7320a47d91c1c7094bccb923e36c51231e8ce6b8d0b2665a3e9aad246a63ca073decce4a68 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar deleted file mode 100644 index d36b14f..0000000 Binary files a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar and /dev/null differ diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar.md5 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar.md5 deleted file mode 100644 index ee2919a..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar.md5 +++ /dev/null @@ -1 +0,0 @@ -b4c3cdc59566abc5ea37bd6311ce818c \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar.sha1 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar.sha1 deleted file mode 100644 index 6e53e4d..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar.sha1 +++ /dev/null @@ -1 +0,0 @@ -3fe922c099cf22070fb5131914012269c68337e6 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar.sha256 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar.sha256 deleted file mode 100644 index 952ee0e..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar.sha256 +++ /dev/null @@ -1 +0,0 @@ -19a94e1af4190b32e8ed0a463a7deeccfb4785a03cde91b88efafee0931f9c80 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar.sha512 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar.sha512 deleted file mode 100644 index 8ba78e8..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release-sources.jar.sha512 +++ /dev/null @@ -1 +0,0 @@ -253ca7b3b2b6953681ce77d43c2c75bbb6f4f6699e5fba3f2fdb657fd6e12ff578bc7ba8fa27945a017354daf2ef28f6bfaf22e87d68d34625b05c57d1999368 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar deleted file mode 100644 index 58113a5..0000000 Binary files a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar and /dev/null differ diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar.md5 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar.md5 deleted file mode 100644 index 6e05aab..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar.md5 +++ /dev/null @@ -1 +0,0 @@ -50b3e7bf5bfc3acab1e9f498f988d3f0 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar.sha1 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar.sha1 deleted file mode 100644 index 7316439..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar.sha1 +++ /dev/null @@ -1 +0,0 @@ -00c9f58ad16f8e6f11bc75ad826bf4e805f6ac69 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar.sha256 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar.sha256 deleted file mode 100644 index 8ed6644..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar.sha256 +++ /dev/null @@ -1 +0,0 @@ -591fab93fa3ff09b66748007dd4bcd4ae5f9da14bbf5ab5d6109cb1a29f9c918 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar.sha512 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar.sha512 deleted file mode 100644 index 30d86ed..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5-release.aar.sha512 +++ /dev/null @@ -1 +0,0 @@ -28f0e88dcd49bd32c355f11822fe299b81d88c69f9eb2f650ee933c09aa4a88364024b44e0237821a429dc1d7af4db46d4205a86755343bef91aa163b3e5c385 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module deleted file mode 100644 index 17928ef..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module +++ /dev/null @@ -1,628 +0,0 @@ -{ - "formatVersion": "1.1", - "component": { - "group": "com.facebook.react", - "module": "react-native", - "version": "0.70.5", - "attributes": { - "org.gradle.status": "release" - } - }, - "createdBy": { - "gradle": { - "version": "7.5.1" - } - }, - "variants": [ - { - "name": "debugVariantDefaultApiPublication", - "attributes": { - "com.android.build.api.attributes.BuildTypeAttr": "debug", - "org.gradle.category": "library", - "org.gradle.dependency.bundling": "external", - "org.gradle.libraryelements": "aar", - "org.gradle.usage": "java-api" - }, - "dependencies": [ - { - "group": "androidx.appcompat", - "module": "appcompat-resources", - "version": { - "requires": "1.4.1" - } - }, - { - "group": "androidx.appcompat", - "module": "appcompat", - "version": { - "requires": "1.4.1" - } - }, - { - "group": "androidx.autofill", - "module": "autofill", - "version": { - "requires": "1.1.0" - } - }, - { - "group": "androidx.swiperefreshlayout", - "module": "swiperefreshlayout", - "version": { - "requires": "1.0.0" - } - }, - { - "group": "com.facebook.fbjni", - "module": "fbjni-java-only", - "version": { - "requires": "0.2.2" - } - }, - { - "group": "com.facebook.fresco", - "module": "fresco", - "version": { - "requires": "2.5.0" - } - }, - { - "group": "com.facebook.fresco", - "module": "imagepipeline-okhttp3", - "version": { - "requires": "2.5.0" - } - }, - { - "group": "com.facebook.fresco", - "module": "ui-common", - "version": { - "requires": "2.5.0" - } - }, - { - "group": "com.facebook.infer.annotation", - "module": "infer-annotation", - "version": { - "requires": "0.18.0" - } - }, - { - "group": "com.facebook.soloader", - "module": "soloader", - "version": { - "requires": "0.10.4" - } - }, - { - "group": "com.facebook.yoga", - "module": "proguard-annotations", - "version": { - "requires": "1.19.0" - } - }, - { - "group": "com.google.code.findbugs", - "module": "jsr305", - "version": { - "requires": "3.0.2" - } - }, - { - "group": "com.squareup.okhttp3", - "module": "okhttp-urlconnection", - "version": { - "requires": "4.9.2" - } - }, - { - "group": "com.squareup.okhttp3", - "module": "okhttp", - "version": { - "requires": "4.9.2" - } - }, - { - "group": "com.squareup.okio", - "module": "okio", - "version": { - "requires": "2.9.0" - } - }, - { - "group": "javax.inject", - "module": "javax.inject", - "version": { - "requires": "1" - } - }, - { - "group": "org.jetbrains.kotlin", - "module": "kotlin-stdlib-jdk8", - "version": { - "requires": "1.6.10" - } - } - ], - "files": [ - { - "name": "react-native-0.70.5-debug.aar", - "url": "react-native-0.70.5-debug.aar", - "size": 32896271, - "sha512": "a75e86a070303e119cc4875d194740bc99a70dc4c538e994fe68fd7320a47d91c1c7094bccb923e36c51231e8ce6b8d0b2665a3e9aad246a63ca073decce4a68", - "sha256": "e9f11e2e7c0e95bdc8443566d9ba6cec9b9613ee09426832f38050edcf65b828", - "sha1": "650825ef196f2045dfe93cf7eff46ed6a9cb851e", - "md5": "8b6106b2cab596fdcdf1de5b495419dd" - } - ] - }, - { - "name": "debugVariantDefaultRuntimePublication", - "attributes": { - "com.android.build.api.attributes.BuildTypeAttr": "debug", - "org.gradle.category": "library", - "org.gradle.dependency.bundling": "external", - "org.gradle.libraryelements": "aar", - "org.gradle.usage": "java-runtime" - }, - "dependencies": [ - { - "group": "androidx.appcompat", - "module": "appcompat-resources", - "version": { - "requires": "1.4.1" - } - }, - { - "group": "androidx.appcompat", - "module": "appcompat", - "version": { - "requires": "1.4.1" - } - }, - { - "group": "androidx.autofill", - "module": "autofill", - "version": { - "requires": "1.1.0" - } - }, - { - "group": "androidx.swiperefreshlayout", - "module": "swiperefreshlayout", - "version": { - "requires": "1.0.0" - } - }, - { - "group": "com.facebook.fbjni", - "module": "fbjni-java-only", - "version": { - "requires": "0.2.2" - } - }, - { - "group": "com.facebook.fresco", - "module": "fresco", - "version": { - "requires": "2.5.0" - } - }, - { - "group": "com.facebook.fresco", - "module": "imagepipeline-okhttp3", - "version": { - "requires": "2.5.0" - } - }, - { - "group": "com.facebook.fresco", - "module": "ui-common", - "version": { - "requires": "2.5.0" - } - }, - { - "group": "com.facebook.infer.annotation", - "module": "infer-annotation", - "version": { - "requires": "0.18.0" - } - }, - { - "group": "com.facebook.soloader", - "module": "soloader", - "version": { - "requires": "0.10.4" - } - }, - { - "group": "com.facebook.yoga", - "module": "proguard-annotations", - "version": { - "requires": "1.19.0" - } - }, - { - "group": "com.google.code.findbugs", - "module": "jsr305", - "version": { - "requires": "3.0.2" - } - }, - { - "group": "com.squareup.okhttp3", - "module": "okhttp-urlconnection", - "version": { - "requires": "4.9.2" - } - }, - { - "group": "com.squareup.okhttp3", - "module": "okhttp", - "version": { - "requires": "4.9.2" - } - }, - { - "group": "com.squareup.okio", - "module": "okio", - "version": { - "requires": "2.9.0" - } - }, - { - "group": "javax.inject", - "module": "javax.inject", - "version": { - "requires": "1" - } - }, - { - "group": "org.jetbrains.kotlin", - "module": "kotlin-stdlib-jdk8", - "version": { - "requires": "1.6.10" - } - } - ], - "files": [ - { - "name": "react-native-0.70.5-debug.aar", - "url": "react-native-0.70.5-debug.aar", - "size": 32896271, - "sha512": "a75e86a070303e119cc4875d194740bc99a70dc4c538e994fe68fd7320a47d91c1c7094bccb923e36c51231e8ce6b8d0b2665a3e9aad246a63ca073decce4a68", - "sha256": "e9f11e2e7c0e95bdc8443566d9ba6cec9b9613ee09426832f38050edcf65b828", - "sha1": "650825ef196f2045dfe93cf7eff46ed6a9cb851e", - "md5": "8b6106b2cab596fdcdf1de5b495419dd" - } - ] - }, - { - "name": "debugVariantDefaultSourcePublication", - "attributes": { - "com.android.build.api.attributes.BuildTypeAttr": "debug", - "org.gradle.category": "documentation", - "org.gradle.dependency.bundling": "external", - "org.gradle.docstype": "sources", - "org.gradle.usage": "java-runtime" - }, - "files": [ - { - "name": "react-native-0.70.5-debug-sources.jar", - "url": "react-native-0.70.5-debug-sources.jar", - "size": 1044828, - "sha512": "1cabc724dd44d1266c637d9db0a41e1d0d03d7b333770b173c7724bd56a318e43947bf1bd5f83734c4afdf5f695749bbb8e77c4df2268974cc23d8a7b399d179", - "sha256": "947f3bb8fe00e0d72d10eb3fe1bd00c181ee366fdf28fcd6e35794575faa1fb1", - "sha1": "c64ee18787feb457f9a4f3ffc888b0f312afe16c", - "md5": "74d86431fd9bc24b8769b1dcff698814" - } - ] - }, - { - "name": "releaseVariantDefaultApiPublication", - "attributes": { - "com.android.build.api.attributes.BuildTypeAttr": "release", - "org.gradle.category": "library", - "org.gradle.dependency.bundling": "external", - "org.gradle.libraryelements": "aar", - "org.gradle.usage": "java-api" - }, - "dependencies": [ - { - "group": "androidx.appcompat", - "module": "appcompat-resources", - "version": { - "requires": "1.4.1" - } - }, - { - "group": "androidx.appcompat", - "module": "appcompat", - "version": { - "requires": "1.4.1" - } - }, - { - "group": "androidx.autofill", - "module": "autofill", - "version": { - "requires": "1.1.0" - } - }, - { - "group": "androidx.swiperefreshlayout", - "module": "swiperefreshlayout", - "version": { - "requires": "1.0.0" - } - }, - { - "group": "com.facebook.fbjni", - "module": "fbjni-java-only", - "version": { - "requires": "0.2.2" - } - }, - { - "group": "com.facebook.fresco", - "module": "fresco", - "version": { - "requires": "2.5.0" - } - }, - { - "group": "com.facebook.fresco", - "module": "imagepipeline-okhttp3", - "version": { - "requires": "2.5.0" - } - }, - { - "group": "com.facebook.fresco", - "module": "ui-common", - "version": { - "requires": "2.5.0" - } - }, - { - "group": "com.facebook.infer.annotation", - "module": "infer-annotation", - "version": { - "requires": "0.18.0" - } - }, - { - "group": "com.facebook.soloader", - "module": "soloader", - "version": { - "requires": "0.10.4" - } - }, - { - "group": "com.facebook.yoga", - "module": "proguard-annotations", - "version": { - "requires": "1.19.0" - } - }, - { - "group": "com.google.code.findbugs", - "module": "jsr305", - "version": { - "requires": "3.0.2" - } - }, - { - "group": "com.squareup.okhttp3", - "module": "okhttp-urlconnection", - "version": { - "requires": "4.9.2" - } - }, - { - "group": "com.squareup.okhttp3", - "module": "okhttp", - "version": { - "requires": "4.9.2" - } - }, - { - "group": "com.squareup.okio", - "module": "okio", - "version": { - "requires": "2.9.0" - } - }, - { - "group": "javax.inject", - "module": "javax.inject", - "version": { - "requires": "1" - } - }, - { - "group": "org.jetbrains.kotlin", - "module": "kotlin-stdlib-jdk8", - "version": { - "requires": "1.6.10" - } - } - ], - "files": [ - { - "name": "react-native-0.70.5-release.aar", - "url": "react-native-0.70.5-release.aar", - "size": 12614227, - "sha512": "28f0e88dcd49bd32c355f11822fe299b81d88c69f9eb2f650ee933c09aa4a88364024b44e0237821a429dc1d7af4db46d4205a86755343bef91aa163b3e5c385", - "sha256": "591fab93fa3ff09b66748007dd4bcd4ae5f9da14bbf5ab5d6109cb1a29f9c918", - "sha1": "00c9f58ad16f8e6f11bc75ad826bf4e805f6ac69", - "md5": "50b3e7bf5bfc3acab1e9f498f988d3f0" - } - ] - }, - { - "name": "releaseVariantDefaultRuntimePublication", - "attributes": { - "com.android.build.api.attributes.BuildTypeAttr": "release", - "org.gradle.category": "library", - "org.gradle.dependency.bundling": "external", - "org.gradle.libraryelements": "aar", - "org.gradle.usage": "java-runtime" - }, - "dependencies": [ - { - "group": "androidx.appcompat", - "module": "appcompat-resources", - "version": { - "requires": "1.4.1" - } - }, - { - "group": "androidx.appcompat", - "module": "appcompat", - "version": { - "requires": "1.4.1" - } - }, - { - "group": "androidx.autofill", - "module": "autofill", - "version": { - "requires": "1.1.0" - } - }, - { - "group": "androidx.swiperefreshlayout", - "module": "swiperefreshlayout", - "version": { - "requires": "1.0.0" - } - }, - { - "group": "com.facebook.fbjni", - "module": "fbjni-java-only", - "version": { - "requires": "0.2.2" - } - }, - { - "group": "com.facebook.fresco", - "module": "fresco", - "version": { - "requires": "2.5.0" - } - }, - { - "group": "com.facebook.fresco", - "module": "imagepipeline-okhttp3", - "version": { - "requires": "2.5.0" - } - }, - { - "group": "com.facebook.fresco", - "module": "ui-common", - "version": { - "requires": "2.5.0" - } - }, - { - "group": "com.facebook.infer.annotation", - "module": "infer-annotation", - "version": { - "requires": "0.18.0" - } - }, - { - "group": "com.facebook.soloader", - "module": "soloader", - "version": { - "requires": "0.10.4" - } - }, - { - "group": "com.facebook.yoga", - "module": "proguard-annotations", - "version": { - "requires": "1.19.0" - } - }, - { - "group": "com.google.code.findbugs", - "module": "jsr305", - "version": { - "requires": "3.0.2" - } - }, - { - "group": "com.squareup.okhttp3", - "module": "okhttp-urlconnection", - "version": { - "requires": "4.9.2" - } - }, - { - "group": "com.squareup.okhttp3", - "module": "okhttp", - "version": { - "requires": "4.9.2" - } - }, - { - "group": "com.squareup.okio", - "module": "okio", - "version": { - "requires": "2.9.0" - } - }, - { - "group": "javax.inject", - "module": "javax.inject", - "version": { - "requires": "1" - } - }, - { - "group": "org.jetbrains.kotlin", - "module": "kotlin-stdlib-jdk8", - "version": { - "requires": "1.6.10" - } - } - ], - "files": [ - { - "name": "react-native-0.70.5-release.aar", - "url": "react-native-0.70.5-release.aar", - "size": 12614227, - "sha512": "28f0e88dcd49bd32c355f11822fe299b81d88c69f9eb2f650ee933c09aa4a88364024b44e0237821a429dc1d7af4db46d4205a86755343bef91aa163b3e5c385", - "sha256": "591fab93fa3ff09b66748007dd4bcd4ae5f9da14bbf5ab5d6109cb1a29f9c918", - "sha1": "00c9f58ad16f8e6f11bc75ad826bf4e805f6ac69", - "md5": "50b3e7bf5bfc3acab1e9f498f988d3f0" - } - ] - }, - { - "name": "releaseVariantDefaultSourcePublication", - "attributes": { - "com.android.build.api.attributes.BuildTypeAttr": "release", - "org.gradle.category": "documentation", - "org.gradle.dependency.bundling": "external", - "org.gradle.docstype": "sources", - "org.gradle.usage": "java-runtime" - }, - "files": [ - { - "name": "react-native-0.70.5-release-sources.jar", - "url": "react-native-0.70.5-release-sources.jar", - "size": 1044810, - "sha512": "253ca7b3b2b6953681ce77d43c2c75bbb6f4f6699e5fba3f2fdb657fd6e12ff578bc7ba8fa27945a017354daf2ef28f6bfaf22e87d68d34625b05c57d1999368", - "sha256": "19a94e1af4190b32e8ed0a463a7deeccfb4785a03cde91b88efafee0931f9c80", - "sha1": "3fe922c099cf22070fb5131914012269c68337e6", - "md5": "b4c3cdc59566abc5ea37bd6311ce818c" - } - ] - } - ] -} diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module.md5 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module.md5 deleted file mode 100644 index 4cd1c36..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module.md5 +++ /dev/null @@ -1 +0,0 @@ -c0dfc07b0961a25ba9ceb2b494f46bb6 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module.sha1 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module.sha1 deleted file mode 100644 index 57ddbe5..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module.sha1 +++ /dev/null @@ -1 +0,0 @@ -80f317430557db0de3088903d62818e3e3f9b90c \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module.sha256 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module.sha256 deleted file mode 100644 index d6e2f15..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module.sha256 +++ /dev/null @@ -1 +0,0 @@ -a99732a86b4bc51cd3e2c1d87a16bec11f45ee151c264b2873b803a571caef1e \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module.sha512 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module.sha512 deleted file mode 100644 index 460164d..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.module.sha512 +++ /dev/null @@ -1 +0,0 @@ -cd3ab73cec4f59e339a1f3f08a35a89e7a28bfee744e53b8eefbef873dbf96a075d46bb0de4142a0ffddfdaf4d1f139afd5108d39521fe28cd95e21068bbaf10 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom deleted file mode 100644 index 242c546..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom +++ /dev/null @@ -1,156 +0,0 @@ - - - - - - - - 4.0.0 - com.facebook.react - react-native - 0.70.5 - pom - ReactNative - A framework for building native apps with React - https://github.com/facebook/react-native - - - MIT License - https://github.com/facebook/react-native/blob/HEAD/LICENSE - repo - - - - - facebook - Facebook - - - - scm:git:https://github.com/facebook/react-native.git - scm:git:git@github.com:facebook/react-native.git - https://github.com/facebook/react-native.git - - - - androidx.appcompat - appcompat-resources - 1.4.1 - compile - true - - - androidx.appcompat - appcompat - 1.4.1 - compile - true - - - androidx.autofill - autofill - 1.1.0 - compile - true - - - androidx.swiperefreshlayout - swiperefreshlayout - 1.0.0 - compile - true - - - com.facebook.fbjni - fbjni-java-only - 0.2.2 - compile - true - - - com.facebook.fresco - fresco - 2.5.0 - compile - true - - - com.facebook.fresco - imagepipeline-okhttp3 - 2.5.0 - compile - true - - - com.facebook.fresco - ui-common - 2.5.0 - compile - true - - - com.facebook.infer.annotation - infer-annotation - 0.18.0 - compile - true - - - com.facebook.soloader - soloader - 0.10.4 - compile - true - - - com.facebook.yoga - proguard-annotations - 1.19.0 - compile - true - - - com.google.code.findbugs - jsr305 - 3.0.2 - compile - true - - - com.squareup.okhttp3 - okhttp-urlconnection - 4.9.2 - compile - true - - - com.squareup.okhttp3 - okhttp - 4.9.2 - compile - true - - - com.squareup.okio - okio - 2.9.0 - compile - true - - - javax.inject - javax.inject - 1 - compile - true - - - org.jetbrains.kotlin - kotlin-stdlib-jdk8 - 1.6.10 - compile - true - - - diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom.md5 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom.md5 deleted file mode 100644 index 0c566c0..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom.md5 +++ /dev/null @@ -1 +0,0 @@ -314aca710fcde34076ae5994d7f9b97e \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom.sha1 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom.sha1 deleted file mode 100644 index 68f999a..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom.sha1 +++ /dev/null @@ -1 +0,0 @@ -6a163a1b47caaf40d6e1073ea5c7e12985e5039a \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom.sha256 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom.sha256 deleted file mode 100644 index bf2273f..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom.sha256 +++ /dev/null @@ -1 +0,0 @@ -801b36c31a6e9a37096d594bd2ab459c2506d6a25c8417e912a29af7b7d6507e \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom.sha512 b/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom.sha512 deleted file mode 100644 index b07736b..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/0.70.5/react-native-0.70.5.pom.sha512 +++ /dev/null @@ -1 +0,0 @@ -2b7a31bf8d9b01bc8185de8a018e469e5eea59c311e4a1cd531004b016d2218ff0c683f1c4ad904d28248fa3b58d0c54384f9b19dfedb68e82ce3d226fa10b70 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml b/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml deleted file mode 100644 index 1c5ffff..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - com.facebook.react - react-native - - 0.70.5 - 0.70.5 - - 0.70.5 - - 20221106211052 - - diff --git a/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml.md5 b/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml.md5 deleted file mode 100644 index 5519167..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml.md5 +++ /dev/null @@ -1 +0,0 @@ -2fd397e2d08ed150f66851e1e34dd67e \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml.sha1 b/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml.sha1 deleted file mode 100644 index a853b16..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml.sha1 +++ /dev/null @@ -1 +0,0 @@ -d4efb834e0463c9149216b52f559ffbb81710ece \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml.sha256 b/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml.sha256 deleted file mode 100644 index aaf8473..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml.sha256 +++ /dev/null @@ -1 +0,0 @@ -e3a583f456c35a1bd17a05d4627fec2fa5c7d80ea095f5d6d24c13b98b341453 \ No newline at end of file diff --git a/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml.sha512 b/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml.sha512 deleted file mode 100644 index 3376915..0000000 --- a/android/libs/react-native-android/com/facebook/react/react-native/maven-metadata.xml.sha512 +++ /dev/null @@ -1 +0,0 @@ -4b9cfbc4aed81b138b7942f7488f450c4475d60f0d352f9e67b54e38879873e7f78ee744835d46be66ba32925244d4916add618897b45180381fb95bb8082cd6 \ No newline at end of file diff --git a/android/src/main/AndroidManifestNew.xml b/android/src/main/AndroidManifestNew.xml new file mode 100644 index 0000000..0fd6dad --- /dev/null +++ b/android/src/main/AndroidManifestNew.xml @@ -0,0 +1,3 @@ + + + diff --git a/android/src/main/java/com/mparticle/react/MParticleModule.java b/android/src/main/java/com/mparticle/react/MParticleModule.java index 1e322c3..8f93f8f 100644 --- a/android/src/main/java/com/mparticle/react/MParticleModule.java +++ b/android/src/main/java/com/mparticle/react/MParticleModule.java @@ -50,6 +50,7 @@ public class MParticleModule extends ReactContextBaseJavaModule { + public static final String MODULE_NAME = "MParticle"; private final static String LOG_TAG = "MParticleModule"; ReactApplicationContext reactContext; @@ -61,7 +62,7 @@ public MParticleModule(ReactApplicationContext reactContext) { @Override public String getName() { - return "MParticle"; + return MODULE_NAME; } @ReactMethod diff --git a/android/src/main/java/com/mparticle/react/MParticlePackage.java b/android/src/main/java/com/mparticle/react/MParticlePackage.java deleted file mode 100644 index 2c744c8..0000000 --- a/android/src/main/java/com/mparticle/react/MParticlePackage.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.mparticle.react; - -import com.facebook.react.ReactPackage; -import com.facebook.react.bridge.JavaScriptModule; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.uimanager.ViewManager; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class MParticlePackage implements ReactPackage { - @Override - public List createNativeModules( - ReactApplicationContext reactContext) { - List modules = new ArrayList<>(); - - modules.add(new MParticleModule(reactContext)); - - return modules; - } - - // Deprecated RN 0.47 - public List> createJSModules() { - return Collections.emptyList(); - } - - @Override - public List createViewManagers( - ReactApplicationContext reactContext) { - return Collections.emptyList(); - } -} diff --git a/android/src/main/java/com/mparticle/react/MParticlePackage.kt b/android/src/main/java/com/mparticle/react/MParticlePackage.kt new file mode 100644 index 0000000..54e5dd0 --- /dev/null +++ b/android/src/main/java/com/mparticle/react/MParticlePackage.kt @@ -0,0 +1,70 @@ +package com.mparticle.react + +import com.facebook.react.TurboReactPackage +import com.facebook.react.bridge.ModuleSpec +import com.facebook.react.bridge.NativeModule +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.module.model.ReactModuleInfo +import com.facebook.react.module.model.ReactModuleInfoProvider +import com.facebook.react.uimanager.ViewManager +import com.mparticle.react.rokt.MPRoktModule +import com.mparticle.react.rokt.MPRoktModuleImpl +import com.mparticle.react.rokt.RoktLayoutViewManager + +class MParticlePackage : TurboReactPackage() { + override fun getModule( + name: String, + reactContext: ReactApplicationContext, + ): NativeModule? = + when (name) { + MParticleModule.MODULE_NAME -> { + MParticleModule(reactContext) + } + + MPRoktModuleImpl.MODULE_NAME -> { + MPRoktModule(reactContext) + } + + else -> null + } + + override fun createViewManagers(reactContext: ReactApplicationContext): List> = listOf(RoktLayoutViewManager()) + + override fun getReactModuleInfoProvider() = + ReactModuleInfoProvider { + val moduleInfos: MutableMap = + HashMap() + moduleInfos.put( + MParticleModule.MODULE_NAME, + ReactModuleInfo( + MParticleModule.MODULE_NAME, + MParticleModule.MODULE_NAME, + true, // canOverrideExistingModule + false, // needsEagerInit + true, // hasConstants + false, // isCxxModule + // BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + false, // isTurboModule + ), + ) + moduleInfos.put( + MPRoktModuleImpl.MODULE_NAME, + ReactModuleInfo( + MPRoktModuleImpl.MODULE_NAME, + MPRoktModuleImpl.MODULE_NAME, + true, // canOverrideExistingModule + false, // needsEagerInit + true, // hasConstants + false, // isCxxModule + // BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + false, // isTurboModule + ), + ) + moduleInfos.toMap() + } + + override fun getViewManagers(reactContext: ReactApplicationContext): List = + listOf( + ModuleSpec.viewManagerSpec { RoktLayoutViewManager() }, + ) +} diff --git a/android/src/main/java/com/mparticle/react/rokt/MPRoktModuleImpl.kt b/android/src/main/java/com/mparticle/react/rokt/MPRoktModuleImpl.kt new file mode 100644 index 0000000..f3a1423 --- /dev/null +++ b/android/src/main/java/com/mparticle/react/rokt/MPRoktModuleImpl.kt @@ -0,0 +1,254 @@ +package com.mparticle.react.rokt + +import android.app.Activity +import android.util.Log +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleOwner +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle +import com.facebook.react.bridge.Arguments +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactContext +import com.facebook.react.bridge.ReadableMap +import com.facebook.react.bridge.WritableMap +import com.facebook.react.modules.core.DeviceEventManagerModule +import com.mparticle.MParticle +import com.mparticle.MpRoktEventCallback +import com.mparticle.RoktEvent +import com.mparticle.UnloadReasons +import com.mparticle.rokt.CacheConfig +import com.mparticle.rokt.RoktConfig +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.launch + +class MPRoktModuleImpl( + private val reactContext: ReactApplicationContext, +) { + private var roktEventHandler: MpRoktEventCallback? = null + private val debug = false + + private val eventSubscriptions = mutableMapOf() + private val listeners: MutableMap = + object : LinkedHashMap() { + override fun removeEldestEntry(eldest: Map.Entry): Boolean = this.size > MAX_LISTENERS + } + + fun getName(): String = MODULE_NAME + + fun purchaseFinalized( + placementId: String, + catalogItemId: String, + success: Boolean, + ) { + MParticle.getInstance()?.Rokt()?.purchaseFinalized(placementId, catalogItemId, success) + } + + fun setRoktEventHandler(roktEventHandler: MpRoktEventCallback) { + this.roktEventHandler = roktEventHandler + } + + fun createRoktCallback(): MpRoktEventCallback { + val callback: MpRoktEventCallback = + object : MpRoktEventCallback { + override fun onLoad() { + sendCallback("onLoad", null) + } + + override fun onUnload(reason: UnloadReasons) { + sendCallback("onUnLoad", reason.toString()) + } + + override fun onShouldShowLoadingIndicator() { + sendCallback("onShouldShowLoadingIndicator", null) + } + + override fun onShouldHideLoadingIndicator() { + sendCallback("onShouldHideLoadingIndicator", null) + } + } + listeners[System.currentTimeMillis()] = callback + return callback + } + + fun sendCallback( + eventValue: String, + reason: String?, + ) { + val params = Arguments.createMap() + params.putString("callbackValue", eventValue) + if (reason != null) { + params.putString("reason", reason) + } + sendEvent(reactContext, "RoktCallback", params) + } + + fun sendEvent( + reactContext: ReactContext?, + eventName: String, + params: WritableMap?, + ) { + reactContext?.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)?.emit(eventName, params) + } + + fun readableMapToMapOfStrings(attributes: ReadableMap?): Map = + attributes?.toHashMap()?.filter { it.value is String }?.mapValues { it.value as String } + ?: emptyMap() + + fun logDebug(message: String) { + if (debug) { + Log.d("Rokt", message) + } + } + + fun String.toColorMode(): RoktConfig.ColorMode = + when (this) { + "dark" -> RoktConfig.ColorMode.DARK + "light" -> RoktConfig.ColorMode.LIGHT + else -> RoktConfig.ColorMode.SYSTEM + } + + fun buildRoktConfig(roktConfig: ReadableMap?): RoktConfig { + val builder = RoktConfig.Builder() + val configMap: Map = readableMapToMapOfStrings(roktConfig) + configMap["colorMode"]?.let { + builder.colorMode(it.toColorMode()) + } + roktConfig?.getMap("cacheConfig")?.let { + builder.cacheConfig(buildCacheConfig(it)) + } + return builder.build() + } + + fun buildCacheConfig(cacheConfigMap: ReadableMap?): CacheConfig { + val cacheDurationInSeconds = + if (cacheConfigMap?.hasKey("cacheDurationInSeconds") == true) { + cacheConfigMap.getDouble("cacheDurationInSeconds").toLong() + } else { + 0L + } + val cacheAttributes = + if (cacheConfigMap?.hasKey("cacheAttributes") == true) { + cacheConfigMap.getMap("cacheAttributes")?.toHashMap()?.mapValues { it.value as String } + } else { + null + } + return CacheConfig( + cacheDurationInSeconds = cacheDurationInSeconds, + cacheAttributes = cacheAttributes, + ) + } + + fun startRoktEventListener( + flow: Flow, + currentActivity: Activity?, + viewName: String? = null, + ) { + val activeJob = eventSubscriptions[viewName.orEmpty()]?.takeIf { it.isActive } + if (activeJob != null) { + return + } + val job = + (currentActivity as? LifecycleOwner)?.lifecycleScope?.launch { + (currentActivity as LifecycleOwner).repeatOnLifecycle(Lifecycle.State.CREATED) { + flow.collect { event -> + val params = Arguments.createMap() + var eventName: String + val placementId: String? = + when (event) { + is RoktEvent.FirstPositiveEngagement -> { + eventName = "FirstPositiveEngagement" + event.placementId + } + + RoktEvent.HideLoadingIndicator -> { + eventName = "HideLoadingIndicator" + null + } + + is RoktEvent.OfferEngagement -> { + eventName = "OfferEngagement" + event.placementId + } + + is RoktEvent.PlacementClosed -> { + eventName = "PlacementClosed" + event.placementId + } + + is RoktEvent.PlacementCompleted -> { + eventName = "PlacementCompleted" + event.placementId + } + + is RoktEvent.PlacementFailure -> { + eventName = "PlacementFailure" + event.placementId + } + + is RoktEvent.PlacementInteractive -> { + eventName = "PlacementInteractive" + event.placementId + } + + is RoktEvent.PlacementReady -> { + eventName = "PlacementReady" + event.placementId + } + + is RoktEvent.PositiveEngagement -> { + eventName = "PositiveEngagement" + event.placementId + } + + RoktEvent.ShowLoadingIndicator -> { + eventName = "ShowLoadingIndicator" + null + } + + is RoktEvent.InitComplete -> { + eventName = "InitComplete" + params.putString("status", event.success.toString()) + null + } + + is RoktEvent.OpenUrl -> { + eventName = "OpenUrl" + params.putString("url", event.url) + event.placementId + } + + is RoktEvent.CartItemInstantPurchase -> { + eventName = "CartItemInstantPurchase" + params.putString("cartItemId", event.cartItemId) + params.putString("catalogItemId", event.catalogItemId) + params.putString("currency", event.currency) + params.putString("description", event.description) + params.putString("linkedProductId", event.linkedProductId) + params.putDouble("totalPrice", event.totalPrice) + params.putInt("quantity", event.quantity) + params.putDouble("unitPrice", event.unitPrice) + event.placementId + } + + else -> { + eventName = "Unknown" + null + } + } + + placementId?.let { params.putString("placementId", it) } + params.putString("event", eventName) + viewName?.let { params.putString("viewName", it) } + sendEvent(reactContext, "RoktEvents", params) + } + } + } + eventSubscriptions[viewName.orEmpty()] = job + } + + companion object { + const val MAX_LISTENERS = 5 + const val MODULE_NAME = "MPRokt" + } +} diff --git a/android/src/main/java/com/mparticle/react/rokt/RoktLayoutViewManagerImpl.kt b/android/src/main/java/com/mparticle/react/rokt/RoktLayoutViewManagerImpl.kt new file mode 100644 index 0000000..d6ab5e5 --- /dev/null +++ b/android/src/main/java/com/mparticle/react/rokt/RoktLayoutViewManagerImpl.kt @@ -0,0 +1,79 @@ +package com.mparticle.react.rokt + +import com.facebook.react.bridge.Arguments +import com.facebook.react.bridge.ReactContext +import com.facebook.react.uimanager.ThemedReactContext +import com.facebook.react.uimanager.events.RCTEventEmitter +import com.mparticle.rokt.RoktEmbeddedView +import com.mparticle.rokt.RoktLayoutDimensionCallBack + +class RoktLayoutViewManagerImpl { + companion object { + const val REACT_CLASS = "RoktNativeLayout" + const val EVENT_HEIGHT_CHANGED = "onLayoutHeightChanged" + const val EVENT_MARGIN_CHANGED = "onLayoutMarginChanged" + } + + fun getName(): String = REACT_CLASS + + fun createViewInstance(reactContext: ThemedReactContext): RoktEmbeddedView { + val widget = RoktEmbeddedView(reactContext) + setUpWidgetListeners(widget) + return widget + } + + fun setPlaceholderName( + view: RoktEmbeddedView?, + value: String?, + ) { + view?.tag = value + } + + private fun setUpWidgetListeners(widget: RoktEmbeddedView) { + widget.dimensionCallBack = + object : RoktLayoutDimensionCallBack { + override fun onHeightChanged(height: Int) { + changeHeight(widget.context as ReactContext, height, widget.id) + } + + override fun onMarginChanged( + start: Int, + top: Int, + end: Int, + bottom: Int, + ) { + changeMargin(widget.context as ReactContext, widget.id, start, top, end, bottom) + } + } + } + + fun changeHeight( + context: ReactContext, + height: Int, + id: Int, + ) { + val event = Arguments.createMap() + event.putString("height", height.toString()) + context + .getJSModule(RCTEventEmitter::class.java) + .receiveEvent(id, EVENT_HEIGHT_CHANGED, event) + } + + fun changeMargin( + context: ReactContext, + id: Int, + start: Int, + top: Int, + end: Int, + bottom: Int, + ) { + val event = Arguments.createMap() + event.putString("marginLeft", start.toString()) + event.putString("marginTop", top.toString()) + event.putString("marginRight", end.toString()) + event.putString("marginBottom", bottom.toString()) + context + .getJSModule(RCTEventEmitter::class.java) + .receiveEvent(id, EVENT_MARGIN_CHANGED, event) + } +} diff --git a/android/src/oldarch/java/com/mparticle/react/rokt/MPRoktModule.kt b/android/src/oldarch/java/com/mparticle/react/rokt/MPRoktModule.kt new file mode 100644 index 0000000..2733060 --- /dev/null +++ b/android/src/oldarch/java/com/mparticle/react/rokt/MPRoktModule.kt @@ -0,0 +1,74 @@ +package com.mparticle.react.rokt + +import com.facebook.react.bridge.ReactApplicationContext +import com.facebook.react.bridge.ReactContextBaseJavaModule +import com.facebook.react.bridge.ReactMethod +import com.facebook.react.bridge.ReadableMap +import com.facebook.react.uimanager.NativeViewHierarchyManager +import com.facebook.react.uimanager.UIManagerModule +import com.mparticle.MParticle +import com.mparticle.WrapperSdk +import com.mparticle.rokt.RoktEmbeddedView +import java.lang.ref.WeakReference + +class MPRoktModule( + private val reactContext: ReactApplicationContext, +) : ReactContextBaseJavaModule(reactContext) { + init { + MParticle.getInstance()?.setWrapperSdk(WrapperSdk.WrapperSdkReactNative, "") + } + + private val impl = MPRoktModuleImpl(reactContext) + + override fun getName(): String = impl.getName() + + @ReactMethod + fun selectPlacements( + identifier: String, + attributes: ReadableMap?, + placeholders: ReadableMap?, + roktConfig: ReadableMap?, + fontFilesMap: ReadableMap?, + ) { + if (identifier.isBlank()) { + impl.logDebug("selectPlacements failed. identifier cannot be empty") + return + } + val uiManager = reactContext.getNativeModule(UIManagerModule::class.java) + MParticle.getInstance()?.Rokt()?.events(identifier)?.let { + impl.startRoktEventListener(it, reactContext.currentActivity, identifier) + } + + val config = roktConfig?.let { impl.buildRoktConfig(it) } + uiManager?.addUIBlock { nativeViewHierarchyManager -> + MParticle.getInstance()?.Rokt()?.selectPlacements( + identifier = identifier, + attributes = impl.readableMapToMapOfStrings(attributes), + callbacks = impl.createRoktCallback(), + embeddedViews = safeUnwrapPlaceholders(placeholders, nativeViewHierarchyManager), + fontTypefaces = null, // TODO + config = config, + ) + } + } + + private fun safeUnwrapPlaceholders( + placeholders: ReadableMap?, + nativeViewHierarchyManager: NativeViewHierarchyManager, + ): Map> { + val placeholderMap: MutableMap> = HashMap() + + if (placeholders != null) { + placeholderMap.putAll( + placeholders + .toHashMap() + .filterValues { value -> value is Double } + .mapValues { pair -> (pair.value as Double).toInt() } + .mapValues { pair -> nativeViewHierarchyManager.resolveView(pair.value) as? RoktEmbeddedView } + .filterValues { value -> value != null } + .mapValues { WeakReference(it.value as RoktEmbeddedView) }, + ) + } + return placeholderMap + } +} diff --git a/android/src/oldarch/java/com/mparticle/react/rokt/RoktLayoutViewManager.kt b/android/src/oldarch/java/com/mparticle/react/rokt/RoktLayoutViewManager.kt new file mode 100644 index 0000000..9e2d144 --- /dev/null +++ b/android/src/oldarch/java/com/mparticle/react/rokt/RoktLayoutViewManager.kt @@ -0,0 +1,34 @@ +package com.mparticle.react.rokt + +import com.facebook.react.common.MapBuilder +import com.facebook.react.uimanager.ThemedReactContext +import com.facebook.react.uimanager.ViewGroupManager +import com.mparticle.rokt.RoktEmbeddedView + +class RoktLayoutViewManager : ViewGroupManager() { + private val impl = RoktLayoutViewManagerImpl() + + override fun getName(): String = impl.getName() + + override fun createViewInstance(reactContext: ThemedReactContext): RoktEmbeddedView = impl.createViewInstance(reactContext) + + override fun getExportedCustomDirectEventTypeConstants(): Map? = + MapBuilder + .builder() + .put( + RoktLayoutViewManagerImpl.EVENT_HEIGHT_CHANGED, + MapBuilder.of("registrationName", RoktLayoutViewManagerImpl.EVENT_HEIGHT_CHANGED), + ).put( + RoktLayoutViewManagerImpl.EVENT_MARGIN_CHANGED, + MapBuilder.of("registrationName", RoktLayoutViewManagerImpl.EVENT_MARGIN_CHANGED), + ).build() + + override fun needsCustomLayoutForChildren(): Boolean = false + + fun setPlaceholderName( + view: RoktEmbeddedView?, + value: String?, + ) { + impl.setPlaceholderName(view, value) + } +} diff --git a/android/src/test/java/com/mparticle/react/testutils/MockMParticleUser.java b/android/src/test/java/com/mparticle/react/testutils/MockMParticleUser.java index 8a1babe..f071580 100644 --- a/android/src/test/java/com/mparticle/react/testutils/MockMParticleUser.java +++ b/android/src/test/java/com/mparticle/react/testutils/MockMParticleUser.java @@ -4,10 +4,11 @@ import androidx.annotation.Nullable; import com.mparticle.MParticle; -import com.mparticle.UserAttributeListener; import com.mparticle.UserAttributeListenerType; import com.mparticle.consent.ConsentState; import com.mparticle.identity.MParticleUser; +import com.mparticle.audience.AudienceTask; +import com.mparticle.audience.AudienceResponse; import java.util.Map; @@ -99,5 +100,10 @@ public long getFirstSeenTime() { public long getLastSeenTime() { return 0; } + + @Override + public AudienceTask getUserAudiences() { + return null; + } } diff --git a/android/src/test/java/com/mparticle/react/testutils/MockMap.java b/android/src/test/java/com/mparticle/react/testutils/MockMap.java index 5ae32dc..e1b74c0 100644 --- a/android/src/test/java/com/mparticle/react/testutils/MockMap.java +++ b/android/src/test/java/com/mparticle/react/testutils/MockMap.java @@ -1,10 +1,13 @@ package com.mparticle.react.testutils; +import androidx.annotation.NonNull; + +import com.facebook.react.bridge.Dynamic; +import com.facebook.react.bridge.DynamicFromObject; import com.facebook.react.bridge.ReadableArray; import com.facebook.react.bridge.ReadableMap; import com.facebook.react.bridge.ReadableMapKeySetIterator; import com.facebook.react.bridge.ReadableType; -import com.facebook.react.bridge.WritableArray; import com.facebook.react.bridge.WritableMap; import org.json.JSONException; @@ -61,6 +64,11 @@ public int getInt(String name) { return (int) map.get(name); } + @Override + public long getLong(String name) { + return (long) map.get(name); + } + @Override public String getString(String name) { return (String) map.get(name); @@ -105,6 +113,11 @@ public ReadableMapKeySetIterator keySetIterator() { return new MockReadableMapKeySetIterator(map.keySet()); } + @Override + public java.util.HashMap toHashMap() { + return new java.util.HashMap<>(map); + } + @Override public void putNull(String key) { map.put(key, null); @@ -125,18 +138,23 @@ public void putInt(String key, int value) { map.put(key, value); } + @Override + public void putLong(String key, long value) { + map.put(key, value); + } + @Override public void putString(String key, String value) { map.put(key, value); } @Override - public void putArray(String key, WritableArray value) { + public void putArray(String key, ReadableArray value) { map.put(key, value); } @Override - public void putMap(String key, WritableMap value) { + public void putMap(String key, ReadableMap value) { map.put(key, value); } @@ -145,6 +163,22 @@ public void merge(ReadableMap source) { throw new RuntimeException("Not Implemented"); } + @Override + public WritableMap copy() { + return new MockMap(new java.util.HashMap<>(map)); + } + + @NonNull + @Override + public Iterator> getEntryIterator() { + return map.entrySet().iterator(); + } + + @NonNull + @Override + public Dynamic getDynamic(@NonNull String s) { + return new DynamicFromObject(map.get(s)); + } class MockReadableMapKeySetIterator implements ReadableMapKeySetIterator { List keys; diff --git a/android/src/test/java/com/mparticle/react/testutils/MockReadableArray.java b/android/src/test/java/com/mparticle/react/testutils/MockReadableArray.java index b26e217..65329c4 100644 --- a/android/src/test/java/com/mparticle/react/testutils/MockReadableArray.java +++ b/android/src/test/java/com/mparticle/react/testutils/MockReadableArray.java @@ -31,6 +31,11 @@ public int getInt(int index) { return 0; } + @Override + public long getLong(int index) { + return 0; + } + @Override public String getString(int index) { return null; @@ -50,4 +55,14 @@ public ReadableMap getMap(int index) { public ReadableType getType(int index) { return null; } + + @Override + public com.facebook.react.bridge.Dynamic getDynamic(int index) { + return null; + } + + @Override + public java.util.ArrayList toArrayList() { + return new java.util.ArrayList<>(); + } } \ No newline at end of file diff --git a/dev-link.sh b/dev-link.sh new file mode 100755 index 0000000..e94a607 --- /dev/null +++ b/dev-link.sh @@ -0,0 +1,16 @@ +#!/bin/bash +set -e + +echo "🔨 Building..." +yarn build + +echo "📦 Packing..." +yarn pack --filename react-native-mparticle-latest.tgz + +echo "🔄 Updating sample..." +cd sample +rm -rf node_modules/react-native-mparticle +tar -xzf ../react-native-mparticle-latest.tgz +mv package node_modules/react-native-mparticle + +echo "✅ Done! Sample updated with latest changes." \ No newline at end of file diff --git a/ios/RNMParticle.xcodeproj/project.pbxproj b/ios/RNMParticle.xcodeproj/project.pbxproj index 600194b..88cabcc 100644 --- a/ios/RNMParticle.xcodeproj/project.pbxproj +++ b/ios/RNMParticle.xcodeproj/project.pbxproj @@ -171,7 +171,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -213,7 +213,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.4; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; diff --git a/ios/RNMParticle/RNMPRokt.h b/ios/RNMParticle/RNMPRokt.h new file mode 100644 index 0000000..6cc24ba --- /dev/null +++ b/ios/RNMParticle/RNMPRokt.h @@ -0,0 +1,8 @@ +#import +#import + +@interface RNMPRokt : NSObject + +@property (nonatomic, weak, nullable) RCTBridge *bridge; + +@end diff --git a/ios/RNMParticle/RNMPRokt.m b/ios/RNMParticle/RNMPRokt.m new file mode 100644 index 0000000..538200c --- /dev/null +++ b/ios/RNMParticle/RNMPRokt.m @@ -0,0 +1,189 @@ +#import "RNMPRokt.h" +#if defined(__has_include) && __has_include() + #import + #import +#elif defined(__has_include) && __has_include() + #import +#else + #import "mParticle.h" +#endif +#if defined(__has_include) && __has_include() + #import +#elif defined(__has_include) && __has_include() + #import +#else + #import "mParticle_Apple_SDK-Swift.h" +#endif +#import +#import +#import +#import +#import +#import "RoktEventManager.h" + +@interface RNMPRokt () + +@property (nonatomic, nullable) RoktEventManager *eventManager; + +@end + +@implementation RNMPRokt + +@synthesize bridge = _bridge; + +RCT_EXTERN void RCTRegisterModule(Class); + ++ (NSString *)moduleName { + return @"MPRokt"; +} + ++ (void)load { + RCTRegisterModule(self); +} + +RCT_EXPORT_METHOD(selectPlacements:(NSString *) identifer attributes:(NSDictionary *)attributes placeholders:(NSDictionary * _Nullable)placeholders roktConfig:(NSDictionary * _Nullable)roktConfig fontFilesMap:(NSDictionary * _Nullable)fontFilesMap) +{ + NSMutableDictionary *finalAttributes = [self convertToMutableDictionaryOfStrings:attributes]; + MPRoktConfig *config = [self buildRoktConfigFromDict:roktConfig]; + + // Create callback implementation + MPRoktEventCallback *callbacks = [[MPRoktEventCallback alloc] init]; + + __weak typeof(self) weakSelf = self; + + callbacks.onLoad = ^{ + [self.eventManager onRoktCallbackReceived:@"onLoad"]; + }; + + callbacks.onUnLoad = ^{ + [self.eventManager onRoktCallbackReceived:@"onUnLoad"]; + RCTLogInfo(@"unloaded"); + }; + + callbacks.onShouldShowLoadingIndicator = ^{ + [self.eventManager onRoktCallbackReceived:@"onShouldShowLoadingIndicator"]; + }; + + callbacks.onShouldHideLoadingIndicator = ^{ + [self.eventManager onRoktCallbackReceived:@"onShouldHideLoadingIndicator"]; + }; + + callbacks.onEmbeddedSizeChange = ^(NSString *placementId, CGFloat height) { + [self.eventManager onWidgetHeightChanges:height placement:placementId]; + }; + + [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) { + NSMutableDictionary *nativePlaceholders = [self getNativePlaceholders:placeholders viewRegistry:viewRegistry]; + + [self subscribeViewEvents:identifer]; + + // TODO: Add placeholders and fontFilesMap + [[[MParticle sharedInstance] rokt] selectPlacements:identifer + attributes:finalAttributes + embeddedViews:nativePlaceholders + config:config + callbacks:callbacks]; + }]; +} + +- (NSMutableDictionary*)convertToMutableDictionaryOfStrings:(NSDictionary*)attributes +{ + NSMutableDictionary *finalAttributes = [attributes mutableCopy]; + NSArray *keysForNullValues = [finalAttributes allKeysForObject:[NSNull null]]; + [finalAttributes removeObjectsForKeys:keysForNullValues]; + + NSSet *keys = [finalAttributes keysOfEntriesPassingTest:^BOOL(id key, id obj, BOOL *stop) { + return ![obj isKindOfClass:[NSString class]]; + }]; + + [finalAttributes removeObjectsForKeys:[keys allObjects]]; + return finalAttributes; + +} + +- (MPColorMode)stringToColorMode:(NSString*)colorString +{ + if ([colorString isEqualToString:@"light"]) { + return MPColorModeLight; + } + else if ([colorString isEqualToString:@"dark"]) { + return MPColorModeDark; + } + else { + return MPColorModeSystem; + } +} + +- (MPRoktConfig *)buildRoktConfigFromDict:(NSDictionary *)configMap { + MPRoktConfig *config = [[MPRoktConfig alloc] init]; + BOOL isConfigEmpty = YES; + + NSString *colorModeString = configMap[@"colorMode"]; + if (colorModeString && [colorModeString isKindOfClass:[NSString class]]) { + if (@available(iOS 12.0, *)) { + isConfigEmpty = NO; + if ([colorModeString isEqualToString:@"dark"]) { + if (@available(iOS 13.0, *)) { + config.colorMode = MPColorModeDark; + } + } else if ([colorModeString isEqualToString:@"light"]) { + config.colorMode = MPColorModeLight; + } else { + // default: "system" + config.colorMode = MPColorModeSystem; + } + } + } + + NSDictionary *cacheConfigMap = configMap[@"cacheConfig"]; + if (cacheConfigMap && [cacheConfigMap isKindOfClass:[NSDictionary class]]) { + isConfigEmpty = NO; + NSNumber *cacheDuration = cacheConfigMap[@"cacheDurationInSeconds"]; + if (!cacheDuration) { + cacheDuration = @0; + } + NSDictionary *cacheAttributes = cacheConfigMap[@"cacheAttributes"]; + config.cacheAttributes = cacheAttributes; + config.cacheDuration = cacheDuration; + } + + return isConfigEmpty ? nil : config; +} + +- (void)subscribeViewEvents:(NSString* _Nonnull) viewName +{ + if (self.eventManager == nil) { + self.eventManager = [RoktEventManager allocWithZone: nil]; + } + [[[MParticle sharedInstance] rokt] events:viewName onEvent:^(MPRoktEvent * _Nonnull roktEvent) { + [self.eventManager onRoktEvents:roktEvent viewName:viewName]; + }]; +} + +- (NSMutableDictionary *)getNativePlaceholders:(NSDictionary *)placeholders viewRegistry:(NSDictionary *)viewRegistry +{ + NSMutableDictionary *nativePlaceholders = [[NSMutableDictionary alloc]initWithCapacity:placeholders.count]; + + for(id key in placeholders){ +//#ifdef RCT_NEW_ARCH_ENABLED + /*RoktNativeWidgetComponentView *wrapperView = (RoktNativeWidgetComponentView *)viewRegistry[[placeholders objectForKey:key]]; + if (!wrapperView || ![wrapperView isKindOfClass:[RoktNativeWidgetComponentView class]]) { + RCTLogError(@"Cannot find RoktNativeWidgetComponentView with tag #%@", key); + continue; + } + nativePlaceholders[key] = wrapperView.roktEmbeddedView;*/ +//#else + MPRoktEmbeddedView *view = viewRegistry[[placeholders objectForKey:key]]; + if (!view || ![view isKindOfClass:[MPRoktEmbeddedView class]]) { + RCTLogError(@"Cannot find RoktEmbeddedView with tag #%@", key); + continue; + } + + nativePlaceholders[key] = view; +//#endif // RCT_NEW_ARCH_ENABLED + } + + return nativePlaceholders; +} + +@end diff --git a/ios/RNMParticle/RoktEventManager.h b/ios/RNMParticle/RoktEventManager.h new file mode 100644 index 0000000..6c7bd90 --- /dev/null +++ b/ios/RNMParticle/RoktEventManager.h @@ -0,0 +1,16 @@ +#import +#import +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface RoktEventManager : RCTEventEmitter ++ (instancetype _Nonnull)allocWithZone:(NSZone * _Nullable)zone; +- (void)onWidgetHeightChanges:(CGFloat)widgetHeight placement:(NSString * _Nonnull)selectedPlacement; +- (void)onFirstPositiveResponse; +- (void)onRoktCallbackReceived:(NSString * _Nonnull)eventValue; +- (void)onRoktEvents:(MPRoktEvent * _Nonnull)event viewName:(NSString * _Nullable)viewName; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/RNMParticle/RoktEventManager.m b/ios/RNMParticle/RoktEventManager.m new file mode 100644 index 0000000..5369324 --- /dev/null +++ b/ios/RNMParticle/RoktEventManager.m @@ -0,0 +1,174 @@ +#import "RoktEventManager.h" +#import + +@implementation RoktEventManager +{ + bool hasListeners; +} + +RCT_EXPORT_MODULE(RoktEventManager); + ++ (id)allocWithZone:(NSZone *)zone { + static RoktEventManager *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [super allocWithZone:zone]; + }); + return sharedInstance; +} + +// Will be called when this module's first listener is added. +-(void)startObserving { + hasListeners = YES; +} + +// Will be called when this module's last listener is removed, or on dealloc. +-(void)stopObserving { + hasListeners = NO; +} + + +- (NSArray *)supportedEvents +{ + return @[@"LayoutHeightChanges", @"FirstPositiveResponse", @"RoktCallback", @"RoktEvents"]; +} + +- (void)onWidgetHeightChanges:(CGFloat)widgetHeight placement:(NSString*) selectedPlacement +{ + if (hasListeners) { + [self sendEventWithName:@"LayoutHeightChanges" body:@{@"height": [NSNumber numberWithDouble: widgetHeight], + @"selectedPlacement": selectedPlacement + }]; + } +} + +- (void)onFirstPositiveResponse +{ + if (hasListeners) { + [self sendEventWithName:@"FirstPositiveResponse" body:@{@"":@""}]; + } +} + +- (void)onRoktCallbackReceived:(NSString*)eventValue +{ + if (hasListeners) { + [self sendEventWithName:@"RoktCallback" body:@{@"callbackValue": eventValue}]; + } +} + +- (void)onRoktEvents:(MPRoktEvent * _Nonnull)event viewName:(NSString * _Nullable)viewName +{ + if (hasListeners) { + NSString *placementId; + NSString *eventName = @""; + NSString *status; + NSString *url; + NSString *cartItemId; + NSString *catalogItemId; + NSString *currency; + NSString *itemDescription; + NSString *linkedProductId; + NSString *providerData; + NSDecimalNumber *quantity; + NSDecimalNumber *totalPrice; + NSDecimalNumber *unitPrice; + + if ([event isKindOfClass:[MPRoktShowLoadingIndicator class]]) { + eventName = @"ShowLoadingIndicator"; + } else if ([event isKindOfClass:[MPRoktHideLoadingIndicator class]]) { + eventName = @"HideLoadingIndicator"; + } else if ([event isKindOfClass:[MPRoktPlacementInteractive class]]) { + placementId = ((MPRoktPlacementInteractive *)event).placementId; + eventName = @"PlacementInteractive"; + } else if ([event isKindOfClass:[MPRoktPlacementReady class]]) { + placementId = ((MPRoktPlacementReady *)event).placementId; + eventName = @"PlacementReady"; + } else if ([event isKindOfClass:[MPRoktOfferEngagement class]]) { + placementId = ((MPRoktOfferEngagement *)event).placementId; + eventName = @"OfferEngagement"; + } else if ([event isKindOfClass:[MPRoktPositiveEngagement class]]) { + placementId = ((MPRoktPositiveEngagement *)event).placementId; + eventName = @"PositiveEngagement"; + } else if ([event isKindOfClass:[MPRoktPlacementClosed class]]) { + placementId = ((MPRoktPlacementClosed *)event).placementId; + eventName = @"PlacementClosed"; + } else if ([event isKindOfClass:[MPRoktPlacementCompleted class]]) { + placementId = ((MPRoktPlacementCompleted *)event).placementId; + eventName = @"PlacementCompleted"; + } else if ([event isKindOfClass:[MPRoktPlacementFailure class]]) { + placementId = ((MPRoktPlacementFailure *)event).placementId; + eventName = @"PlacementFailure"; + } else if ([event isKindOfClass:[MPRoktFirstPositiveEngagement class]]) { + placementId = ((MPRoktFirstPositiveEngagement *)event).placementId; + eventName = @"FirstPositiveEngagement"; + } else if ([event isKindOfClass:[MPRoktInitComplete class]]) { + eventName = @"InitComplete"; + status = ((MPRoktInitComplete *)event).success ? @"true" : @"false"; + } else if ([event isKindOfClass:[MPRoktOpenUrl class]]) { + eventName = @"OpenUrl"; + placementId = ((MPRoktOpenUrl *)event).placementId; + url = ((MPRoktOpenUrl *)event).url; + } else if ([event isKindOfClass:[MPRoktCartItemInstantPurchase class]]) { + MPRoktCartItemInstantPurchase *cartEvent = (MPRoktCartItemInstantPurchase *)event; + eventName = @"CartItemInstantPurchase"; + // Required properties + placementId = cartEvent.placementId; + cartItemId = cartEvent.cartItemId; + catalogItemId = cartEvent.catalogItemId; + currency = cartEvent.currency; + providerData = cartEvent.providerData; + // Optional properties + linkedProductId = cartEvent.linkedProductId; + // Overridden description property + itemDescription = cartEvent.description; + // Decimal properties + quantity = cartEvent.quantity; + totalPrice = cartEvent.totalPrice; + unitPrice = cartEvent.unitPrice; + } + NSMutableDictionary *payload = [@{@"event": eventName} mutableCopy]; + if (viewName != nil) { + [payload setObject:viewName forKey:@"viewName"]; + } + if (placementId != nil) { + [payload setObject:placementId forKey:@"placementId"]; + } + if (status != nil) { + [payload setObject:status forKey:@"status"]; + } + if (url != nil) { + [payload setObject:url forKey:@"url"]; + } + if (cartItemId != nil) { + [payload setObject:cartItemId forKey:@"cartItemId"]; + } + if (catalogItemId != nil) { + [payload setObject:catalogItemId forKey:@"catalogItemId"]; + } + if (currency != nil) { + [payload setObject:currency forKey:@"currency"]; + } + if (itemDescription != nil) { + [payload setObject:itemDescription forKey:@"description"]; + } + if (linkedProductId != nil) { + [payload setObject:linkedProductId forKey:@"linkedProductId"]; + } + if (providerData != nil) { + [payload setObject:providerData forKey:@"providerData"]; + } + if (quantity != nil) { + [payload setObject:quantity forKey:@"quantity"]; + } + if (totalPrice != nil) { + [payload setObject:totalPrice forKey:@"totalPrice"]; + } + if (unitPrice != nil) { + [payload setObject:unitPrice forKey:@"unitPrice"]; + } + + [self sendEventWithName:@"RoktEvents" body:payload]; + } +} + +@end diff --git a/ios/RNMParticle/RoktWidgetManager.m b/ios/RNMParticle/RoktWidgetManager.m new file mode 100644 index 0000000..a6c5148 --- /dev/null +++ b/ios/RNMParticle/RoktWidgetManager.m @@ -0,0 +1,17 @@ +#import +#import +#import + +@interface RoktNativeWidgetManager : RCTViewManager +@end + +@implementation RoktNativeWidgetManager + +RCT_EXPORT_MODULE(RoktNativeLayout) + +- (UIView *)view +{ + return [[MPRoktEmbeddedView alloc] init]; +} + +@end diff --git a/js/index.d.ts b/js/index.d.ts new file mode 100644 index 0000000..93afa54 --- /dev/null +++ b/js/index.d.ts @@ -0,0 +1,441 @@ +import { Rokt, CacheConfig, IRoktConfig, ColorMode } from './rokt/rokt'; +import RoktLayoutView, { RoktLayoutViewProps } from './rokt/rokt-layout-view'; + +// ******** Types ******** +export interface UserAttributes { + [key: string]: string | string[] | number | boolean; +} + +export interface UserIdentities { + [key: number]: string; +} + +export interface CustomAttributes { + [key: string]: string | number | boolean; +} + +export interface MParticleErrorResponse { + message: string; + code: number; +} + +export interface AttributionResult { + [key: string]: any; +} + +export type CompletionCallback = (result: T) => void; +export type ErrorCallback = (error: MParticleError | null) => void; +export type IdentityCallback = ( + error: MParticleError | null, + userId: string | null, + previousUserId: string | null +) => void; + +// ******** Constants ******** +export declare const EventType: { + readonly Navigation: 1; + readonly Location: 2; + readonly Search: 3; + readonly Transaction: 4; + readonly UserContent: 5; + readonly UserPreference: 6; + readonly Social: 7; + readonly Other: 8; + readonly Media: 9; +}; + +export declare const UserAttributeType: { + readonly FirstName: '$FirstName'; + readonly LastName: '$LastName'; + readonly Address: '$Address'; + readonly State: '$State'; + readonly City: '$City'; + readonly Zipcode: '$Zip'; + readonly Country: '$Country'; + readonly Age: '$Age'; + readonly Gender: '$Gender'; + readonly MobileNumber: '$Mobile'; +}; + +export declare const UserIdentityType: { + readonly Other: 0; + readonly CustomerId: 1; + readonly Facebook: 2; + readonly Twitter: 3; + readonly Google: 4; + readonly Microsoft: 5; + readonly Yahoo: 6; + readonly Email: 7; + readonly Alias: 8; + readonly FacebookCustomAudienceId: 9; + readonly Other2: 10; + readonly Other3: 11; + readonly Other4: 12; + readonly Other5: 13; + readonly Other6: 14; + readonly Other7: 15; + readonly Other8: 16; + readonly Other9: 17; + readonly Other10: 18; + readonly MobileNumber: 19; + readonly PhoneNumber2: 20; + readonly PhoneNumber3: 21; + readonly IOSAdvertiserId: 22; + readonly IOSVendorId: 23; + readonly PushToken: 24; + readonly DeviceApplicationStamp: 25; +}; + +export declare const ProductActionType: { + readonly AddToCart: 1; + readonly RemoveFromCart: 2; + readonly Checkout: 3; + readonly CheckoutOption: 4; + readonly Click: 5; + readonly ViewDetail: 6; + readonly Purchase: 7; + readonly Refund: 8; + readonly AddToWishlist: 9; + readonly RemoveFromWishlist: 10; +}; + +export declare const PromotionActionType: { + readonly View: 0; + readonly Click: 1; +}; + +export declare const ATTAuthStatus: { + readonly NotDetermined: 0; + readonly Restricted: 1; + readonly Denied: 2; + readonly Authorized: 3; +}; + +// ******** Main API ******** +export declare const upload: () => void; +export declare const setUploadInterval: (uploadInterval: number) => void; +export declare const logEvent: ( + eventName: string, + type?: number, + attributes?: CustomAttributes | null +) => void; +export declare const logMPEvent: (event: Event) => void; +export declare const logCommerceEvent: (commerceEvent: CommerceEvent) => void; +export declare const logScreenEvent: ( + screenName: string, + attributes?: CustomAttributes | null, + shouldUploadEvent?: boolean +) => void; +export declare const setATTStatus: (status: number) => void; +export declare const setATTStatusWithCustomTimestamp: ( + status: number, + timestamp: number +) => void; +export declare const setOptOut: (optOut: boolean) => void; +export declare const getOptOut: ( + completion: CompletionCallback +) => void; +export declare const addGDPRConsentState: ( + newConsentState: GDPRConsent, + purpose: string +) => void; +export declare const removeGDPRConsentStateWithPurpose: ( + purpose: string +) => void; +export declare const setCCPAConsentState: ( + newConsentState: CCPAConsent +) => void; +export declare const removeCCPAConsentState: () => void; +export declare const isKitActive: ( + kitId: number, + completion: CompletionCallback +) => void; +export declare const getAttributions: ( + completion: CompletionCallback +) => void; +export declare const logPushRegistration: ( + registrationField1: string, + registrationField2: string +) => void; +export declare const getSession: ( + completion: CompletionCallback +) => void; +export declare const setLocation: (latitude: number, longitude: number) => void; + +// ******** Identity ******** +export declare class User { + readonly userId: string; + constructor(userId: string); + getMpid(): string; + setUserAttribute( + key: string, + value: string | string[] | number | boolean + ): void; + setUserAttributeArray(key: string, value: string[]): void; + getUserAttributes(completion: CompletionCallback): void; + setUserTag(value: string): void; + incrementUserAttribute(key: string, value: number): void; + removeUserAttribute(key: string): void; + getUserIdentities(completion: CompletionCallback): void; + getFirstSeen(completion: CompletionCallback): void; + getLastSeen(completion: CompletionCallback): void; +} + +export declare class IdentityRequest { + [key: number]: string; + setEmail(email: string): this; + setCustomerID(customerId: string): this; + setUserIdentity(userIdentity: string, identityType: number): this; + /** + * @deprecated This method is deprecated and will be removed in a future version. + */ + setOnUserAlias(onUserAlias: any): void; +} + +export declare class Identity { + static getCurrentUser(completion: CompletionCallback): void; + static identify( + identityRequest: IdentityRequest, + completion: IdentityCallback + ): void; + static login( + identityRequest: IdentityRequest, + completion: IdentityCallback + ): void; + static logout( + identityRequest: IdentityRequest, + completion: IdentityCallback + ): void; + static modify( + identityRequest: IdentityRequest, + completion: IdentityCallback + ): void; + static aliasUsers( + aliasRequest: AliasRequest, + completion: CompletionCallback + ): void; +} + +// ******** Commerce ******** +export declare class Impression { + readonly impressionListName: string; + readonly products: Product[]; + constructor(impressionListName: string, products: Product[]); +} + +export declare class Promotion { + readonly id: string; + readonly name: string; + readonly creative: string; + readonly position: string; + constructor(id: string, name: string, creative: string, position: string); +} + +export declare class AliasRequest { + sourceMpid(mpid: string): this; + destinationMpid(mpid: string): this; + endTime(endTime: number): this; + startTime(startTime: number): this; +} + +export declare class TransactionAttributes { + readonly transactionId: string; + affiliation?: string; + revenue?: number; + shipping?: number; + tax?: number; + couponCode?: string; + constructor(transactionId: string); + setAffiliation(affiliation: string): this; + setRevenue(revenue: string | number): this; + setShipping(shipping: string | number): this; + setTax(tax: string | number): this; + setCouponCode(couponCode: string): this; +} + +export declare class Product { + readonly name: string; + readonly sku: string; + readonly price: number; + readonly quantity: number; + brand?: string; + couponCode?: string; + position?: number; + category?: string; + variant?: string; + customAttributes?: CustomAttributes; + constructor(name: string, sku: string, price: number, quantity?: number); + setBrand(brand: string): this; + setCouponCode(couponCode: string): this; + setPosition(position: number): this; + setCategory(category: string): this; + setVariant(variant: string): this; + setCustomAttributes(customAttributes: CustomAttributes): this; +} + +export declare class GDPRConsent { + consented?: boolean; + document?: string; + timestamp?: number; + location?: string; + hardwareId?: string; + constructor( + consented?: boolean, + doc?: string, + timestamp?: number, + location?: string, + hardwareId?: string + ); + setConsented(consented: boolean): this; + setDocument(doc: string): this; + setTimestamp(timestamp: number): this; + setLocation(location: string): this; + setHardwareId(hardwareId: string): this; +} + +export declare class CCPAConsent { + consented?: boolean; + document?: string; + timestamp?: number; + location?: string; + hardwareId?: string; + constructor( + consented?: boolean, + doc?: string, + timestamp?: number, + location?: string, + hardwareId?: string + ); + setConsented(consented: boolean): this; + setDocument(doc: string): this; + setTimestamp(timestamp: number): this; + setLocation(location: string): this; + setHardwareId(hardwareId: string): this; +} + +export declare class CommerceEvent { + productActionType?: number; + promotionActionType?: number; + products?: Product[]; + transactionAttributes?: TransactionAttributes; + promotions?: Promotion[]; + impressions?: Impression[]; + screenName?: string; + currency?: string; + customAttributes?: CustomAttributes; + checkoutOptions?: string; + productActionListName?: string; + productActionListSource?: string; + checkoutStep?: number; + nonInteractive?: boolean; + shouldUploadEvent?: boolean; + static createProductActionEvent( + productActionType: number, + products: Product[], + transactionAttributes?: TransactionAttributes + ): CommerceEvent; + static createPromotionEvent( + promotionActionType: number, + promotions: Promotion[] + ): CommerceEvent; + static createImpressionEvent(impressions: Impression[]): CommerceEvent; + setTransactionAttributes(transactionAttributes: TransactionAttributes): this; + setProductActionType(productActionType: number): this; + setPromotionActionType(promotionActionType: number): this; + setProducts(products: Product[]): this; + setPromotions(promotions: Promotion[]): this; + setImpressions(impressions: Impression[]): this; + setScreenName(screenName: string): this; + setCurrency(currency: string): this; + setCustomAttributes(customAttributes: CustomAttributes): this; + setCheckoutOptions(checkoutOptions: string): this; + setProductActionListName(productActionListName: string): this; + setProductActionListSource(productActionListSource: string): this; + setCheckoutStep(checkoutStep: number): this; + setNonInteractive(nonInteractive: boolean): this; + setShouldUploadEvent(shouldUploadEvent: boolean): this; +} + +export declare class Event { + category?: string; + duration?: number; + endTime?: number; + info?: CustomAttributes; + name?: string; + startTime?: number; + type?: number; + shouldUploadEvent?: boolean; + customFlags?: { [key: string]: string }; + setCategory(category: string): this; + setDuration(duration: number): this; + setEndTime(endTime: number): this; + setInfo(info: CustomAttributes): this; + setName(name: string): this; + setStartTime(startTime: number): this; + setType(type: number): this; + setShouldUploadEvent(shouldUploadEvent: boolean): this; + setCustomFlags(customFlags: { [key: string]: string }): this; +} + +export declare class MParticleError { + readonly message: string; + readonly code: number; + constructor(errorResponse: MParticleErrorResponse); +} + +// Export Rokt functionality +export { + Rokt, + CacheConfig, + IRoktConfig, + ColorMode, + RoktLayoutView, + RoktLayoutViewProps, +}; + +// Default export +declare const _default: { + EventType: typeof EventType; + UserAttributeType: typeof UserAttributeType; + UserIdentityType: typeof UserIdentityType; + ProductActionType: typeof ProductActionType; + PromotionActionType: typeof PromotionActionType; + ATTAuthStatus: typeof ATTAuthStatus; + upload: typeof upload; + setUploadInterval: typeof setUploadInterval; + logEvent: typeof logEvent; + logMPEvent: typeof logMPEvent; + logCommerceEvent: typeof logCommerceEvent; + logScreenEvent: typeof logScreenEvent; + setATTStatus: typeof setATTStatus; + setATTStatusWithCustomTimestamp: typeof setATTStatusWithCustomTimestamp; + setOptOut: typeof setOptOut; + getOptOut: typeof getOptOut; + addGDPRConsentState: typeof addGDPRConsentState; + removeGDPRConsentStateWithPurpose: typeof removeGDPRConsentStateWithPurpose; + setCCPAConsentState: typeof setCCPAConsentState; + removeCCPAConsentState: typeof removeCCPAConsentState; + isKitActive: typeof isKitActive; + getAttributions: typeof getAttributions; + logPushRegistration: typeof logPushRegistration; + getSession: typeof getSession; + setLocation: typeof setLocation; + User: typeof User; + IdentityRequest: typeof IdentityRequest; + Identity: typeof Identity; + Impression: typeof Impression; + Promotion: typeof Promotion; + AliasRequest: typeof AliasRequest; + TransactionAttributes: typeof TransactionAttributes; + Product: typeof Product; + GDPRConsent: typeof GDPRConsent; + CCPAConsent: typeof CCPAConsent; + CommerceEvent: typeof CommerceEvent; + Event: typeof Event; + MParticleError: typeof MParticleError; + Rokt: typeof Rokt; + CacheConfig: typeof CacheConfig; + RoktLayoutView: typeof RoktLayoutView; +}; + +export default _default; diff --git a/js/index.js b/js/index.js index f2ed42b..a243849 100644 --- a/js/index.js +++ b/js/index.js @@ -1,6 +1,8 @@ -'use strict' +'use strict'; -import { NativeModules } from 'react-native' +import { NativeModules } from 'react-native'; +import { Rokt, CacheConfig } from './rokt/rokt'; +import RoktLayoutView from './rokt/rokt-layout-view'; // ******** Constants ******** @@ -13,8 +15,8 @@ const EventType = { UserPreference: 6, Social: 7, Other: 8, - Media: 9 -} + Media: 9, +}; const UserAttributeType = { FirstName: '$FirstName', @@ -26,8 +28,8 @@ const UserAttributeType = { Country: '$Country', Age: '$Age', Gender: '$Gender', - MobileNumber: '$Mobile' -} + MobileNumber: '$Mobile', +}; const UserIdentityType = { Other: 0, @@ -55,8 +57,8 @@ const UserIdentityType = { IOSAdvertiserId: 22, IOSVendorId: 23, PushToken: 24, - DeviceApplicationStamp: 25 -} + DeviceApplicationStamp: 25, +}; const ProductActionType = { AddToCart: 1, @@ -68,598 +70,624 @@ const ProductActionType = { Purchase: 7, Refund: 8, AddToWishlist: 9, - RemoveFromWishlist: 10 -} + RemoveFromWishlist: 10, +}; const PromotionActionType = { View: 0, - Click: 1 -} + Click: 1, +}; const ATTAuthStatus = { NotDetermined: 0, Restricted: 1, Denied: 2, - Authorized: 3 -} + Authorized: 3, +}; // ******** Main API ******** const upload = () => { - NativeModules.MParticle.upload() -} + NativeModules.MParticle.upload(); +}; -const setUploadInterval = (uploadInterval) => { - NativeModules.MParticle.setUploadInterval(uploadInterval) -} +const setUploadInterval = uploadInterval => { + NativeModules.MParticle.setUploadInterval(uploadInterval); +}; const logEvent = (eventName, type = EventType.Other, attributes = null) => { - NativeModules.MParticle.logEvent(eventName, type, attributes) -} - -const logMPEvent = (event) => { - NativeModules.MParticle.logMPEvent(event) -} - -const logCommerceEvent = (commerceEvent) => { - NativeModules.MParticle.logCommerceEvent(commerceEvent) -} - -const logScreenEvent = (screenName, attributes = null, shouldUploadEvent = true) => { - NativeModules.MParticle.logScreenEvent(screenName, attributes, shouldUploadEvent) -} + NativeModules.MParticle.logEvent(eventName, type, attributes); +}; + +const logMPEvent = event => { + NativeModules.MParticle.logMPEvent(event); +}; + +const logCommerceEvent = commerceEvent => { + NativeModules.MParticle.logCommerceEvent(commerceEvent); +}; + +const logScreenEvent = ( + screenName, + attributes = null, + shouldUploadEvent = true +) => { + NativeModules.MParticle.logScreenEvent( + screenName, + attributes, + shouldUploadEvent + ); +}; // Use ATTAuthStatus constants for status -const setATTStatus = (status) => { - NativeModules.MParticle.setATTStatus(status) -} +const setATTStatus = status => { + NativeModules.MParticle.setATTStatus(status); +}; const setATTStatusWithCustomTimestamp = (status, timestamp) => { - NativeModules.MParticle.setATTStatus(status, timestamp) -} + NativeModules.MParticle.setATTStatus(status, timestamp); +}; -const setOptOut = (optOut) => { - NativeModules.MParticle.setOptOut(optOut) -} +const setOptOut = optOut => { + NativeModules.MParticle.setOptOut(optOut); +}; -const getOptOut = (completion) => { - NativeModules.MParticle.getOptOut(completion) -} +const getOptOut = completion => { + NativeModules.MParticle.getOptOut(completion); +}; const addGDPRConsentState = (newConsentState, purpose) => { - NativeModules.MParticle.addGDPRConsentState(newConsentState, purpose) -} + NativeModules.MParticle.addGDPRConsentState(newConsentState, purpose); +}; -const removeGDPRConsentStateWithPurpose = (purpose) => { - NativeModules.MParticle.removeGDPRConsentStateWithPurpose(purpose) -} +const removeGDPRConsentStateWithPurpose = purpose => { + NativeModules.MParticle.removeGDPRConsentStateWithPurpose(purpose); +}; -const setCCPAConsentState = (newConsentState) => { - NativeModules.MParticle.setCCPAConsentState(newConsentState) -} +const setCCPAConsentState = newConsentState => { + NativeModules.MParticle.setCCPAConsentState(newConsentState); +}; const removeCCPAConsentState = () => { - NativeModules.MParticle.removeCCPAConsentState() -} + NativeModules.MParticle.removeCCPAConsentState(); +}; const isKitActive = (kitId, completion) => { - NativeModules.MParticle.isKitActive(kitId, completion) -} + NativeModules.MParticle.isKitActive(kitId, completion); +}; -const getAttributions = (completion) => { - NativeModules.MParticle.getAttributions(completion) -} +const getAttributions = completion => { + NativeModules.MParticle.getAttributions(completion); +}; const logPushRegistration = (registrationField1, registrationField2) => { - NativeModules.MParticle.logPushRegistration(registrationField1, registrationField2) -} + NativeModules.MParticle.logPushRegistration( + registrationField1, + registrationField2 + ); +}; -const getSession = (completion) => { - NativeModules.MParticle.getSession(completion) -} +const getSession = completion => { + NativeModules.MParticle.getSession(completion); +}; const setLocation = (latitude, longitude) => { - NativeModules.MParticle.setLocation(latitude, longitude) -} + NativeModules.MParticle.setLocation(latitude, longitude); +}; // ******** Identity ******** class User { - constructor (userId) { - this.userId = userId + constructor(userId) { + this.userId = userId; } - getMpid () { - return this.userId + getMpid() { + return this.userId; } - setUserAttribute (key, value) { + setUserAttribute(key, value) { if (value && value.constructor === Array) { - NativeModules.MParticle.setUserAttributeArray(this.userId, key, value) + NativeModules.MParticle.setUserAttributeArray(this.userId, key, value); } else { - NativeModules.MParticle.setUserAttribute(this.userId, key, value) + NativeModules.MParticle.setUserAttribute(this.userId, key, value); } } - setUserAttributeArray (key, value) { - NativeModules.MParticle.setUserAttributeArray(this.userId, key, value) + setUserAttributeArray(key, value) { + NativeModules.MParticle.setUserAttributeArray(this.userId, key, value); } - getUserAttributes (completion) { - NativeModules.MParticle.getUserAttributes(this.userId, (error, userAttributes) => { - if (error) { - console.log(error.stack) + getUserAttributes(completion) { + NativeModules.MParticle.getUserAttributes( + this.userId, + (error, userAttributes) => { + if (error) { + console.log(error.stack); + } + completion(userAttributes); } - completion(userAttributes) - }) + ); } - setUserTag (value) { - NativeModules.MParticle.setUserTag(this.userId, value) + setUserTag(value) { + NativeModules.MParticle.setUserTag(this.userId, value); } - incrementUserAttribute (key, value) { - NativeModules.MParticle.incrementUserAttribute(this.userId, key, value) + incrementUserAttribute(key, value) { + NativeModules.MParticle.incrementUserAttribute(this.userId, key, value); } - removeUserAttribute (key) { - NativeModules.MParticle.removeUserAttribute(this.userId, key) + removeUserAttribute(key) { + NativeModules.MParticle.removeUserAttribute(this.userId, key); } - getUserIdentities (completion) { - NativeModules.MParticle.getUserIdentities(this.userId, (error, userIdentities) => { - if (error) { - console.log(error.stack) + getUserIdentities(completion) { + NativeModules.MParticle.getUserIdentities( + this.userId, + (error, userIdentities) => { + if (error) { + console.log(error.stack); + } + completion(userIdentities); } - completion(userIdentities) - }) + ); } - getFirstSeen (completion) { - NativeModules.MParticle.getFirstSeen(this.userId, completion) + getFirstSeen(completion) { + NativeModules.MParticle.getFirstSeen(this.userId, completion); } - getLastSeen (completion) { - NativeModules.MParticle.getLastSeen(this.userId, completion) + getLastSeen(completion) { + NativeModules.MParticle.getLastSeen(this.userId, completion); } } class IdentityRequest { - - setEmail (email) { - this[UserIdentityType.Email] = email - return this + setEmail(email) { + this[UserIdentityType.Email] = email; + return this; } - setCustomerID (customerId) { - this[UserIdentityType.CustomerId] = customerId - return this + setCustomerID(customerId) { + this[UserIdentityType.CustomerId] = customerId; + return this; } - setUserIdentity (userIdentity, identityType) { - this[identityType] = userIdentity - return this + setUserIdentity(userIdentity, identityType) { + this[identityType] = userIdentity; + return this; } - setOnUserAlias (onUserAlias) { - console.log("Warning: deprecated method 'setUserAlias(onUserAlias)', will be removed in future releases") + setOnUserAlias(_onUserAlias) { + console.log( + "Warning: deprecated method 'setUserAlias(onUserAlias)', will be removed in future releases" + ); } } class Identity { - - static getCurrentUser (completion) { + static getCurrentUser(completion) { NativeModules.MParticle.getCurrentUserWithCompletion((error, userId) => { if (error) { - console.log(error.stack) + console.log(error.stack); } - var currentUser = new User(userId) - completion(currentUser) - }) - } - - static identify (IdentityRequest, completion) { - NativeModules.MParticle.identify(IdentityRequest, (error, userId, previousUserId) => { - if (error == null || error === undefined) { - completion(error, userId, previousUserId) - } else { - var parsedError = new MParticleError(error) - completion(parsedError, userId, previousUserId) + var currentUser = new User(userId); + completion(currentUser); + }); + } + + static identify(IdentityRequest, completion) { + NativeModules.MParticle.identify( + IdentityRequest, + (error, userId, previousUserId) => { + if (error == null || error === undefined) { + completion(error, userId, previousUserId); + } else { + var parsedError = new MParticleError(error); + completion(parsedError, userId, previousUserId); + } } - }) - } - - static login (IdentityRequest, completion) { - NativeModules.MParticle.login(IdentityRequest, (error, userId, previousUserId) => { - if (error == null || error === undefined) { - completion(error, userId, previousUserId) - } else { - var parsedError = new MParticleError(error) - completion(parsedError, userId, previousUserId) + ); + } + + static login(IdentityRequest, completion) { + NativeModules.MParticle.login( + IdentityRequest, + (error, userId, previousUserId) => { + if (error == null || error === undefined) { + completion(error, userId, previousUserId); + } else { + var parsedError = new MParticleError(error); + completion(parsedError, userId, previousUserId); + } } - }) - } - - static logout (IdentityRequest, completion) { - NativeModules.MParticle.logout(IdentityRequest, (error, userId, previousUserId) => { - if (error == null || error === undefined) { - completion(error, userId, previousUserId) - } else { - var parsedError = new MParticleError(error) - completion(parsedError, userId, previousUserId) + ); + } + + static logout(IdentityRequest, completion) { + NativeModules.MParticle.logout( + IdentityRequest, + (error, userId, previousUserId) => { + if (error == null || error === undefined) { + completion(error, userId, previousUserId); + } else { + var parsedError = new MParticleError(error); + completion(parsedError, userId, previousUserId); + } } - }) - } - - static modify (IdentityRequest, completion) { - NativeModules.MParticle.modify(IdentityRequest, (error, userId, previousUserId) => { - if (error == null || error === undefined) { - completion(error, userId, previousUserId) - } else { - var parsedError = new MParticleError(error) - completion(parsedError, userId, previousUserId) + ); + } + + static modify(IdentityRequest, completion) { + NativeModules.MParticle.modify( + IdentityRequest, + (error, userId, previousUserId) => { + if (error == null || error === undefined) { + completion(error, userId, previousUserId); + } else { + var parsedError = new MParticleError(error); + completion(parsedError, userId, previousUserId); + } } - }) + ); } - static aliasUsers (AliasRequest, completion) { - NativeModules.MParticle.aliasUsers(AliasRequest, completion) + static aliasUsers(AliasRequest, completion) { + NativeModules.MParticle.aliasUsers(AliasRequest, completion); } - } // ******** Commerce ******** class Impression { - constructor (impressionListName, products) { - this.impressionListName = impressionListName - this.products = products + constructor(impressionListName, products) { + this.impressionListName = impressionListName; + this.products = products; } } class Promotion { - constructor (id, name, creative, position) { - this.id = id - this.name = name - this.creative = creative - this.position = position + constructor(id, name, creative, position) { + this.id = id; + this.name = name; + this.creative = creative; + this.position = position; } } class AliasRequest { - - sourceMpid (mpid) { - this.sourceMpid = mpid - return this + sourceMpid(mpid) { + this.sourceMpid = mpid; + return this; } - destinationMpid (mpid) { - this.destinationMpid = mpid - return this + destinationMpid(mpid) { + this.destinationMpid = mpid; + return this; } - endTime (mpid) { - this.endTime = mpid - return this + endTime(mpid) { + this.endTime = mpid; + return this; } - startTime (mpid) { - this.startTime = mpid - return this + startTime(mpid) { + this.startTime = mpid; + return this; } } class TransactionAttributes { - constructor (transactionId) { - this.transactionId = transactionId + constructor(transactionId) { + this.transactionId = transactionId; } - setAffiliation (affiliation) { - this.affiliation = affiliation - return this + setAffiliation(affiliation) { + this.affiliation = affiliation; + return this; } - setRevenue (revenue) { - this.revenue = typeof revenue === 'string' ? parseFloat(revenue) : revenue - return this + setRevenue(revenue) { + this.revenue = typeof revenue === 'string' ? parseFloat(revenue) : revenue; + return this; } - setShipping (shipping) { - this.shipping = typeof shipping === 'string' ? parseFloat(shipping) : shipping - return this + setShipping(shipping) { + this.shipping = + typeof shipping === 'string' ? parseFloat(shipping) : shipping; + return this; } - setTax (tax) { - this.tax = typeof tax === 'string' ? parseFloat(tax) : tax - return this + setTax(tax) { + this.tax = typeof tax === 'string' ? parseFloat(tax) : tax; + return this; } - setCouponCode (couponCode) { - this.couponCode = couponCode - return this + setCouponCode(couponCode) { + this.couponCode = couponCode; + return this; } } class Product { - constructor (name, sku, price, quantity = 1) { - this.name = name - this.sku = sku - this.price = price - this.quantity = quantity + constructor(name, sku, price, quantity = 1) { + this.name = name; + this.sku = sku; + this.price = price; + this.quantity = quantity; } - setBrand (brand) { - this.brand = brand - return this + setBrand(brand) { + this.brand = brand; + return this; } - setCouponCode (couponCode) { - this.couponCode = couponCode - return this + setCouponCode(couponCode) { + this.couponCode = couponCode; + return this; } - setPosition (position) { - this.position = position - return this + setPosition(position) { + this.position = position; + return this; } - setCategory (category) { - this.category = category - return this + setCategory(category) { + this.category = category; + return this; } - setVariant (variant) { - this.variant = variant - return this + setVariant(variant) { + this.variant = variant; + return this; } - setCustomAttributes (customAttributes) { - this.customAttributes = customAttributes - return this + setCustomAttributes(customAttributes) { + this.customAttributes = customAttributes; + return this; } } class GDPRConsent { - - constructor (consented, doc, timestamp, location, hardwareId) { - this.consented = consented - this.document = doc - this.timestamp = timestamp - this.location = location - this.hardwareId = hardwareId + constructor(consented, doc, timestamp, location, hardwareId) { + this.consented = consented; + this.document = doc; + this.timestamp = timestamp; + this.location = location; + this.hardwareId = hardwareId; } - setConsented (consented) { - this.consented = consented - return this + setConsented(consented) { + this.consented = consented; + return this; } - setDocument (doc) { - this.document = doc - return this + setDocument(doc) { + this.document = doc; + return this; } - setTimestamp (timestamp) { - this.timestamp = timestamp - return this + setTimestamp(timestamp) { + this.timestamp = timestamp; + return this; } - setLocation (location) { - this.location = location - return this + setLocation(location) { + this.location = location; + return this; } - setHardwareId (hardwareId) { - this.hardwareId = hardwareId - return this + setHardwareId(hardwareId) { + this.hardwareId = hardwareId; + return this; } } class CCPAConsent { - - constructor (consented, doc, timestamp, location, hardwareId) { - this.consented = consented - this.document = doc - this.timestamp = timestamp - this.location = location - this.hardwareId = hardwareId + constructor(consented, doc, timestamp, location, hardwareId) { + this.consented = consented; + this.document = doc; + this.timestamp = timestamp; + this.location = location; + this.hardwareId = hardwareId; } - setConsented (consented) { - this.consented = consented - return this + setConsented(consented) { + this.consented = consented; + return this; } - setDocument (doc) { - this.document = doc - return this + setDocument(doc) { + this.document = doc; + return this; } - setTimestamp (timestamp) { - this.timestamp = timestamp - return this + setTimestamp(timestamp) { + this.timestamp = timestamp; + return this; } - setLocation (location) { - this.location = location - return this + setLocation(location) { + this.location = location; + return this; } - setHardwareId (hardwareId) { - this.hardwareId = hardwareId - return this + setHardwareId(hardwareId) { + this.hardwareId = hardwareId; + return this; } } class CommerceEvent { - - static createProductActionEvent (productActionType, products, transactionAttributes = {}) { + static createProductActionEvent( + productActionType, + products, + transactionAttributes = {} + ) { return new CommerceEvent() - .setProductActionType(productActionType) - .setProducts(products) - .setTransactionAttributes(transactionAttributes) + .setProductActionType(productActionType) + .setProducts(products) + .setTransactionAttributes(transactionAttributes); } - static createPromotionEvent (promotionActionType, promotions) { + static createPromotionEvent(promotionActionType, promotions) { return new CommerceEvent() - .setPromotionActionType(promotionActionType) - .setPromotions(promotions) + .setPromotionActionType(promotionActionType) + .setPromotions(promotions); } - static createImpressionEvent (impressions) { - return new CommerceEvent() - .setImpressions(impressions) + static createImpressionEvent(impressions) { + return new CommerceEvent().setImpressions(impressions); } - setTransactionAttributes (transactionAttributes) { - this.transactionAttributes = transactionAttributes - return this + setTransactionAttributes(transactionAttributes) { + this.transactionAttributes = transactionAttributes; + return this; } - setProductActionType (productActionType) { - this.productActionType = productActionType - return this + setProductActionType(productActionType) { + this.productActionType = productActionType; + return this; } - setPromotionActionType (promotionActionType) { - this.promotionActionType = promotionActionType - return this + setPromotionActionType(promotionActionType) { + this.promotionActionType = promotionActionType; + return this; } - setProducts (products) { - this.products = products - return this + setProducts(products) { + this.products = products; + return this; } - setPromotions (promotions) { - this.promotions = promotions - return this + setPromotions(promotions) { + this.promotions = promotions; + return this; } - setImpressions (impressions) { - this.impressions = impressions - return this + setImpressions(impressions) { + this.impressions = impressions; + return this; } - setScreenName (screenName) { - this.screenName = screenName - return this + setScreenName(screenName) { + this.screenName = screenName; + return this; } - setCurrency (currency) { - this.currency = currency - return this + setCurrency(currency) { + this.currency = currency; + return this; } - setCustomAttributes (customAttributes) { - this.customAttributes = customAttributes - return this + setCustomAttributes(customAttributes) { + this.customAttributes = customAttributes; + return this; } - setCheckoutOptions (checkoutOptions) { - this.checkoutOptions = checkoutOptions - return this + setCheckoutOptions(checkoutOptions) { + this.checkoutOptions = checkoutOptions; + return this; } - setProductActionListName (productActionListName) { - this.productActionListName = productActionListName - return this + setProductActionListName(productActionListName) { + this.productActionListName = productActionListName; + return this; } - setProductActionListSource (productActionListSource) { - this.productActionListSource = productActionListSource - return this + setProductActionListSource(productActionListSource) { + this.productActionListSource = productActionListSource; + return this; } - setCheckoutStep (checkoutStep) { - this.checkoutStep = checkoutStep - return this + setCheckoutStep(checkoutStep) { + this.checkoutStep = checkoutStep; + return this; } - setNonInteractive (nonInteractive) { - this.nonInteractive = nonInteractive - return this + setNonInteractive(nonInteractive) { + this.nonInteractive = nonInteractive; + return this; } - setShouldUploadEvent (shouldUploadEvent) { - this.shouldUploadEvent = shouldUploadEvent - return this + setShouldUploadEvent(shouldUploadEvent) { + this.shouldUploadEvent = shouldUploadEvent; + return this; } } class Event { - - setCategory (category) { - this.category = category - return this + setCategory(category) { + this.category = category; + return this; } - setDuration (duration) { - this.duration = duration - return this + setDuration(duration) { + this.duration = duration; + return this; } - setEndTime (endTime) { - this.endTime = endTime - return this + setEndTime(endTime) { + this.endTime = endTime; + return this; } - setInfo (info) { - this.info = info - return this + setInfo(info) { + this.info = info; + return this; } - setName (name) { - this.name = name - return this + setName(name) { + this.name = name; + return this; } - setStartTime (startTime) { - this.startTime = startTime - return this + setStartTime(startTime) { + this.startTime = startTime; + return this; } - setType (type) { - this.type = type - return this + setType(type) { + this.type = type; + return this; } - setShouldUploadEvent (shouldUploadEvent) { - this.shouldUploadEvent = shouldUploadEvent - return this + setShouldUploadEvent(shouldUploadEvent) { + this.shouldUploadEvent = shouldUploadEvent; + return this; } - setCustomFlags (customFlags) { - this.customFlags = customFlags - return this + setCustomFlags(customFlags) { + this.customFlags = customFlags; + return this; } } class MParticleError { - constructor (errorResponse) { - this.httpCode = errorResponse.httpCode + constructor(errorResponse) { + this.httpCode = errorResponse.httpCode; - this.responseCode = errorResponse.responseCode + this.responseCode = errorResponse.responseCode; - this.message = errorResponse.message + this.message = errorResponse.message; - this.mpid = errorResponse.mpid + this.mpid = errorResponse.mpid; - this.errors = errorResponse.errors + this.errors = errorResponse.errors; } } // ******** Exports ******** const MParticle = { - - EventType, // Constants + EventType, // Constants UserIdentityType, UserAttributeType, ProductActionType, PromotionActionType, ATTAuthStatus, - Product, // Classes + Product, // Classes Impression, Promotion, CommerceEvent, @@ -672,8 +700,11 @@ const MParticle = { MParticleError, GDPRConsent, CCPAConsent, + Rokt, + CacheConfig, + RoktLayoutView, - upload, // Methods + upload, // Methods setUploadInterval, logEvent, logMPEvent, @@ -691,7 +722,7 @@ const MParticle = { getAttributions, logPushRegistration, getSession, - setLocation -} + setLocation, +}; -export default MParticle +export default MParticle; diff --git a/js/rokt/RoktNativeLayoutComponent.ts b/js/rokt/RoktNativeLayoutComponent.ts new file mode 100644 index 0000000..740c29e --- /dev/null +++ b/js/rokt/RoktNativeLayoutComponent.ts @@ -0,0 +1,29 @@ +import type { HostComponent, ViewProps } from 'react-native'; +import type { DirectEventHandler } from 'react-native/Libraries/Types/CodegenTypes'; +import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent'; + +// Event types - these define the data structure passed from native to JS +type HeightChangedEvent = { + height: string; +}; + +type MarginChangedEvent = { + marginTop: string; + marginRight: string; + marginLeft: string; + marginBottom: string; +}; + +// Native component props - these are the props the native component expects +export interface NativeProps extends ViewProps { + // Placeholder name to be passed to the native component + placeholderName: string; + + // Custom events + onLayoutHeightChanged?: DirectEventHandler; + onLayoutMarginChanged?: DirectEventHandler; +} + +export default codegenNativeComponent( + 'RoktNativeLayout' +) as HostComponent; diff --git a/js/rokt/rokt-layout-view.android.tsx b/js/rokt/rokt-layout-view.android.tsx new file mode 100644 index 0000000..27dc7c9 --- /dev/null +++ b/js/rokt/rokt-layout-view.android.tsx @@ -0,0 +1,133 @@ +import { StyleSheet } from 'react-native'; +import React, { Component } from 'react'; +import RoktNativeLayoutComponent from './RoktNativeLayoutComponent'; + +/** + * PUBLIC API: Props that users of RoktLayoutView can set + */ +export interface RoktLayoutViewProps { + // Placeholder name to use + placeholderName: string; +} + +/** + * INTERNAL: State managed by the component to handle native events + */ +export interface RoktLayoutViewState { + height: number; + placeholderName: string; + marginTop: number; + marginRight: number; + marginLeft: number; + marginBottom: number; +} + +/** + * Native event types for type safety + */ +interface HeightChangedEvent { + nativeEvent: { + height: string; + }; +} + +interface MarginChangedEvent { + nativeEvent: { + marginTop?: string; + marginLeft?: string; + marginRight?: string; + marginBottom?: string; + }; +} + +const styles = StyleSheet.create({ + widget: { + flex: 1, + backgroundColor: 'transparent', + }, +}); + +/** + * RoktEmbeddedView is a wrapper component for the native RoktNativeWidget. + * It handles the native events internally and provides a simpler API for React Native apps. + * + * This component only exposes the placeholderName prop to users, hiding all the internal complexity. + */ +export class RoktLayoutView extends Component< + RoktLayoutViewProps, + RoktLayoutViewState +> { + constructor(props: RoktLayoutViewProps) { + super(props); + this.state = { + height: 0, + placeholderName: this.props.placeholderName, + marginTop: 0, + marginRight: 0, + marginLeft: 0, + marginBottom: 0, + }; + } + + /** + * Handles the height changed event from the native component + * This is an internal implementation detail not exposed to users + */ + private handleHeightChanged = (event: HeightChangedEvent) => { + if (event && event.nativeEvent && event.nativeEvent.height) { + this.setState({ height: parseInt(event.nativeEvent.height) }); + } + }; + + /** + * Handles the margin changed event from the native component + * This is an internal implementation detail not exposed to users + */ + private handleMarginChanged = (event: MarginChangedEvent) => { + if (event && event.nativeEvent) { + const { marginTop, marginLeft, marginRight, marginBottom } = + event.nativeEvent; + this.setState({ + marginTop: parseInt(marginTop || '0'), + marginLeft: parseInt(marginLeft || '0'), + marginRight: parseInt(marginRight || '0'), + marginBottom: parseInt(marginBottom || '0'), + }); + } + }; + + override render() { + try { + // Get the placeholderName from props + const { placeholderName } = this.props; + + // Return the native component with the props + // Cast to React.ComponentType to make it compatible with JSX + const RoktComponent = + // eslint-disable-next-line @typescript-eslint/no-explicit-any + RoktNativeLayoutComponent as React.ComponentType; + return ( + + ); + } catch (error) { + console.error('[ROKT] Error rendering RoktEmbeddedView:', error); + return null; + } + } +} + +export default RoktLayoutView; diff --git a/js/rokt/rokt-layout-view.ios.tsx b/js/rokt/rokt-layout-view.ios.tsx new file mode 100644 index 0000000..6afc31a --- /dev/null +++ b/js/rokt/rokt-layout-view.ios.tsx @@ -0,0 +1,155 @@ +import { + requireNativeComponent, + StyleSheet, + NativeEventEmitter, + NativeModules, + HostComponent, + ViewProps, + NativeModule, + UIManager, +} from 'react-native'; +import React, { Component } from 'react'; + +const RoktEventManager = NativeModules.RoktEventManager as NativeModule; + +export interface HeightChangedEvent extends Event { + height: string; +} + +export interface MarginChangedEvent extends Event { + marginTop: string; + marginRight: string; + marginLeft: string; + marginBottom: string; +} + +export interface WidgetChangeEvent { + selectedPlacement: string; + height: string; +} + +export interface RoktLayoutViewProps { + placeholderName: string; +} + +export interface RoktLayoutViewState { + height: number; + placeholderName: string; + marginTop: number; + marginRight: number; + marginLeft: number; + marginBottom: number; +} + +// Define the native component props interface +interface RoktNativeLayoutProps extends ViewProps { + placeholderName?: string; + onLayoutHeightChanged?: (event: HeightChangedEvent) => void; + onLayoutMarginChanged?: (event: MarginChangedEvent) => void; +} + +// Architecture detection - Updated for RN 0.80+ compatibility +// In RN 0.80+, check for Fabric renderer using a more reliable method +const isNewArchitecture = (() => { + // Check if Fabric renderer is enabled by looking at UIManager properties + // This is a safer approach that works in RN 0.80+ + const hasFabricUIManager = + UIManager && + typeof UIManager.hasViewManagerConfig === 'function' && + UIManager.hasViewManagerConfig('RCTView'); + + if (hasFabricUIManager) { + return true; + } + + // Fallback: check TurboModule presence (less reliable in 0.80+) + const turboModuleCheck = + (NativeModules as { RNRoktWidget?: unknown }).RNRoktWidget == null; + return turboModuleCheck; +})(); + +// Conditional component loading based on architecture +let WidgetNativeComponent: HostComponent; + +if (isNewArchitecture) { + try { + // Try to import the new architecture component + // eslint-disable-next-line @typescript-eslint/no-var-requires + const NativeComponent = require('./RoktNativeLayoutComponent') as { + default: HostComponent; + }; + WidgetNativeComponent = NativeComponent.default; + } catch (error) { + WidgetNativeComponent = requireNativeComponent('RoktNativeLayout'); + } +} else { + WidgetNativeComponent = requireNativeComponent('RoktNativeLayout'); +} + +const eventManagerEmitter = new NativeEventEmitter(RoktEventManager); + +export class RoktLayoutView extends Component< + RoktLayoutViewProps, + RoktLayoutViewState +> { + subscription = eventManagerEmitter.addListener( + 'LayoutHeightChanges', + (widgetChanges: WidgetChangeEvent) => { + if (widgetChanges.selectedPlacement == this.state.placeholderName) { + this.setState({ height: parseInt(widgetChanges.height) }); + } + } + ); + + constructor(props: RoktLayoutViewProps) { + super(props); + + this.state = { + height: 0, + placeholderName: this.props.placeholderName, + marginTop: 0, + marginRight: 0, + marginLeft: 0, + marginBottom: 0, + }; + } + + override render() { + // Cast to React.ComponentType to make it compatible with JSX + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const RoktComponent = WidgetNativeComponent as React.ComponentType; + return ( + { + if (event.height) { + this.setState({ height: parseInt(event.height) }); + } + }} + onLayoutMarginChanged={(event: MarginChangedEvent) => { + this.setState({ + marginTop: parseInt(event.marginTop || '0'), + marginRight: parseInt(event.marginRight || '0'), + marginLeft: parseInt(event.marginLeft || '0'), + marginBottom: parseInt(event.marginBottom || '0'), + }); + }} + /> + ); + } + + override componentWillUnmount() { + this.subscription.remove(); + } +} + +const styles = StyleSheet.create({ + widget: { + flex: 1, + backgroundColor: 'transparent', + overflow: 'hidden', + }, +}); + +export default RoktLayoutView; diff --git a/js/rokt/rokt-layout-view.tsx b/js/rokt/rokt-layout-view.tsx new file mode 100644 index 0000000..da3c6cf --- /dev/null +++ b/js/rokt/rokt-layout-view.tsx @@ -0,0 +1,15 @@ +import { Platform } from 'react-native'; + +// Import both implementations +import { RoktLayoutView as RoktLayoutViewIOS } from './rokt-layout-view.ios'; +import { RoktLayoutView as RoktLayoutViewAndroid } from './rokt-layout-view.android'; + +// Export types +export type { RoktLayoutViewProps } from './rokt-layout-view.ios'; + +// Export the appropriate component based on platform +export const RoktLayoutView = + Platform.OS === 'ios' ? RoktLayoutViewIOS : RoktLayoutViewAndroid; + +// Default export +export default RoktLayoutView; diff --git a/js/rokt/rokt.ts b/js/rokt/rokt.ts new file mode 100644 index 0000000..74ca574 --- /dev/null +++ b/js/rokt/rokt.ts @@ -0,0 +1,72 @@ +import { NativeModules } from 'react-native'; + +export abstract class Rokt { + /** + * Selects placements with a [identifier], [attributes], optional [placeholders], optional [roktConfig], and optional [fontFilePathMap]. + * + * @param {string} identifier - The page identifier for the placement. + * @param {Record} attributes - Attributes to be associated with the placement. + * @param {Record} [placeholders] - Optional placeholders for dynamic content. + * @param {IRoktConfig} [roktConfig] - Optional configuration settings for Rokt. + * @param {Record} [fontFilesMap] - Optional mapping of font files. + * @returns {Promise} A promise that resolves when the placement request is sent. + */ + static async selectPlacements( + identifier: string, + attributes: Record, + placeholders?: Record, + roktConfig?: IRoktConfig, + fontFilesMap?: Record + ): Promise { + NativeModules.MPRokt.selectPlacements( + identifier, + attributes, + placeholders, + roktConfig, + fontFilesMap + ); + } + + static createRoktConfig(colorMode?: ColorMode, cacheConfig?: CacheConfig) { + return new RoktConfig(colorMode ?? 'system', cacheConfig); + } + + static createCacheConfig( + cacheDurationInSeconds: number, + cacheAttributes: Record + ) { + return new CacheConfig(cacheDurationInSeconds, cacheAttributes); + } +} + +// Define the interface that matches the native module for cleaner code +export interface IRoktConfig { + readonly colorMode?: ColorMode; + readonly cacheConfig?: CacheConfig; +} + +/** + * Cache configuration for Rokt SDK + */ +export class CacheConfig { + /** + * @param cacheDurationInSeconds - The duration in seconds for which the Rokt SDK should cache the experience. Default is 90 minutes + * @param cacheAttributes - optional attributes to be used as cache key. If null, all the attributes will be used as the cache key + */ + constructor( + public readonly cacheDurationInSeconds?: number, + public readonly cacheAttributes?: Record + ) {} +} + +class RoktConfig implements IRoktConfig { + public readonly colorMode: ColorMode; + public readonly cacheConfig?: CacheConfig; + + constructor(colorMode: ColorMode, cacheConfig?: CacheConfig) { + this.colorMode = colorMode; + this.cacheConfig = cacheConfig; + } +} + +export type ColorMode = 'light' | 'dark' | 'system'; diff --git a/metro.config.js b/metro.config.js new file mode 100644 index 0000000..d792153 --- /dev/null +++ b/metro.config.js @@ -0,0 +1,17 @@ +/** + * Metro configuration for React Native + * https://github.com/facebook/react-native + * + * @format + */ + +module.exports = { + transformer: { + getTransformOptions: async () => ({ + transform: { + experimentalImportSupport: false, + inlineRequires: true + } + }) + } +} diff --git a/package.json b/package.json index 14592ec..e0a0365 100644 --- a/package.json +++ b/package.json @@ -6,14 +6,16 @@ "repository": "mParticle/react-native-mparticle", "version": "2.7.13", "main": "js/index.js", + "types": "js/index.d.ts", "scripts": { - "test": "./node_modules/standard/bin/cmd.js", - "fix": "./node_modules/standard/bin/cmd.js --fix" - }, - "standard": { - "ignore": [ - "/sample" - ] + "build": "tsc", + "clean": "rm -rf lib", + "prepare": "yarn clean && yarn build", + "dev:pack": "yarn build && yarn pack --filename react-native-mparticle-latest.tgz", + "dev:link": "./dev-link.sh", + "lint": "eslint js/**/*.{js,ts,tsx} --fix", + "format": "prettier --write js/**/*.{js,ts,tsx}", + "test": "npm run lint" }, "dependencies": {}, "peerDependencies": { @@ -21,6 +23,25 @@ "react-native": ">= 0.45.0" }, "devDependencies": { - "standard": "^8.6.0" + "@typescript-eslint/eslint-plugin": "^5.62.0", + "@typescript-eslint/parser": "^5.62.0", + "eslint": "^8.45.0", + "eslint-config-prettier": "^8.10.0", + "eslint-plugin-prettier": "^4.2.1", + "prettier": "^2.8.8", + "@types/react": "^18.0.0", + "@types/react-native": "^0.70.0", + "typescript": "5.0.4" + }, + "codegenConfig": { + "name": "RoktLayoutView", + "type": "all", + "jsSrcsDir": "lib/", + "android": { + "javaPackageName": "com.mparticle.react.rokt" + }, + "ios": { + "swiftModuleName": "RoktLayoutView" + } } } diff --git a/react-native-mparticle.podspec b/react-native-mparticle.podspec index db5dd32..8165b7c 100644 --- a/react-native-mparticle.podspec +++ b/react-native-mparticle.podspec @@ -17,7 +17,7 @@ Pod::Spec.new do |s| s.platforms = { :ios => ios_platform, :tvos => "9.2" } s.source = { :git => "https://github.com/mParticle/react-native-mparticle.git", :tag => "#{s.version}" } - s.source_files = "ios/**/*.{h,m}" + s.source_files = "ios/**/*.{h,m,mm,swift}" if defined?(install_modules_dependencies()) != nil install_modules_dependencies(s); diff --git a/sample/.babelrc b/sample/.babelrc deleted file mode 100644 index 8df53fe..0000000 --- a/sample/.babelrc +++ /dev/null @@ -1,3 +0,0 @@ -{ -"presets": ["react-native"] -} \ No newline at end of file diff --git a/sample/.buckconfig b/sample/.buckconfig deleted file mode 100644 index 2ce91fb..0000000 --- a/sample/.buckconfig +++ /dev/null @@ -1,6 +0,0 @@ - -[android] - target = Google Inc.:Google APIs:26 - -[maven_repositories] - central = https://repo1.maven.org/maven2 diff --git a/sample/.eslintrc.js b/sample/.eslintrc.js new file mode 100644 index 0000000..187894b --- /dev/null +++ b/sample/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: '@react-native', +}; diff --git a/sample/.gitignore b/sample/.gitignore index fc13f16..7a015a8 100644 --- a/sample/.gitignore +++ b/sample/.gitignore @@ -21,6 +21,7 @@ DerivedData *.ipa *.xcuserstate project.xcworkspace +.xcode.env.local # Android/IntelliJ # @@ -29,6 +30,8 @@ build/ .gradle local.properties *.iml +android/app/build/ +android/app/.cxx/ # node.js # @@ -39,7 +42,6 @@ npm-debug.log buck-out/ \.buckd/ android/app/libs -*.keystore # fastlane # diff --git a/sample/.prettierrc.js b/sample/.prettierrc.js new file mode 100644 index 0000000..2b54074 --- /dev/null +++ b/sample/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + arrowParens: 'avoid', + bracketSameLine: true, + bracketSpacing: false, + singleQuote: true, + trailingComma: 'all', +}; diff --git a/sample/Gemfile b/sample/Gemfile new file mode 100644 index 0000000..03278dd --- /dev/null +++ b/sample/Gemfile @@ -0,0 +1,10 @@ +source 'https://rubygems.org' + +# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version +ruby ">= 2.6.10" + +# Exclude problematic versions of cocoapods and activesupport that causes build failures. +gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' +gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' +gem 'xcodeproj', '< 1.26.0' +gem 'concurrent-ruby', '< 1.3.4' diff --git a/sample/README.md b/sample/README.md new file mode 100644 index 0000000..8fb273c --- /dev/null +++ b/sample/README.md @@ -0,0 +1,144 @@ +# mParticle React Native Sample App + +This sample app demonstrates how to integrate and use the mParticle React Native SDK. + +## Prerequisites + +- Node.js (>= 18) +- Yarn package manager +- React Native development environment set up +- For iOS: Xcode and iOS Simulator +- For Android: Android Studio and Android SDK + +## Setup Instructions + +### 1. Configure mParticle Keys + +Before running the sample app, you need to replace the placeholder mParticle keys with your actual mParticle app credentials. + +#### iOS Configuration + +Edit `ios/MParticleSample/AppDelegate.mm` and replace the placeholder keys: + +```objc +MParticleOptions *mParticleOptions = [MParticleOptions optionsWithKey:@"YOUR_IOS_API_KEY" + secret:@"YOUR_IOS_SECRET_KEY"]; +``` + +#### Android Configuration + +Edit `android/app/src/main/java/com/mparticlesample/MainApplication.kt` and replace the placeholder keys: + +```kotlin +val options = MParticleOptions.builder(this) + .credentials("YOUR_ANDROID_API_KEY", "YOUR_ANDROID_SECRET_KEY") + .logLevel(MParticle.LogLevel.VERBOSE) + .identify(identityRequest.build()) + .build() +``` + +### 2. Build and Install the Package + +From the **root directory**, run the following commands: + +```bash +# Build the TypeScript source and create a package +yarn dev:pack + +# Install dependencies in the sample app +cd sample +yarn install +``` + +Alternatively, you can use the combined command from the root directory: + +```bash +# Build, pack, and install in sample directory in one command +yarn dev:link +``` + +### 3. Install iOS Dependencies (iOS only) + +```bash +cd sample/ios +pod install +``` + +## Running the Sample App + +### iOS + +From the **sample directory**: + +```bash +yarn ios +``` + +### Android + +From the **sample directory**: + +```bash +yarn android +``` + +## Development Workflow + +When making changes to the mParticle React Native SDK: + +1. Make your changes to the SDK source code +2. Rebuild and reinstall the package: + + ```bash + # From root directory + yarn dev:link + ``` + +3. Restart the sample app to see your changes + +## Troubleshooting + +### Common Issues + +1. **Metro bundler cache issues**: Clear the cache with: + + ```bash + cd sample + npx react-native start --reset-cache + ``` + +2. **iOS build issues**: Clean and rebuild: + + ```bash + cd sample/ios + xcodebuild clean + cd .. + yarn ios + ``` + +3. **Android build issues**: Clean and rebuild: + + ```bash + cd sample/android + ./gradlew clean + cd .. + yarn android + ``` + +4. **Package not found**: Make sure you've run `yarn dev:pack` or `yarn dev:link` from the root directory + +## Available Scripts + +From the sample directory: + +- `yarn start` - Start the Metro bundler +- `yarn ios` - Run on iOS simulator +- `yarn android` - Run on Android emulator +- `yarn lint` - Run ESLint +- `yarn test` - Run Jest tests + +## Additional Resources + +- [mParticle Documentation](https://docs.mparticle.com/) +- [React Native mParticle SDK Documentation](https://github.com/mParticle/react-native-mparticle) +- [React Native Documentation](https://reactnative.dev/) diff --git a/sample/__mocks__/react-native-mparticle.js b/sample/__mocks__/react-native-mparticle.js new file mode 100644 index 0000000..a721023 --- /dev/null +++ b/sample/__mocks__/react-native-mparticle.js @@ -0,0 +1,184 @@ +/* eslint-disable */ +/** + * Mock for react-native-mparticle + * This mock provides a simple API that mimics the essential functionality + */ + +// Mock classes +class User { + constructor(userId) { + this.userId = userId; + } + + getMpid() { + return this.userId; + } + + setUserAttribute() {} + getUserAttributes(callback) { + callback({ testAttribute: 'testValue' }); + } + setUserTag() {} + incrementUserAttribute() {} + removeUserAttribute() {} + getUserIdentities(callback) { + callback({ email: 'test@example.com' }); + } + getFirstSeen(callback) { + callback(Date.now() - 86400000); + } + getLastSeen(callback) { + callback(Date.now()); + } +} + +class IdentityRequest { + setEmail(email) { + this.email = email; + return this; + } + + setCustomerID(customerId) { + this.customerId = customerId; + return this; + } + + setUserIdentity(userIdentity, identityType) { + this[identityType] = userIdentity; + return this; + } +} + +class Identity { + static getCurrentUser(completion) { + var currentUser = new User('mockUserId123'); + completion(currentUser); + } + + static login(request, completion) { + completion(null, 'mockUserId123', 'mockPreviousUserId456'); + } + + static logout(request, completion) { + completion(null, 'mockUserId123'); + } + + static identify(request, completion) { + completion(null, 'mockUserId123', 'mockPreviousUserId456'); + } + + static modify(request, completion) { + completion(null, 'mockUserId123', 'mockPreviousUserId456'); + } + + static aliasUsers(request, completion) { + completion(true, null); + } +} + +class Product { + constructor(name, sku, price, quantity = 1) { + this.name = name; + this.sku = sku; + this.price = price; + this.quantity = quantity; + } +} + +class TransactionAttributes { + constructor(transactionId) { + this.transactionId = transactionId; + } +} + +class CommerceEvent { + static createProductActionEvent(productActionType, products, transactionAttributes) { + return new CommerceEvent(); + } +} + +class AliasRequest { + sourceMpid(mpid) { + this.sourceMpid = mpid; + return this; + } + + destinationMpid(mpid) { + this.destinationMpid = mpid; + return this; + } + + startTime(time) { + this.startTime = time; + return this; + } + + endTime(time) { + this.endTime = time; + return this; + } +} + +// Mock Rokt +const Rokt = { + selectPlacements: () => Promise.resolve() +}; + +// Constants +const EventType = { + Navigation: 1, + Location: 2, + Search: 3, + Transaction: 4, + UserContent: 5, + UserPreference: 6, + Social: 7, + Other: 8, + Media: 9 +}; + +const UserIdentityType = { + Email: 7, + CustomerId: 1, + Alias: 8 +}; + +const ProductActionType = { + AddToCart: 1, + RemoveFromCart: 2, + Checkout: 3, + Purchase: 7 +}; + +// Main mock object +const MParticle = { + // Classes + User, + IdentityRequest, + Identity, + Product, + TransactionAttributes, + CommerceEvent, + AliasRequest, + Rokt, + + // Constants + EventType, + UserIdentityType, + ProductActionType, + + // Methods + logEvent: () => {}, + logCommerceEvent: () => {}, + logPushRegistration: () => {}, + getSession: (callback) => callback({ sessionId: 'mockSessionId123' }), + setOptOut: () => {}, + getOptOut: (callback) => callback(false), + isKitActive: (kitId, callback) => callback(true), + getAttributions: (callback) => callback({ attributionResults: 'mock results' }), + upload: () => {}, + setUploadInterval: () => {}, + setLocation: () => {} +}; + +module.exports = MParticle; \ No newline at end of file diff --git a/sample/__tests__/index.ios.js b/sample/__tests__/index.ios.js deleted file mode 100644 index ba7c5b5..0000000 --- a/sample/__tests__/index.ios.js +++ /dev/null @@ -1,12 +0,0 @@ -import 'react-native'; -import React from 'react'; -import Index from '../index.ios.js'; - -// Note: test renderer must be required after react-native. -import renderer from 'react-test-renderer'; - -it('renders correctly', () => { - const tree = renderer.create( - - ); -}); diff --git a/sample/__tests__/index.android.js b/sample/__tests__/index.js similarity index 50% rename from sample/__tests__/index.android.js rename to sample/__tests__/index.js index b49b908..235014b 100644 --- a/sample/__tests__/index.android.js +++ b/sample/__tests__/index.js @@ -1,12 +1,21 @@ import 'react-native'; import React from 'react'; -import Index from '../index.android.js'; +import Index from '../index.js'; // Note: test renderer must be required after react-native. import renderer from 'react-test-renderer'; +// Use fake timers to avoid async issues +jest.useFakeTimers(); + it('renders correctly', () => { const tree = renderer.create( ); + + // Clean up any timers that might be running + jest.runOnlyPendingTimers(); + jest.clearAllTimers(); + + expect(tree.toJSON()).toBeTruthy(); }); diff --git a/sample/android/app/BUCK b/sample/android/app/BUCK deleted file mode 100644 index dec14f9..0000000 --- a/sample/android/app/BUCK +++ /dev/null @@ -1,66 +0,0 @@ -import re - -# To learn about Buck see [Docs](https://buckbuild.com/). -# To run your application with Buck: -# - install Buck -# - `npm start` - to start the packager -# - `cd android` -# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` -# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck -# - `buck install -r android/app` - compile, install and run application -# - -lib_deps = [] -for jarfile in glob(['libs/*.jar']): - name = 'jars__' + re.sub(r'^.*/([^/]+)\.jar$', r'\1', jarfile) - lib_deps.append(':' + name) - prebuilt_jar( - name = name, - binary_jar = jarfile, - ) - -for aarfile in glob(['libs/*.aar']): - name = 'aars__' + re.sub(r'^.*/([^/]+)\.aar$', r'\1', aarfile) - lib_deps.append(':' + name) - android_prebuilt_aar( - name = name, - aar = aarfile, - ) - -android_library( - name = 'all-libs', - exported_deps = lib_deps -) - -android_library( - name = 'app-code', - srcs = glob([ - 'src/main/java/**/*.java', - ]), - deps = [ - ':all-libs', - ':build_config', - ':res', - ], -) - -android_build_config( - name = 'build_config', - package = 'com.mparticlesample', -) - -android_resource( - name = 'res', - res = 'src/main/res', - package = 'com.mparticlesample', -) - -android_binary( - name = 'app', - package_type = 'debug', - manifest = 'src/main/AndroidManifest.xml', - keystore = '//android/keystores:debug', - deps = [ - ':app-code', - ], -) diff --git a/sample/android/app/build.gradle b/sample/android/app/build.gradle index acd905e..8bc69b6 100644 --- a/sample/android/app/build.gradle +++ b/sample/android/app/build.gradle @@ -1,154 +1,121 @@ apply plugin: "com.android.application" - -import com.android.build.OutputFile +apply plugin: "org.jetbrains.kotlin.android" +apply plugin: "com.facebook.react" /** - * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets - * and bundleReleaseJsAndAssets). - * These basically call `react-native bundle` with the correct arguments during the Android build - * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the - * bundle directly from the development server. Below you can see all the possible configurations - * and their defaults. If you decide to add a configuration block, make sure to add it before the - * `apply from: "../../node_modules/react-native/react.gradle"` line. - * - * project.ext.react = [ - * // the name of the generated asset file containing your JS bundle - * bundleAssetName: "index.android.bundle", - * - * // the entry file for bundle generation - * entryFile: "index.android.js", - * - * // whether to bundle JS and assets in debug mode - * bundleInDebug: false, - * - * // whether to bundle JS and assets in release mode - * bundleInRelease: true, - * - * // whether to bundle JS and assets in another build variant (if configured). - * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants - * // The configuration property can be in the following formats - * // 'bundleIn${productFlavor}${buildType}' - * // 'bundleIn${buildType}' - * // bundleInFreeDebug: true, - * // bundleInPaidRelease: true, - * // bundleInBeta: true, - * - * // the root of your project, i.e. where "package.json" lives - * root: "../../", - * - * // where to put the JS bundle asset in debug mode - * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", - * - * // where to put the JS bundle asset in release mode - * jsBundleDirRelease: "$buildDir/intermediates/assets/release", - * - * // where to put drawable resources / React Native assets, e.g. the ones you use via - * // require('./image.png')), in debug mode - * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", - * - * // where to put drawable resources / React Native assets, e.g. the ones you use via - * // require('./image.png')), in release mode - * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", - * - * // by default the gradle tasks are skipped if none of the JS files or assets change; this means - * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to - * // date; if you have any other folders that you want to ignore for performance reasons (gradle - * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ - * // for example, you might want to remove it from here. - * inputExcludes: ["android/**", "ios/**"], - * - * // override which node gets called and with what additional arguments - * nodeExecutableAndArgs: ["node"] - * - * // supply additional arguments to the packager - * extraPackagerArgs: [] - * ] + * This is the configuration block to customize your React Native Android app. + * By default you don't need to apply any configuration, just uncomment the lines you need. */ +react { + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '../..' + // root = file("../../") + // The folder where the react-native NPM package is. Default is ../../node_modules/react-native + // reactNativeDir = file("../../node_modules/react-native") + // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen + // codegenDir = file("../../node_modules/@react-native/codegen") + // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js + // cliFile = file("../../node_modules/react-native/cli.js") -apply from: "../../node_modules/react-native/react.gradle" + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. By default is just 'debug'. + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + // debuggableVariants = ["liteDebug", "prodDebug"] + + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + // + // The command to run when bundling. By default is 'bundle' + // bundleCommand = "ram-bundle" + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle + // bundleAssetName = "MyApplication.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' + // entryFile = file("../js/MyApplication.android.js") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] + + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' + // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" + // + // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" + // hermesFlags = ["-O", "-output-source-map"] + + /* Autolinking */ + autolinkLibrariesWithApp() +} /** - * Set this to true to create two separate APKs instead of one: - * - An APK that only works on ARM devices - * - An APK that only works on x86 devices - * The advantage is the size of the APK is reduced by about 4MB. - * Upload all the APKs to the Play Store and people will download - * the correct one based on the CPU architecture of their device. + * Set this to true to Run Proguard on Release builds to minify the Java bytecode. */ -def enableSeparateBuildPerCPUArchitecture = false +def enableProguardInReleaseBuilds = false /** - * Run Proguard to shrink the Java bytecode in release builds. + * The preferred build flavor of JavaScriptCore (JSC) + * + * For example, to use the international variant, you can use: + * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. */ -def enableProguardInReleaseBuilds = false +def jscFlavor = 'org.webkit:android-jsc:+' android { - compileSdkVersion 28 - buildToolsVersion "28.0.3" + ndkVersion rootProject.ext.ndkVersion + buildToolsVersion rootProject.ext.buildToolsVersion + compileSdk rootProject.ext.compileSdkVersion + namespace "com.mparticlesample" defaultConfig { applicationId "com.mparticlesample" - minSdkVersion 16 - targetSdkVersion 28 + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 versionName "1.0" - ndk { - abiFilters "armeabi-v7a", "x86" - } } - splits { - abi { - reset() - enable enableSeparateBuildPerCPUArchitecture - universalApk false // If true, also generate a universal APK - include "armeabi-v7a", "x86" + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' } } buildTypes { + debug { + signingConfig signingConfigs.debug + } release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + signingConfig signingConfigs.debug minifyEnabled enableProguardInReleaseBuilds proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" } } - // applicationVariants are e.g. debug, release - applicationVariants.all { variant -> - variant.outputs.each { output -> - // For each separate APK per architecture, set a unique version code as described here: - // http://tools.android.com/tech-docs/new-build-system/user-guide/apk-splits - def versionCodes = ["armeabi-v7a":1, "x86":2] - def abi = output.getFilter(OutputFile.ABI) - if (abi != null) { // null for the universal-debug, universal-release variants - output.versionCodeOverride = - versionCodes.get(abi) * 1048576 + defaultConfig.versionCode - } - } - } } dependencies { - implementation project(':react-native-mparticle') - implementation fileTree(dir: "libs", include: ["*.jar"]) - implementation "com.facebook.react:react-native:+" // From node_modules + // The version of react-native is set by the React Native Gradle Plugin + implementation("com.facebook.react:react-android") + implementation("com.mparticle:android-core:5.71.0") + implementation("com.mparticle:android-rokt-kit:5.71.0") - // - // In your app, you should include mParticle core like this: - // - // compile "com.mparticle.android-core:REPLACEME" - // - // (See https://github.com/mparticle/mparticle-android-sdk for the latest version) - // - implementation "com.mparticle:android-core:5.+" - - // - // And, if you want to include kits, you can do so as follows: - // - // compile 'com.mparticle:android-example-kit:REPLACEME' - // -} - -// Run this once to be able to run the application with BUCK -// puts all compile dependencies into folder libs for BUCK to use -task copyDownloadableDepsToLibs(type: Copy) { - from configurations.compile - into 'libs' + if (hermesEnabled.toBoolean()) { + implementation("com.facebook.react:hermes-android") + } else { + implementation jscFlavor + } } diff --git a/sample/android/app/debug.keystore b/sample/android/app/debug.keystore new file mode 100644 index 0000000..364e105 Binary files /dev/null and b/sample/android/app/debug.keystore differ diff --git a/sample/android/app/proguard-rules.pro b/sample/android/app/proguard-rules.pro index 48361a9..11b0257 100644 --- a/sample/android/app/proguard-rules.pro +++ b/sample/android/app/proguard-rules.pro @@ -8,59 +8,3 @@ # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} - -# Disabling obfuscation is useful if you collect stack traces from production crashes -# (unless you are using a system that supports de-obfuscate the stack traces). --dontobfuscate - -# React Native - -# Keep our interfaces so they can be used by other ProGuard rules. -# See http://sourceforge.net/p/proguard/bugs/466/ --keep,allowobfuscation @interface com.facebook.proguard.annotations.DoNotStrip --keep,allowobfuscation @interface com.facebook.proguard.annotations.KeepGettersAndSetters --keep,allowobfuscation @interface com.facebook.common.internal.DoNotStrip - -# Do not strip any method/class that is annotated with @DoNotStrip --keep @com.facebook.proguard.annotations.DoNotStrip class * --keep @com.facebook.common.internal.DoNotStrip class * --keepclassmembers class * { - @com.facebook.proguard.annotations.DoNotStrip *; - @com.facebook.common.internal.DoNotStrip *; -} - --keepclassmembers @com.facebook.proguard.annotations.KeepGettersAndSetters class * { - void set*(***); - *** get*(); -} - --keep class * extends com.facebook.react.bridge.JavaScriptModule { *; } --keep class * extends com.facebook.react.bridge.NativeModule { *; } --keepclassmembers,includedescriptorclasses class * { native ; } --keepclassmembers class * { @com.facebook.react.uimanager.UIProp ; } --keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactProp ; } --keepclassmembers class * { @com.facebook.react.uimanager.annotations.ReactPropGroup ; } - --dontwarn com.facebook.react.** - -# okhttp - --keepattributes Signature --keepattributes *Annotation* --keep class okhttp3.** { *; } --keep interface okhttp3.** { *; } --dontwarn okhttp3.** - -# okio - --keep class sun.misc.Unsafe { *; } --dontwarn java.nio.file.* --dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement --dontwarn okio.** diff --git a/sample/android/app/src/debug/AndroidManifest.xml b/sample/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..eb98c01 --- /dev/null +++ b/sample/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/sample/android/app/src/main/AndroidManifest.xml b/sample/android/app/src/main/AndroidManifest.xml index b9d8a71..e5320eb 100644 --- a/sample/android/app/src/main/AndroidManifest.xml +++ b/sample/android/app/src/main/AndroidManifest.xml @@ -1,31 +1,28 @@ - + - - - + android:roundIcon="@mipmap/ic_launcher_round" + android:allowBackup="false" + android:theme="@style/AppTheme" + android:networkSecurityConfig="@xml/network_security_config" + android:supportsRtl="true"> + android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|screenSize|smallestScreenSize|uiMode" + android:launchMode="singleTask" + android:windowSoftInputMode="adjustResize" + android:exported="true"> - - + diff --git a/sample/android/app/src/main/java/com/mparticlesample/MainActivity.java b/sample/android/app/src/main/java/com/mparticlesample/MainActivity.java deleted file mode 100644 index 708075a..0000000 --- a/sample/android/app/src/main/java/com/mparticlesample/MainActivity.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.mparticlesample; - -import com.facebook.react.ReactActivity; - -public class MainActivity extends ReactActivity { - - /** - * Returns the name of the main component registered from JavaScript. - * This is used to schedule rendering of the component. - */ - @Override - protected String getMainComponentName() { - return "MParticleSample"; - } -} diff --git a/sample/android/app/src/main/java/com/mparticlesample/MainActivity.kt b/sample/android/app/src/main/java/com/mparticlesample/MainActivity.kt new file mode 100644 index 0000000..a1c587f --- /dev/null +++ b/sample/android/app/src/main/java/com/mparticlesample/MainActivity.kt @@ -0,0 +1,22 @@ +package com.mparticlesample + +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +class MainActivity : ReactActivity() { + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + override fun getMainComponentName(): String = "MParticleSample" + + /** + * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] + * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] + */ + override fun createReactActivityDelegate(): ReactActivityDelegate = + DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) +} diff --git a/sample/android/app/src/main/java/com/mparticlesample/MainApplication.java b/sample/android/app/src/main/java/com/mparticlesample/MainApplication.java deleted file mode 100644 index 59ab70e..0000000 --- a/sample/android/app/src/main/java/com/mparticlesample/MainApplication.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.mparticlesample; - -import android.app.Application; -import android.util.Log; - -import com.facebook.react.ReactApplication; -import com.mparticle.MParticle; -import com.mparticle.identity.IdentityApiRequest; -import com.mparticle.react.MParticlePackage; -import com.facebook.react.ReactInstanceManager; -import com.facebook.react.ReactNativeHost; -import com.facebook.react.ReactPackage; -import com.facebook.react.shell.MainReactPackage; -import com.facebook.soloader.SoLoader; - -import java.util.Arrays; -import java.util.List; - -import com.mparticle.MParticleOptions; -import com.mparticle.identity.BaseIdentityTask; - -public class MainApplication extends Application implements ReactApplication { - - private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { - @Override - public boolean getUseDeveloperSupport() { - return BuildConfig.DEBUG; - } - - @Override - protected List getPackages() { - return Arrays.asList( - new MainReactPackage(), - new MParticlePackage() - ); - } - }; - - @Override - public ReactNativeHost getReactNativeHost() { - return mReactNativeHost; - } - - @Override - public void onCreate() { - super.onCreate(); - - IdentityApiRequest.Builder identityRequest = IdentityApiRequest.withEmptyUser(); - - MParticleOptions options = MParticleOptions.builder(this) - .credentials("us1-352af4d005e49047a7bcc78281f33e9c","flR34mIajnAA5F-Ouha7JQF5v0JqFUfo_QjJtM_16VESU2hS0ikp3hRILG70-aBk") - .logLevel(MParticle.LogLevel.VERBOSE) - .identify(identityRequest.build()) - .build(); - - MParticle.start(options); - SoLoader.init(this, /* native exopackage */ false); - } -} diff --git a/sample/android/app/src/main/java/com/mparticlesample/MainApplication.kt b/sample/android/app/src/main/java/com/mparticlesample/MainApplication.kt new file mode 100644 index 0000000..33d5849 --- /dev/null +++ b/sample/android/app/src/main/java/com/mparticlesample/MainApplication.kt @@ -0,0 +1,56 @@ +package com.mparticlesample + +import android.app.Application +import com.facebook.react.PackageList +import com.facebook.react.ReactApplication +import com.facebook.react.ReactHost +import com.facebook.react.ReactNativeHost +import com.facebook.react.ReactPackage +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load +import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost +import com.facebook.react.defaults.DefaultReactNativeHost +import com.facebook.react.soloader.OpenSourceMergedSoMapping +import com.facebook.soloader.SoLoader +import com.mparticle.MParticle +import com.mparticle.MParticleOptions +import com.mparticle.identity.IdentityApiRequest +import com.mparticle.react.MParticlePackage + +class MainApplication : Application(), ReactApplication { + + override val reactNativeHost: ReactNativeHost = + object : DefaultReactNativeHost(this) { + override fun getPackages(): List = + PackageList(this).packages.apply { + add(MParticlePackage()) + } + + override fun getJSMainModuleName(): String = "index" + + override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG + + override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED + } + + override val reactHost: ReactHost + get() = getDefaultReactHost(applicationContext, reactNativeHost) + + override fun onCreate() { + super.onCreate() + SoLoader.init(this, OpenSourceMergedSoMapping) + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + load() + } + val identityRequest = IdentityApiRequest.withEmptyUser() + + val options = MParticleOptions.builder(this) + .credentials("REPLACE ME","REPLACE ME") + .logLevel(MParticle.LogLevel.VERBOSE) + .identify(identityRequest.build()) + .build() + + MParticle.start(options) + } +} diff --git a/sample/android/app/src/main/res/drawable/rn_edit_text_material.xml b/sample/android/app/src/main/res/drawable/rn_edit_text_material.xml new file mode 100644 index 0000000..5c25e72 --- /dev/null +++ b/sample/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + diff --git a/sample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/sample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index cde69bc..a2f5908 100644 Binary files a/sample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and b/sample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/sample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/sample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png new file mode 100644 index 0000000..1b52399 Binary files /dev/null and b/sample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ diff --git a/sample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/sample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index c133a0c..ff10afd 100644 Binary files a/sample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and b/sample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/sample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/sample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png new file mode 100644 index 0000000..115a4c7 Binary files /dev/null and b/sample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ diff --git a/sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png index bfa42f0..dcd3cd8 100644 Binary files a/sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and b/sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000..459ca60 Binary files /dev/null and b/sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ diff --git a/sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index 324e72c..8ca12fe 100644 Binary files a/sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and b/sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..8e19b41 Binary files /dev/null and b/sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ diff --git a/sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..b824ebd Binary files /dev/null and b/sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png new file mode 100644 index 0000000..4c19a13 Binary files /dev/null and b/sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ diff --git a/sample/android/app/src/main/res/values/styles.xml b/sample/android/app/src/main/res/values/styles.xml index 319eb0c..7ba83a2 100644 --- a/sample/android/app/src/main/res/values/styles.xml +++ b/sample/android/app/src/main/res/values/styles.xml @@ -1,8 +1,9 @@ - diff --git a/sample/android/app/src/main/res/xml/network_security_config.xml b/sample/android/app/src/main/res/xml/network_security_config.xml new file mode 100644 index 0000000..286ba79 --- /dev/null +++ b/sample/android/app/src/main/res/xml/network_security_config.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/sample/android/build.gradle b/sample/android/build.gradle index 7ffd27a..be23c00 100644 --- a/sample/android/build.gradle +++ b/sample/android/build.gradle @@ -1,27 +1,29 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - buildscript { + ext { + buildToolsVersion = "35.0.0" + minSdkVersion = 24 + compileSdkVersion = 35 + targetSdkVersion = 34 + ndkVersion = "26.1.10909125" + kotlinVersion = "1.9.25" + } repositories { - mavenCentral() google() + mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:3.2.1' + classpath("com.android.tools.build:gradle") + classpath("com.facebook.react:react-native-gradle-plugin") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") } } - allprojects { repositories { mavenLocal() - mavenCentral() google() - maven { - // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm - url "$rootDir/../node_modules/react-native/android" - } - maven { - url 'https://maven.google.com' - } + mavenCentral() } } + +apply plugin: "com.facebook.react.rootproject" diff --git a/sample/android/gradle.properties b/sample/android/gradle.properties index 1fd964e..9fb1566 100644 --- a/sample/android/gradle.properties +++ b/sample/android/gradle.properties @@ -9,12 +9,31 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 +# Default value: -Xmx512m -XX:MaxMetaspaceSize=256m +org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true -android.useDeprecatedNdk=true +# AndroidX package structure to make it clearer which packages are bundled with the +# Android operating system, and which are packaged with your app's APK +# https://developer.android.com/topic/libraries/support-library/androidx-rn +android.useAndroidX=true + +# Use this property to specify which architecture you want to build. +# You can also override it from the CLI using +# ./gradlew -PreactNativeArchitectures=x86_64 +reactNativeArchitectures=armeabi-v7a,arm64-v8a,x86,x86_64 + +# Use this property to enable support to the new architecture. +# This will allow you to use TurboModules and the Fabric render in +# your application. You should enable this flag either if you want +# to write custom TurboModules/Fabric components OR use libraries that +# are providing them. +newArchEnabled=false + +# Use this property to enable or disable the Hermes JS engine. +# If set to false, you will be using JSC instead. +hermesEnabled=true diff --git a/sample/android/gradle/wrapper/gradle-wrapper.jar b/sample/android/gradle/wrapper/gradle-wrapper.jar index b5166da..a4b76b9 100644 Binary files a/sample/android/gradle/wrapper/gradle-wrapper.jar and b/sample/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/sample/android/gradle/wrapper/gradle-wrapper.properties b/sample/android/gradle/wrapper/gradle-wrapper.properties index c79d854..79eb9d0 100644 --- a/sample/android/gradle/wrapper/gradle-wrapper.properties +++ b/sample/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ -#Tue Apr 03 15:57:13 EDT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip diff --git a/sample/android/gradlew b/sample/android/gradlew index 91a7e26..f5feea6 100755 --- a/sample/android/gradlew +++ b/sample/android/gradlew @@ -1,79 +1,130 @@ -#!/usr/bin/env bash +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum -warn ( ) { +warn () { echo "$*" -} +} >&2 -die ( ) { +die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac -# For Cygwin, ensure paths are in UNIX format before anything is touched. -if $cygwin ; then - [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` -fi - -# Attempt to set APP_HOME -# Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi -done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >&- -APP_HOME="`pwd -P`" -cd "$SAVED" >&- - CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -82,83 +133,120 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules -function splitJvmOpts() { - JVM_OPTS=("$@") -} -eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS -JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" -exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/sample/android/gradlew.bat b/sample/android/gradlew.bat index aec9973..9b42019 100644 --- a/sample/android/gradlew.bat +++ b/sample/android/gradlew.bat @@ -1,4 +1,22 @@ -@if "%DEBUG%" == "" @echo off +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -8,26 +26,30 @@ @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -35,54 +57,36 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail -:init -@rem Get command-line arguments, handling Windowz variants - -if not "%OS%" == "Windows_NT" goto win9xME_args -if "%@eval[2+2]" == "4" goto 4NT_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* -goto execute - -:4NT_args -@rem Get arguments from the 4NT Shell from JP Software -set CMD_LINE_ARGS=%$ - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/sample/android/settings.gradle b/sample/android/settings.gradle index 02f67e6..bdc49b7 100644 --- a/sample/android/settings.gradle +++ b/sample/android/settings.gradle @@ -1,5 +1,6 @@ +pluginManagement { includeBuild("../node_modules/@react-native/gradle-plugin") } +plugins { id("com.facebook.react.settings") } +extensions.configure(com.facebook.react.ReactSettingsExtension){ ex -> ex.autolinkLibrariesFromCommand() } rootProject.name = 'MParticleSample' -include ':react-native-mparticle' -project(':react-native-mparticle').projectDir = new File(rootProject.projectDir, '../../android') - include ':app' +includeBuild('../node_modules/@react-native/gradle-plugin') diff --git a/sample/app.json b/sample/app.json new file mode 100644 index 0000000..b51e9b3 --- /dev/null +++ b/sample/app.json @@ -0,0 +1,4 @@ +{ + "name": "MParticleSample", + "displayName": "MParticleSample" +} diff --git a/sample/babel.config.js b/sample/babel.config.js new file mode 100644 index 0000000..f7b3da3 --- /dev/null +++ b/sample/babel.config.js @@ -0,0 +1,3 @@ +module.exports = { + presets: ['module:@react-native/babel-preset'], +}; diff --git a/sample/build b/sample/build index fb7be50..697e574 100755 --- a/sample/build +++ b/sample/build @@ -1,4 +1,4 @@ cp -r ../android node_modules/react-native-mparticle -cp -r ../js node_modules/react-native-mparticle +cp -r ../lib node_modules/react-native-mparticle rm -rf node_modules/react-native-mparticle/ios -cp -r ../ios node_modules/react-native-mparticle \ No newline at end of file +cp -r ../ios node_modules/react-native-mparticle diff --git a/sample/index.android.js b/sample/index.android.js deleted file mode 100644 index d1edcb3..0000000 --- a/sample/index.android.js +++ /dev/null @@ -1,218 +0,0 @@ -/** - * Sample React Native App - * https://github.com/facebook/react-native - * @flow - */ - -import React, { Component } from 'react'; -import { - AppRegistry, - StyleSheet, - Text, - View, - Button -} from 'react-native'; -import MParticle from 'react-native-mparticle' - - -export default class MParticleSample extends Component { - constructor(props) { - super(props); - this.state = {isShowingText: true, - optedOut: true, - attributionResults: "{value: no attributionResults}", - session: '', - isKitActive: true}; - - this._toggleOptOut = this._toggleOptOut.bind(this) - this._getAttributionResults = this._getAttributionResults.bind(this) - this._isKitActive = this._isKitActive.bind(this) - this.render = this.render.bind(this) - - // Example Login - var request = new MParticle.IdentityRequest(); - request.email = 'testing1@gmail.com'; - request.customerId = "123" - MParticle.Identity.login(request, (error, userId, previousUserId) => { - if (error) { - console.debug(error); - } - var previousUser = new MParticle.User(previousUserId); - previousUser.getFirstSeen((firstSeen) => { - previousUser.getLastSeen((lastSeen) => { - var aliasRequest = new MParticle.AliasRequest() - .sourceMpid(previousUser.getMpid()) - .destinationMpid(userId) - .startTime(firstSeen - 1000) - .endTime(lastSeen - 1000) - console.log("AliasRequest = " + JSON.stringify(aliasRequest)); - MParticle.Identity.aliasUsers(aliasRequest, (success, error) => { - if (error) { - console.log("Alias error = " + error); - } - console.log("Alias result: " + success); - }); - - var aliasRequest2 = new MParticle.AliasRequest() - .sourceMpid(previousUser.getMpid()) - .destinationMpid(userId) - console.log("AliasRequest2 = " + JSON.stringify(aliasRequest2)); - MParticle.Identity.aliasUsers(aliasRequest2, (success, error) => { - if (error) { - console.log("Alias 2 error = " + error); - } - console.log("Alias 2 result: " + success); - }); - }) - }) - - var user = new MParticle.User(userId); - console.debug("User Attributes = " + user.userAttributes); - MParticle.Identity.logout({}, (error, userId) => { - if (error) { - console.debug("Logout error" + error); - } - var request = new MParticle.IdentityRequest(); - request.email = 'testing2@gmail.com'; - request.customerId = '456' - MParticle.Identity.modify(request, (error) => { - if (error) { - console.debug("Modify error = " + error) - } - }); - }); - }); - - var i = 0; - // Toggle the state every few seconds, 10 times - var intervalId = setInterval(() => { - MParticle.logEvent('Test event', MParticle.EventType.Other, { 'Test key': 'Test value', 'Test Boolean': true, 'Test Int': 1235, 'Test Double': 123.123 }) - this.setState((previousState) => { - return {isShowingText: !previousState.isShowingText} - }) - MParticle.Identity.getCurrentUser((currentUser) => { - currentUser.setUserTag('regular'); - }); - var request = new MParticle.IdentityRequest(); - request.email = 'testing1@gmail.com'; - request.customerId = "vlknasdlknv" - request.setUserIdentity('12345', MParticle.UserIdentityType.Alias); - - const product = new MParticle.Product('Test product for cart', '1234', 19.99) - const transactionAttributes = new MParticle.TransactionAttributes('Test transaction id') - const event = MParticle.CommerceEvent.createProductActionEvent(MParticle.ProductActionType.AddToCart, [product], transactionAttributes) - - MParticle.logCommerceEvent(event) - MParticle.logPushRegistration("afslibvnoewtibnsgb", "vdasvadsdsav"); - console.debug("interval") - i++; - if (i >= 10) { - clearInterval(intervalId); - } - }, 5000); - } - - componentDidMount() { - MParticle.getSession(session => this.setState({ session })) - } - - _toggleOptOut() { - MParticle.getOptOut((optedOut) => { - MParticle.setOptOut(!optedOut) - console.debug("setOptout" + optedOut) - this.setState((previousState) => { - console.debug("returning state") - return { optedOut: !optedOut }; - }) - }) - } - - _getAttributionResults() { - MParticle.getAttributions((_attributionResults) => { - this.setState((previousState) => { - return {attributionResults: _attributionResults} - }) - }) - } - - _isKitActive() { - MParticle.isKitActive(80, (active) => { - this.setState((previousState) => { - return {isKitActive: active} - }) - }) - } - - _incrementAttribute() { - MParticle.Identity.getCurrentUser((currentUser) => { - currentUser.incrementUserAttribute("incrementedAttribute", 1) - }) - } - - render() { - let display = this.state.isShowingText ? 'Sending Event' : ' ' - let optedOut = this.state.optedOut ? 'true' : 'false' - let optAction = this.state.optedOut ? 'In' : 'Out' - let kitActive = this.state.isKitActive ? 'true' : 'false' - return ( - - - Welcome to React Native! {display} - - - Opted Out = {optedOut} - -